I am trying to setup project in React with Server Side Rendering and PWA.
I have setup React with Server Side Rendering but when I am trying to add PWA I am not able to do.
This is my project structure.
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
client: './src/client.js',
bundle: './src/bundle.js'
},
output: {
path: path.resolve(__dirname, 'assets'),
filename: "[name].js"
},
module: {
rules: [
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }
]
}
}
package.json
{
"name": "react-poc",
"version": "1.1.0",
"description": "react-poc",
"main": "index.js",
"scripts": {
"start": "yarn build && node index.js",
"build": "webpack --config webpack.config.js"
},
"author": "Piyush Jain",
"license": "MIT",
"dependencies": {
"#babel/register": "^7.8.6",
"express": "^4.17.1",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"#babel/cli": "^7.8.4",
"#babel/core": "^7.8.7",
"#babel/preset-env": "^7.8.7",
"#babel/preset-react": "^7.8.3",
"babel-loader": "^8.0.6",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
}
In my src folder i created a file worker.js
// Flag for enabling cache in production
var doCache = false;
var CACHE_NAME = 'pwa-app-cache';
// Delete old caches
self.addEventListener('activate', event => {
const currentCachelist = [CACHE_NAME];
event.waitUntil(
caches.keys()
.then(keyList =>
Promise.all(keyList.map(key => {
if (!currentCachelist.includes(key)) {
return caches.delete(key);
}
}))
)
);
});
// This triggers when user starts the app
self.addEventListener('install', function(event) {
if (doCache) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
fetch('manifest.json')
.then(response => {
response.json();
})
.then(assets => {
// We will cache initial page and the main.js
// We could also cache assets like CSS and images
const urlsToCache = [
'/',
assets['bundle.js']
];
cache.addAll(urlsToCache);
})
})
);
}
});
// Here we intercept request and serve up the matching files
self.addEventListener('fetch', function(event) {
if (doCache) {
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
}
});
then I added this in html
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('worker.js').then(function(registration) {
console.log('Worker registration successful', registration.scope);
}, function(err) {
console.log('Worker registration failed', err);
}).catch(function(err) {
console.log(err);
});
});
} else {
console.log('Service Worker is not supported by browser.');
}
</script>
But when I am trying to run app I am getting below error.
Worker registration failed TypeError: Failed to register a ServiceWorker for scope ('http://localhost:3000/') with script ('http://localhost:3000/worker.js'): A bad HTTP response code (404) was received when fetching the script.
Related
I am trying to seed my db and this issue is preventing that. It keeps saying "Inventory.create is not a function
at seed". I am not sure if this is a syntactical issue, a logistical problem or even a dependency issue so please point me in the wrong direction.
The tech stack that I am using is Express, Node.js, Sequelize, PostgreSQL
My files are structured as such:
--script
-seed.js
--server
-api
-db
-Model.js
-index.js
-db.js
-app.js
-index.js
Model.js
const db = require('./db');
const Model = db.define('model', {
name: {
type: Sequelize.STRING,
allowNull: false,
},
total: {
type: Sequelize.FLOAT,
allowNull: false,
},
})
module.export = Model;
index.js
const db = require('./db')
const Inventory = require('./Inventory')
module.exports = {
db,
models: {
Inventory,
},
}
db.js
const Sequelize = require('sequelize')
const pkg = require('../../package.json')
const databaseName = pkg.name + (process.env.NODE_ENV === 'test' ? '-test' : '')
if(process.env.LOGGING === 'true'){
delete config.logging
}
if(process.env.DATABASE_URL){
config.dialectOptions = {
ssl: {
rejectUnauthorized: false
}
};
}
const db = new Sequelize(
process.env.DATABASE_URL || `postgres://localhost:5432/${databaseName}`, {
logging: false,
})
module.exports = db
seed.js
'use strict'
const {db, models: {Model}} = require('../server/db')
async function seed() {
await db.sync({ force: true })
console.log('db synced!')
// Creating Inventory
const stock = await Promise.all([
Model.create({ name: 'First', amount: 200 }),
Model.create({ name: 'Second', amount: 200 }),
])
console.log(`seeded successfully`)
}
async function runSeed() {
console.log('seeding...')
try {
await seed()
} catch (err) {
console.error(err)
process.exitCode = 1
} finally {
console.log('closing db connection')
await db.close()
console.log('db connection closed')
}
}
if (module === require.main) {
runSeed()
}
module.exports = seed
I included this just in case
package.json
{
"name": "ShopifyInventory",
"version": "1.0",
"description": "Simple backend heavy app for inventory management",
"main": "app.js",
"scripts": {
"build": "webpack",
"build:dev": "npm run build -- --watch --mode=development",
"seed": "node script/seed.js",
"start": "node server"
},
"dependencies": {
"axios": "^0.21.1",
"bcrypt": "^5.0.0",
"compression": "^1.7.3",
"express": "^4.18.1",
"history": "^4.9.0",
"jsonwebtoken": "^8.5.1",
"morgan": "^1.9.1",
"pg": "^8.7.3",
"pg-hstore": "^2.3.4",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-router-dom": "^6.3.0",
"sequelize": "^6.19.2"
},
"author": "Galilior :)",
"devDependencies": {
"#babel/core": "^7.17.12",
"#babel/preset-react": "^7.17.12",
"babel-loader": "^8.2.5",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
}
}
While developing node api, I have a problem when building a production bundle with webpack. In webpack config, if mode is set to 'development', everything works fine. If mode is set to 'production', running node bundle.js, gives me error which does not say much. What could be the problem or how should I debug it.
Error
at c.<anonymous> (/Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:747025)
at c.<anonymous> (/Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:217821)
at c._callback (/Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:217609)
at c.l.end (/Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:434863)
at /Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:255978
at Array.forEach (<anonymous>)
at /Users/sten/Sites/Projects/Farmi/API/New/dist/bundle.js:2:255955
at processTicksAndRejections (node:internal/process/task_queues:78:11)
My webpack production config:
const path = require('path');
module.exports = {
mode: 'production',
target: 'node',
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: 'babel-loader',
},
],
},
output: {
path: path.resolve(__dirname, 'dist/'),
filename: 'bundle.js',
},
};
package.json:
{
"name": "API",
"version": "1.0.0",
"description": "API",
"main": "index.js",
"author": "API",
"license": "MIT",
"dependencies": {
"#koa/router": "^10.1.1",
"axios": "^0.27.2",
"file-extension": "^4.0.5",
"get-4byte-chars": "^0.1.0",
"koa": "^2.13.4",
"lodash": "^4.17.21",
"mime-types": "^2.1.35",
"mysql": "^2.18.1",
"pm3": "^0.0.0",
"unique-filename": "^1.1.1",
"winston": "^3.7.2"
},
"devDependencies": {
"#babel/core": "^7.17.9",
"#babel/plugin-transform-runtime": "^7.17.10",
"#babel/preset-env": "^7.16.11",
"babel-loader": "^8.2.5",
"nodemon-webpack-plugin": "^4.7.1",
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
},
"scripts": {
"dev": "webpack --config=webpack.config.dev.js --watch",
"build": "webpack --config=webpack.config.prod.js",
"start": "node ./dist/bundle.js"
}
}
Found the problem by eliminating blocks of code. Looks like webpack breaks Node's MySQL package while minifying.
Here's a reference:
https://github.com/serverless/serverless/issues/5946
Removed the minification as suggested and it works.
To get the error message from mysql I had to wrap the code inside promise into try / catch block, even tough I'm rejecting the promise with err and that should be caught by the try / catch block calling the function _dbQuery ... or not ?
Original version:
const _dbQuery = async (queryString, values = null) => {
return new Promise((resolve, reject) => {
const connection = mysql.createConnection({
...configuration.mysql,
});
connection.connect((err) => {
if (err) reject(new Error(err.sqlMessage));
});
if (values !== null) {
connection.query(queryString, values, (err, res, fields) => {
if (err) reject(new Error(err.sqlMessage));
resolve(res);
connection.end();
});
} else {
connection.query(queryString, (err, res, fields) => {
if (err) reject(err.sqlMessage);
resolve(res);
connection.end();
});
}
})
};
Modified which gave me the error PROTOCOL_INCORRECT_PACKET_SEQUENCE:
const _dbQuery = async (queryString, values = null) => {
return new Promise((resolve, reject) => {
try {
const connection = mysql.createConnection({
...configuration.mysql,
});
connection.connect((err) => {
if (err) reject(new Error(err.sqlMessage));
});
if (values !== null) {
connection.query(queryString, values, (err, res, fields) => {
if (err) reject(new Error(err.sqlMessage));
resolve(res);
connection.end();
});
} else {
connection.query(queryString, (err, res, fields) => {
if (err) reject(new Error(err.sqlMessage));
resolve(res);
connection.end();
});
}
} catch (err) {
throw err;
}
});
};
My project has 2 folders: client(next.js with custom server) and server(node.js).
I have uploaded it in a Ubuntu 20.04 server and build next.js project in client folder. it works.
I have recently changed some pages of next.js and uploaded to client folder by "sudo git pull".
Now I would like to run "npm run build" to build next.js again, but it gives Error:
warn - No ESLint configuration detected. Run next lint to begin setup
Build error occurred
Error: > Build directory is not writeable. https://nextjs.org/docs/messages/build-dir-not-writeable
at /home/skadmin/client/node_modules/next/dist/build/index.js:275:19
at async Span.traceAsyncFn (/home/skadmin/client/node_modules/next/dist/telemetry/trace/trace.js:60:20)
at async Object.build [as default] (/home/skadmin/client/node_modules/next/dist/build/index.js:77:25)
info - Creating an optimized production build
==========My Custom server is:
'''
const express = require('express')
const next = require('next')
const { createProxyMiddleware } = require('http-proxy-middleware')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app
.prepare()
.then(() => {
const server = express()
// apply proxy in dev mode
if (dev) {
server.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:8000',
changeOrigin: true,
})
)
}
server.all('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:8000')
})
})
.catch((err) => {
console.log('Error', err)
})
'''
=======================package.json is=>:
'''
{
"name": "client",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#ant-design/icons": "^4.5.0",
"#glidejs/glide": "^3.4.1",
"#material-ui/core": "^4.11.4",
"#material-ui/icons": "^4.11.2",
"#persian-tools/persian-tools": "^3.0.1",
"antd": "^4.13.1",
"axios": "^0.21.4",
"express": "^4.17.1",
"http-proxy-middleware": "^2.0.0",
"lodash": "^4.17.21",
"moment-jalaali": "^0.9.2",
"multer": "^1.4.4",
"next": "^11.1.3",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-icons": "^4.2.0",
"react-image-file-resizer": "^0.4.7",
"react-markdown": "^6.0.2",
"react-scroll": "^1.8.2",
"react-toastify": "^7.0.4",
"reactstrap": "^8.9.0",
"swiper": "^7.4.1"
}
}
'''
Please help me, what should I do?
I am trying to create a seeder file in nestjs, the problem is when I run the project using start:dev, somehow nestjs also start seed.ts file with main.ts file. How can I make nestjs not start seed file when I run the project either on prod/dev but seed must be called only when I run the seed script.
Here is the seed.ts code
import { NestFactory } from '#nestjs/core'
import { Logger } from '#nestjs/common'
import { SeederModule } from './database/seeder.module'
import { Seeder } from './database/seeder'
async function bootstrap() {
NestFactory.createApplicationContext(SeederModule)
.then((appContext) => {
const logger = appContext.get(Logger)
const seeder = appContext.get(Seeder)
seeder
.seedRoles()
.then(() => {
logger.debug('Seeding Roles complete!')
})
.catch((error) => {
logger.error('Seeding Roles failed!')
throw error
})
seeder
.seedAdmin()
.then(() => {
logger.debug('Seeding Admin complete!')
})
.catch((error) => {
logger.error('Seeding Admin failed!')
throw error
})
.finally(() => appContext.close())
})
.catch((error) => {
throw error
})
}
bootstrap()
Here is the main.ts file for nestJS
import { Logger, ValidationPipe } from '#nestjs/common'
import { NestFactory } from '#nestjs/core'
import { AppModule } from './modules/app/app.module'
async function bootstrap() {
const app = await NestFactory.create(AppModule)
app.enableCors()
const port = process.env.PORT || 3000
app.useGlobalPipes(new ValidationPipe())
await app
.listen(port)
.then(() => {
Logger.log(`App listening on port ${port}`)
})
.catch((err) => {
Logger.log(`Error while connecting to port ${port}`, err)
})
}
bootstrap()
And here is the package.json file
{
"name": "jugg-website",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "link-module-alias && nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"seed": "ts-node -r tsconfig-paths/register src/seed.ts"
},
"dependencies": {
"#nestjs/common": "^7.6.13",
"#nestjs/core": "^7.6.13",
"#nestjs/jwt": "^7.2.0",
"#nestjs/passport": "^7.1.5",
"#nestjs/platform-express": "^7.6.13",
"#nestjs/typeorm": "^7.1.5",
"class-transformer": "^0.4.0",
"class-validator": "^0.13.1",
"config": "^3.3.6",
"link-module-alias": "^1.2.0",
"passport": "^0.4.1",
"pg": "^8.5.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.6.6",
"typeorm": "^0.2.32"
},
"devDependencies": {
"#nestjs/cli": "^7.5.6",
"#nestjs/schematics": "^7.2.7",
"#nestjs/testing": "^7.6.13",
"#types/express": "^4.17.11",
"#types/jest": "^26.0.20",
"#types/node": "^14.14.31",
"#types/supertest": "^2.0.10",
"#typescript-eslint/eslint-plugin": "^4.15.2",
"#typescript-eslint/parser": "^4.15.2",
"eslint": "^7.20.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"jest": "^26.6.3",
"prettier": "^2.2.1",
"supertest": "^6.1.3",
"ts-jest": "^26.5.2",
"ts-loader": "^8.0.17",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"typescript": "^4.1.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
you can try setting KeepConnectionAlive option to true in typeOrm
configuration in the app.module file
https://github.com/nestjs/typeorm/issues/61
I was getting this error when running e2e tests. I found that the default nestjs template sets up the e2e tests with a beforeEach like this:
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
But since I had more than one test in the spec file (I'm a newbie to node.js dev so not sure whether this is the right thing to do or not, but regardless...), what was happening was the app was being initialised once per test which meant it was attempting to create multiple connections to the database.
The solution was quite simple. Change the beforeEach to beforeAll
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
And don't forget to close the app when the tests are done
afterAll(async () => {
await app.close();
});
In my case, the problem was in my main.ts file. I ran my module with the TypeORM twice without noticing, because I was trying access my ConfigService so that I could use environment variables for some other service than my TypeORM database connection.
main.ts that causes the error:
...
async function bootstrap(): Promise<void> {
// the next line actually initiates a DB connection
const appContext = await NestFactory.createApplicationContext(MailModule);
const configService = appContext.get<ConfigService>(ConfigService);
// by now, we already established a DB connection, so trying to
// reinstantiate the connection will cause the error
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
MailModule,
{
transport: Transport.REDIS,
options: {
port: configService.get<number>('REDIS.PORT'),
host: configService.get<string>('REDIS.HOST'),
},
},
);
await app.listen();
}
bootstrap();
The solution:
...
async function bootstrap(): Promise<void> {
const appContext = await NestFactory.createApplicationContext(MailModule);
// we close the redundant connection before we mount the app.
await getConnection('default').close();
const configService = appContext.get<ConfigService>(ConfigService);
const app = await NestFactory.createMicroservice<MicroserviceOptions>(
MailModule,
{
transport: Transport.REDIS,
options: {
port: configService.get<number>('REDIS.PORT'),
host: configService.get<string>('REDIS.HOST'),
},
},
);
await app.listen();
}
bootstrap();
I have this code:
import "reflect-metadata";
// import { ApolloServer } from "apollo-server-express";
const ApolloServer = require("apollo-server-express");
const express = require("express");
const buildSchema = require("type-graphql");
const createConnection = require("typeorm");
const cors = require("cors");
import { UserResolvers } from "./graphql/user/UserResolver";
import { UserModel } from "./graphql/user/UserModel";
import { TodoItemModel } from "./graphql/todoItem/TodoItemModel";
const app = express();
app.use(cors());
(async () => {
const schema = await buildSchema({
resolvers: [UserResolvers],
});
const server = new ApolloServer({ schema });
const { host, port, username, password, database } = process.env;
console.log({ host }, { port }, { username }, { password }, { database });
app.get("/user");
server.applyMiddleware({ app });
await createConnection({
type: "mysql",
host,
port: parseInt(port),
username,
password,
database,
entities: [UserModel, TodoItemModel],
synchronize: true,
logging: true,
})
app.listen(4000, () => {
console.log(
`🚀 Server ready at http://localhost:4000${server.graphqlPath}`
);
});
})();
And here's my webpack.config
const path = require("path");
module.exports = {
entry: "./src/index.ts",
module: {
rules: [
{
test: /\.ts?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
},
resolve: {
extensions: [".ts"],
},
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
mode: "development",
};
And I build it using:
webpack --config webpack.config.js
The problem is I'm getting:
ERROR in ./node_modules/apollo-server-express/dist/index.js 27:21-46
Module not found: Error: Can't resolve './ApolloServer' in '/home/aironside/Documents/private/todo-app-graphql/backend/node_modules/apollo-server-express/dist'
# ./src/index.ts 40:19-51
ERROR in ./node_modules/cors/lib/index.js 5:15-39
Module not found: Error: Can't resolve 'object-assign' in '/home/aironside/Documents/private/todo-app-graphql/backend/node_modules/cors/lib'
# ./src/index.ts 44:11-26
ERROR in ./node_modules/cors/lib/index.js 6:13-28
Module not found: Error: Can't resolve 'vary' in '/home/aironside/Documents/private/todo-app-graphql/backend/node_modules/cors/lib'
# ./src/index.ts 44:11-26
ERROR in ./node_modules/graphql-subscriptions/dist/index.js 3:22-48
Module not found: Error: Can't resolve './pubsub-engine' in '/home/aironside/Documents/private/todo-app-graphql/backend/node_modules/graphql-subscriptions/dist'
# ./node_modules/type-graphql/dist/index.js 11:30-62
# ./src/index.ts 42:18-41
... and other similar errors, as if I didn't have these modules installed (They are installed)
I tried import {} from, import x from, const x = require('x'), and const {} = require(). I keep getting the same error.
my package.json dependencies
"dependencies": {
"apollo-server-express": "^2.21.1",
"bcrypt": "^5.0.1",
"cors": "^2.8.5",
"express": "^4.17.1",
"type-graphql": "^1.1.1",
"typeorm": "^0.2.31"
},
"devDependencies": {
"#babel/core": "^7.13.10",
"#babel/preset-env": "^7.13.10",
"#types/bcrypt": "^3.0.0",
"#types/express": "^4.17.11",
"babel-loader": "^8.2.2",
"concurrently": "^6.0.0",
"nodemon": "^2.0.7",
"ts-loader": "^8.0.18",
"typescript": "^4.2.3",
"webpack": "^5.27.1",
"webpack-cli": "^4.5.0"
},
What am I missing?