Error starting a Next.js application in https - node.js

I'm attempting to start a Next.js application in https mode. I'm following the instructions here. When I try to open the page, I get the following error:
TypeError: (0 , react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV) is not a function
here's my code:
const { createServer } = require("https");
const { parse } = require("url");
const {next} = require("next");
const fs = require("fs");
const dotenv = require('dotenv');
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
//read the .env file
dotenv.config();
const port = process.env.PORT;
const httpsOptions = {
key: fs.readFileSync("./certificates/privateKey.key"),
cert: fs.readFileSync("./certificates/certificate.crt"),
};
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("> Server started on https://localhost:" + port);
});
});
Here's the stack trace:
TypeError: (0 , react_jsx_dev_runtime__WEBPACK_IMPORTED_MODULE_0__.jsxDEV) is not a function
at IBOUIApp (C:\Users\mgardner\workspace\qa-tool-backoffice\.next\server\pages\_app.js:53:92)
at d (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:33:498)
at bb (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:36:16)
at a.b.render (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:42:43)
at a.b.read (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:41:83)
at exports.renderToString (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\react-dom\cjs\react-dom-server.node.production.min.js:52:138)
at Object.renderPage (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\render.js:54:854)
at Function.getInitialProps (C:\Users\mgardner\workspace\qa-tool-backoffice\.next\server\vendors-node_modules_next_dist_pages__document_js.js:627:19)
at loadGetInitialProps (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\lib\utils.js:5:101)
at renderToHTML (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\render.js:54:1145)
at async C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\next-server.js:112:97
at async C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\next-server.js:105:142
at async DevServer.renderToHTMLWithComponents (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\next-server.js:137:387)
at async DevServer.renderToHTML (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\next-server\server\next-server.js:138:610)
at async DevServer.renderToHTML (C:\Users\mgardner\workspace\qa-tool-backoffice\node_modules\next\dist\server\next-dev-server.js:36:578)

Related

Chai testing TypeError: Converting circular structure to JSON

I'm a new learner express.js I want to test simple post and get operations with tdd mechanism. I created the test, route, index and db files but when I try to test POST method it gives me this error.
This is my routes/task.js
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
This is my test/task.js
let chai = require("chai");
const chaiHttp = require("chai-http");
const { send } = require("process");
let server = require("../index");
//Assertion Style
chai.should();
chai.use(chaiHttp);
describe('Tasks API', () => {
/**
* Test the POST Route
*/
describe('POST /api/task', () => {
it("It should POST a new task", () => {
const task = {task: "Wake Up"};
chai.request(server)
.post("/api/task")
.send(task)
.end((err, response) => {
response.should.have.status(201);
response.body.should.be.a('string');
response.body.should.have.property('id');
response.body.should.have.property('task');
response.body.should.have.property('task').eq("Wake Up");
response.body.length.should.be.eq(1);
done();
});
});
});
});
This is my db.js
var sqlite3 = require('sqlite3').verbose()
const DBSOURCE = "db.sqlite"
let db = new sqlite3.Database(DBSOURCE, (err) => {
if (err) {
// Cannot open database
console.error(err.message)
throw err
}else{
console.log('Connected to the SQLite database.')
db.run(`CREATE TABLE IF NOT EXISTS todo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task text
)`,
(err) => {
if (err) {
// Table already created
console.log(err);
}
});
}
});
module.exports = db
And this is my index.js
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
The thing that I try to do is building a test case to test the post method. I think I couldn't built the correct relations the files.
Currently, just by doing a POST request to /api/task, the error will appear. That is because of these lines in index.js:
app.post('/api/task', (req, res) => {
res.status(201).send(req);
});
The req parameter is circular, hence cannot be JSON-stringified.
Solution
In routes/task.js export the router:
const express = require('express');
const router = express.Router();
router.post("/api/task", async (req,res) => {
try {
const task = await new Task(req.body).save();
res.send(task);
} catch (error) {
res.send(error);
}
})
// By adding this line you can export the router
module.exports = router
In index.js, include the routes/task.js file and pass it to app.use(...), also remove the now-obsolete /api/task route:
const connection = require('./db');
const express = require('express');
const app = express();
const cors = require("cors");
const taskRoutes = require("./routes/task")
const port = process.env.PORT || 8080;
app.use(express.json());
app.use(cors());
app.get('/', (req, res) => {
res.send('Hello World');
});
app.use(taskRoutes)
app.listen(port, () => console.log(`Listening on port ${port}...`));
module.exports = app;
This way we got rid of the circular structure stringifying and the tests should now pass.

Node.js server return error 404 in production

hope you are good,
I am building my next.js weather app project using openweather API, I set up my proxy server, so the API key won't appear on the client side, it works perfect on my localhost, but when I deploy it on vercel or heroku, it returns error 404, it does the same when requesting directly on postman or browser.
PS: the environment variables are set in my vercel dashboard.
PS: api url example localhost:3000/api/weather?q=london
my server.js
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const needle = require('needle');
const url = require('url');
const cors = require('cors');
app.prepare().then(() => {
const API_BASE_URL = process.env.API_BASE_URL;
const API_KEY_NAME = process.env.API_KEY_NAME;
const API_KEY_VALUE = process.env.API_KEY_VALUE;
const server = express();
server.use(
cors({
origin: '*',
})
);
server.get(
'/api/:stat',
async (req, res) => {
try {
const params = new URLSearchParams({
...url.parse(req.url, true).slashes,
...url.parse(req.url, true).query,
[API_KEY_NAME]: API_KEY_VALUE,
});
const apiRes = await needle(
'get',
`${API_BASE_URL}/${req.params.stat}?${params}`
);
const data = apiRes.body;
res.status(200).json(data);
} catch (error) {
res.status(500).json({ error });
}
}
);
server.all('*', (req, res) => {
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});

Error: socket hang up with Node.js, Mongo DB & load-balancer

I am developing an REST-API that is running via a load-balancer with a database in MongoDB.
The API works when not using the load-balancer, but when implemented i do not get a response in Postman/Insomia when posting a GET request to the database - on the index ("/") route there in no problem getting a response back though.
But as the title shows, it get this error when canceling the request in PostMan, if like the connection could not be established.
This is the full error:
Error: socket hang up
at connResetException (internal/errors.js:628:14)
at TLSSocket.socketCloseListener (_http_client.js:449:25)
at TLSSocket.emit (events.js:412:35)
at net.js:675:12
at TCP.done (_tls_wrap.js:563:7) {
code: 'ECONNRESET'
}
This is my load-balancer
const https = require ("https");
const httpProxy = require("http-proxy");
const seaport = require("seaport");
const express = require("express");
const fs = require("fs");
const HOST = 'localhost';
const path = require("path")
const PORT = 8080;
const connect = seaport.connect('localhost', 9090);
let i = - 1;
const certificate = {
key: fs.readFileSync(path.join(__dirname, 'cert', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert', 'cert.pem')),
secure: false
};
let proxy = httpProxy.createProxyServer({secure: false});
let server = https.createServer(certificate, function(req, res) {
let addresses = connect.query('server');
if (!addresses.length) {
res.end('Server failed');
};
i = (i + 1) % addresses.length;
let host = addresses[i].host.split(":").reverse()[0];
let port = addresses[i].port;
proxy.web(req, res, { target: 'https://' + host + ':' + port });
});
server.listen(PORT, function() {
console.log('loadbalancer listens on'+ ":" + PORT)
});
And this is my app.js
const express = require("express");
const app = express();
const morgan = require("morgan")
const bodyParser = require("body-parser")
const https = require('https');
const fs = require('fs');
const seaport = require('seaport');
const path = require('path');
const mongoose = require("mongoose");
//Database
const db = require('./database/db');
const { MongooseDocument } = require('mongoose');
//Routes
const clientRoute = require ("./api/routes/client")
const reservationsRoute = require ("./api/routes/reservations")
app.use('/client', clientRoute);
app.use('/reservations', reservationsRoute);
//index route
app.use('/', (req, res) =>{
res.send('Welcome to the app');
});
//Error handling 1
app.use((req, res, next) => {
const error = new Error("Not found" + " ");
error.status = 400;
next(error);
})
//Error handling 2
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message:("Error 2" + " - " + error.message )
}
});
});
//Create server with the https key and certificate
const sslServer = https.createServer({
key: fs.readFileSync(path.join(__dirname, 'cert', 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert', 'cert.pem')),
}, app);
//Middleware
app.use(morgan("dev"));
app.use(bodyParser.json());
const seaportObject = seaport.connect('localhost', 9090);
//Start listening
let port = seaportObject.register('server');
sslServer.listen(port, () => {
db.mongoConnection()
.then(
console.log('Localserver listens on: ' + port)
)
.catch(err =>{
console.log(err)
res.status(500).json({
error:err,
message: "
It went wrong here "
})
});
});
My Database folder
const mongoose = require('mongoose');
let connection;
const mongoConnection = async () => {
if (!connection) {
connection =
await mongoose.connect("removed",
() => console.log("Mongo is up and running")),{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
}
}
return connection;
}
module.exports = {
mongoConnection: mongoConnection
};
I am stuck on this subject, please share some guidance
A solution has been found - the problem was that the database never connected

Nextjs and Express as middle ware. How do I set 'localhost:3000/newpage' and 'localhost:3000/newpage/' as the same routes

I am new to express and next and was trying to set 'localhost:3000/newpage' and 'localhost:3000/newpage/' as the same route however as I add a '/' at the end it shows a 404 error.
I am using "next-routes" for dynamic routing and have created routes.js file that looks like this:
const nextRoutes = require("next-routes");
const routes = (module.exports = nextRoutes());
routes.add("index", "/");
routes.add("newpage", "/newpage/:slug"); //with body parser this doesnt work
and my server.js file looks like this:
const express = require("express");
const next = require("next");
const routes = require("./routes");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
const bodyParser = require("body-parser");
const handler = routes.getRequestHandler(app);
app
.prepare()
.then(() => {
const server = express();
server.use(bodyParser.json()); //with this dynamic routes dont work
server.use (handler); //with this dynamic routes work but / url show 404
server.get("*", (req, res) => {
server.use(handler);
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // works only when using body parser
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
You can modify the url that you get before passing it to Next's handling.
const next = require('next');
const express = require('express');
const routes = require('./routes');
const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
// const handler = routes.getRequestHandler(app); // redundant line
app.prepare().then(() => {
const server = express();
// server.use(handler); // <-- this line is redundant since you need only one handle!
server.get('*', (req, res) => {
if (req.url.endsWith('/')) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
});
Working example: https://codesandbox.io/s/express-nextjs-react-c47y8?file=/src/index.js
Navigate to /form or /form/
I had to install the body-parser package then used body-parser. I also changed the folder structure such that I didn't have to import the routes. The final code in server.js looks like this:
const express = require("express");
const next = require("next");
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 3000;
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("*", (req, res) => {
if (req.url.endsWith("/")) {
req.url = req.url.slice(0, -1); // remove the last slash
}
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});

How to use koa.js + next in Firebase Functions

I want to use Cloud Functions for Firebase to deploy the React application for shopify app.
I am new to both Next and Koa.
Based on this repo the below code is how to host a simple react application in Firebase.
const path = require('path')
const functions = require('firebase-functions')
const next = require('next')
var dev = process.env.NODE_ENV !== 'production'
var app = next({
dev,
conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})
var handle = app.getRequestHandler()
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl) // log the page.js file that is being requested
return app.prepare().then(() => handle(req, res))
})
Which works correctly, no issue.
Then based on this tutorial from shopify I need to integrate koa and other dependencies in server.js, which in my case I believe it should be placed inside the firebase function. so I get to this code
const path = require('path')
const isomorphicFetch = require('isomorphic-fetch');
const Koa = require('koa');
const functions = require('firebase-functions')
const next = require('next');
const ShopifyConfig = require('./shopify.js');
const { default: createShopifyAuth } = require('#shopify/koa-shopify-auth');
const dotenv = require('dotenv');
const { verifyRequest } = require('#shopify/koa-shopify-auth');
const session = require('koa-session');
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 3000;
var dev = process.env.NODE_ENV !== 'production'
var app = next({
dev,
conf: { distDir: `${path.relative(process.cwd(), __dirname)}/next` }
})
var handle = app.getRequestHandler()
const server = new Koa();
server.use(session(server));
server.keys = [ShopifyConfig.secretKey];
server.use(
createShopifyAuth({
apiKey: ShopifyConfig.key,
secret: ShopifyConfig.secretKey,
scopes: [],
afterAuth(ctx) {
const { shop, accessToken } = ctx.session;
ctx.redirect('/');
},
}),
);
server.use(verifyRequest());
server.use(async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
});
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl) //
// This is old code
// return app.prepare().then(() => {
// handle(req, res);
// })
// I tried this #1
// server.callback(req, res);
})
// I tried this #2
// exports.next = functions.https.onRequest(server.callback);
// I tried this #3
// exports.next = functions.https.onRequest(server.callback());
// I tried this #4
exports.next = functions.https.onRequest((req, res) => {
console.log('File: ' + req.originalUrl)
return app.prepare().then(() => {
server.callback(req, res);
//handle(req, res);
})
})
My question is now based on Koa what code should be in functions.https.onRequest ? please note there is no code to listen to port since it doesn't make sense for firebase functions.
I tried #1, #2, #3, as well as this post
1 -> I get request timeout
2 -> I get request timeout
3 -> I get "Cannot access middleware of undefined"
4 -> I get request timeout
Thanks to kvindasAB
server.callback is not the callback by itself, rather a function that generates the callback from your configuration I assumed.
so code needs to be changed to
server.callback()(req, res);
const functions = require('firebase-functions');
const app = new Koa();
...
exports['http'] = functions.https.onRequest(app.callback());

Resources