Next.JS Hot Reload SSR - reactjs

I'm doing development on Next.JS, and every time I hot reload after making a modification of the codes, there seems to be some kind of a cache that causes Client side codes and Server side codes to be different.
Currently, I need to open a new window every time I save my codes, in order to see the updates.
Is there anything I can do so it auto reload to the latest codes available all the time?
I tried using helmet/nocache with no results.
const express = require('express')
const next = require('next')
//const routes = require('./routes')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const nocache = require('nocache') //added no cache
app.prepare()
.then(() => {
const server = express()
server.use(nocache()) //using no cache
server.get('/listing/:id', (req, res) => {
const actualPage = '/listing'
const queryParams = { id: req.params.id }
return app.render(req, res, actualPage, queryParams)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, '127.0.0.2', (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})

Related

How to resolve the Socket.io error "ERR_NAME_NOT_RESOLVED

When I run my MERN Stack project on my localhost and get my app's render page, when I click on a button in my app, that button does and displays nothing. When I inspect my client-side render page, I see the following error:polling.js:311 GET http://%22http/socket.io/?EIO=4&transport=polling&t=O7Mtvxd net::ERR_NAME_NOT_RESOLVED. I don't know what it means, I searched the meaning on the internet but without success. Here is my backend index.js file:
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
require("dotenv").config()
const app = express()
const http = require('http')
const server = http.createServer(app)
const io = require('socket.io')(server)
const UserRoutes = require('./routes/User')
const AuthRoutes = require('./routes/Auth')
const PostRoutes = require('./routes/Post')
const PORT = process.env.PORT || 5000
const {MONGODB_URI} = require("./config")
app.use(cors())
app.use(express.json())
app.use((req, res, next) => {
io.req = req
req.io = io
next()
})
app.use('/api/auth', AuthRoutes)
app.use('/api/user', UserRoutes)
app.use('/api/post', PostRoutes)
require('./socket')(io)
mongoose
.connect(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log('database connected')
server.listen(PORT, () => console.log(`server started on port ${PORT}`))
})
.catch((err) => console.log(err))
my backend socket.js file :
const User = require('./models/User')
const jwt = require('jsonwebtoken')
module.exports = (io) => {
io.on('connection', (socket) => {
if (io.req) {
socket.broadcast.emit('friend-login-status', { user_id: io.req.userId })
addSocketIdInDB(socket.id, io.req.userId)
socket.on('disconnect', () => {
socket.broadcast.emit('friend-logout-status', {
user_id: io.req.userId,
})
io.req.userId = null
})
}
})
}
async function addSocketIdInDB(socket_id, user_id) {
const user = await User.findById(user_id)
if (socket_id) {
user.socketId = socket_id
}
await user.save()
}
I looked on this question after this but without success. I work on Microsoft Edge .

change code from template engine to next js

How do I convert my app that is made with .pug to next app ? I have an app using .pug engine and I want to convert it into next.
This is the app.js but as I know next is different how do I do it? Because here my files are in views, and in views the files are in pages etc how do I do it? Is there any way or I have to code it all again?
const express = require('express');
const app = express();
const port = process.env.PORT || 3000;
const middleware = require('./middleware')
const path = require('path')
const bodyParser = require("body-parser")
const mongoose = require("./database");
const session = require("express-session");
const http = require('http');
const server = app.listen(port, () => console.log("Server listening on port " + port));
const io = require("socket.io")(server, { pingTimeout: 60000 });
app.set("view engine", "pug");
app.set("views", "views");
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "public")));
app.use(session({
secret: "#########",
resave: true,
saveUninitialized: false
}))
// Routes
const loginRoute = require('./routes/loginRoutes');
const registerRoute = require('./routes/registerRoutes');
const logoutRoute = require('./routes/logout');
const postRoute = require('./routes/postRoutes');
const profileRoute = require('./routes/profileRoutes');
const uploadRoute = require('./routes/uploadRoutes');
const searchRoute = require('./routes/searchRoutes');
const messagesRoute = require('./routes/messagesRoutes');
const notificationsRoute = require('./routes/notificationRoutes');
// Api routes
const postsApiRoute = require('./routes/api/posts');
const usersApiRoute = require('./routes/api/users');
const chatsApiRoute = require('./routes/api/chats');
const messagesApiRoute = require('./routes/api/messages');
const notificationsApiRoute = require('./routes/api/notifications');
app.use("/login", loginRoute);
app.use("/register", registerRoute);
app.use("/logout", logoutRoute);
app.use("/posts", middleware.requireLogin, postRoute);
app.use("/profile", middleware.requireLogin, profileRoute);
app.use("/uploads", uploadRoute);
app.use("/search", middleware.requireLogin, searchRoute);
app.use("/messages", middleware.requireLogin, messagesRoute);
app.use("/notifications", middleware.requireLogin, notificationsRoute);
app.use("/api/posts", postsApiRoute);
app.use("/api/users", usersApiRoute);
app.use("/api/chats", chatsApiRoute);
app.use("/api/messages", messagesApiRoute);
app.use("/api/notifications", notificationsApiRoute);
app.get("/", middleware.requireLogin, (req, res, next) => {
var payload = {
pageTitle: "Home",
userLoggedIn: req.session.user,
userLoggedInJs: JSON.stringify(req.session.user),
}
res.status(200).render("home", payload);
})
io.on("connection", socket => {
socket.on("setup", userData => {
socket.join(userData._id);
socket.emit("connected");
})
socket.on("join room", room => socket.join(room));
socket.on("typing", room => socket.in(room).emit("typing"));
socket.on("stop typing", room => socket.in(room).emit("stop typing"));
socket.on("notification received", room => socket.in(room).emit("notification received"));
socket.on("new message", newMessage => {
var chat = newMessage.chat;
if(!chat.users) return console.log("Chat.users not defined");
chat.users.forEach(user => {
if(user._id == newMessage.sender._id) return;
socket.in(user._id).emit("message received", newMessage);
})
});
})
If you don't want to refactor all your pug template engine pages to next.js pages, then you can make the pug pages coexist with the next.js. You can make the next.js the default route, and place next.js code after all pug page routes. And you also need to refactor app.get("/", middleware.requireLogin, (req, res, next) => {...} to make sure next.js is the default route.
To apply this rule, you need a custom next.js server.
sample code
const express = require('express');
const next = require('next');
const port = 3000;
const dev = process.env.NODE_ENV !== 'production'; // use default NodeJS environment variable to figure out dev mode
const app = next({dev, conf});
const handle = app.getRequestHandler();
const server = express();
// all your pug page routes should be declared before `server.get('*'`.
server.get('*', authMiddleware(false), (req, res) => {
// pass through everything to NextJS
return handle(req, res);
});
app.prepare().then(() => {
server.listen(port, (err) => {
if (err) throw err;
console.log('NextJS is ready on http://localhost:' + port);
});
}).catch(e => {
console.error(e.stack);
process.exit(1);
});

Error wooCommerce REST API : woocommerce_rest_cannot_view

I have some difficulties accessing my wooCommerce API with react and nextjs.
I always have this message : woocommerce_rest_cannot_view
I tried the response I've seen on other thread on stackoverflow, but nothing worked for me.
Here my server.js
const next = require('next');
const express = require('express');
const wooConfig = require( './wooConfig' );
const WooCommerceAPI = require('woocommerce-api');
// import WooCommerceRestApi from "#woocommerce/woocommerce-rest-api"; // Supports ESM
const WooCommerce = new WooCommerceAPI({
url: wooConfig.siteUrl,
consumerKey: wooConfig.consumerKey,
consumerSecret: wooConfig.consumerSecret,
wpAPI: true,
version: 'wc/v1',
query_string_auth: true
});
const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
server.get('/getProducts', (req, response) => {
WooCommerce.get('products', function (err, data, res) {
response.json(JSON.parse(res));
});
})
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) {
throw err;
}
console.log(`Ready on port ${port}`)
})
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});;
I found the solution :
This is
queryStringAuth: true
instead of
query_string_auth: true

HTTPS on localhost using NextJS + Express

System Information
Express: 4.16.4
NextJS: 8.0.3
React: 16.8.4
ReactDOM: 16.8.4
Goal
Serve the web application using SSL over HTTPS on localhost
What has been done
Created basic NextJS application using Create Next App
Generated a certificate and key using OpenSSL and moved it into the project directory
Added the Express dependency
Configured the app to use express inside server.js
Changed script to use the server.js inside package.json scripts.
server.js
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const port = 3000;
const https = require('https');
const fs = require('fs');
const httpsOptions = {
key: fs.readFileSync('./certificates/key.pem'),
cert: fs.readFileSync('./certificates/cert.pem')
};
app
.prepare()
.then(() => {
const server = express();
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log('> Ready on http://localhost: ' + port);
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
Extra Information
The app currently works when initialized using yarn dev. I have tried to serve the app over https using this answer but I was unable to figure out how to apply this to my current setup using NextJS.
I spent a lot of time researching the web how to apply this solution but have not yet found a way on how to make this work.
Any help is greatly appreciated.
You just need to use the createServer method of https module.
const { createServer } = require('https');
const { parse } = require('url');
const { readFileSync } = require('fs');
const next = require('next');
const port = 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const httpsOptions = {
key: readFileSync('./certificates/key.pem'),
cert: readFileSync('./certificates/cert.pem')
};
app.prepare()
.then(() => {
createServer(httpsOptions, (req, res) => {
const parsedUrl = parse(req.url, true);
handle(req, res, parsedUrl);
}).listen(port, err => {
if (err) throw err;
console.log(`> Ready on https://localhost:${port}`);
})
});
Other answer seemed to just drop express... Found a solution after some difficulty with both server code and certificate so hopefully can save someone else the trouble!
First of all, solid advice for creating localhost certificate here:
https://letsencrypt.org/docs/certificates-for-localhost/
Secondly, simple code that offers HTTP/HTTPS with next js and express:
const next = require('next');
const express = require('express');
const http = require('http');
const https = require('https');
const fs = require('fs');
const ports = {
http: 3080,
https: 3443
}
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const server = express();
const options = {
key: fs.readFileSync('localhost.key'),
cert: fs.readFileSync('localhost.crt'),
};
app.prepare().then(() => {
server.all('*', (req, res) => {
return handle(req, res)
});
http.createServer(server).listen(ports.http);
https.createServer(options, server).listen(ports.https);
});
It is worth noting that one could omit or redirect either port.
Below work for me very well for next server with https;
Using this official documentation of node js https module Creating HTTPS Server
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
const { readFileSync } = require('fs');
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const httpsOptions = {
pfx: readFileSync('./certificates/AMB.pfx'),
passphrase: 'Testabc$'
};
app.prepare().then(() => {
createServer(httpsOptions, (req, res) => {
const parsedUrl = parse(req.url, true)
const { pathname, query } = parsedUrl
if (pathname === '/login') {
app.render(req, res, '/login', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(port, err => {
if (err) throw err
console.log(`> Ready on https://localhost:${port}`)
})
})
Our straightforward, switchable implementation:
const app = require('express')();
const https = require('https');
const http = require('http');
const next = require('next');
const fs = require('fs');
const path = require('path');
const HTTPS = true;
const server = HTTPS
? https.createServer(
{
key: fs.readFileSync(path.resolve(__dirname, './server.key')),
cert: fs.readFileSync(path.resolve(__dirname, './server.cert')),
},
app
)
: http.createServer({}, app);
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const nextApp = next({ dev });
const nextHandler = nextApp.getRequestHandler();
nextApp.prepare().then(() => {
app.get('/api/something', (req, res) => {
res.json({});
});
// ...
app.get('*', (req, res) => {
return nextHandler(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http${HTTPS ? 's' : ''}://localhost:${port}`);
});
});

Endpoint returns 404 when using custom Express server

I have a Next.js app with two pages. My structure looks like the following:
/pages
/index.js
/city.js
I've created a custom server so that if the user goes to anything other than the home page it should render city.js. For example if you go to myapp.com/phl then the url should stay myapp.com/phl but it should render city.js. The same applies if you go to myapp.com/stl.
Here's my custom server:
const express = require('express');
const next = require('next');
const url = require('url');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
server.get('*', (request, response) => {
return handler(request, response);
});
server.get('/:airportCode', (request, response) => {
console.log('hello from the server');
app.render( request, response, '/city', { ...request.query, ...request.params } );
});
server.listen(3000, error => {
if (error) throw error;
console.log('> Ready on http://localhost:3000');
});
})
.catch(exception => {
console.error(exception.stack);
process.exit(1);
});
When I visit the home page it renders that page fine, but when I go to https://myapp.com/phl I get a 404. Am I missing something?
You need to switch up your page handler with the asterisk page handler:
const express = require('express');
const next = require('next');
const url = require('url');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
server.get('/:airportCode', (request, response) => {
console.log('hello from the server');
app.render( request, response, '/city', { ...request.query, ...request.params } );
});
server.get('*', (request, response) => {
return handler(request, response);
});
server.listen(3000, error => {
if (error) throw error;
console.log('> Ready on http://localhost:3000');
});
})
.catch(exception => {
console.error(exception.stack);
process.exit(1);
});
The function of asterisk is like a fallback for any path that isn't handled by the previous function.

Resources