Couldn't find a `pages` directory. NextJS with pkg - javascript

I want to make a NextJS executable app for Windows, but I get this annoying error:
(node:18500) UnhandledPromiseRejectionWarning: Error: > Couldn't find a pages directory. Please create one under the project root
I have a pages folder in the root folder
Below is server.js
const { createServer } = require('http')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3003
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev, dir: __dirname })
const handle = app.getRequestHandler()
app.prepare().then(() => {
createServer((req, res) => {
const parsedUrl = new URL(req.url, 'http://w.w')
const { pathname, query } = parsedUrl
if (pathname === '/a') {
app.render(req, res, '/a', query)
} else if (pathname === '/b') {
app.render(req, res, '/b', query)
} else {
handle(req, res, parsedUrl)
}
}).listen(port, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
And package.json
{
"name": "custom-server",
"version": "1.0.0",
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "cross-env NODE_ENV=production node server.js",
"pkg": "pkg . --targets node12-win-x64 --out-path pkg"
},
"dependencies": {
"cross-env": "^7.0.2",
"next": "latest",
"pkg": "^4.4.9",
"react": "^17.0.1",
"react-dom": "^17.0.1"
},
"main": "server.js",
"license": "MIT",
"bin": "server.js",
"pkg": {
"assets": [
".next/**/*"
],
"scripts": [
".next/server/**/*.js"
]
}
}
How can I solve this issue and make a NextJS working executable ?

When you run the build make sure you set NODE_ENV to production, also pass a conf to your server.js as per the docs.
const app = next({ dev, dir: __dirname, conf : {output : "standalone"} })
NODE_ENV should be production for all your tasks besides run dev.

Related

Deploying app to Heroku throws error { path=β€œ/” path=β€œ/favicon.ico” }. But runs on localhost

I am trying to deploy my app to Heroku. I am getting 503 (Service Unavailable) error even though it runs on localhost. I have tried many solutions, but none of them are working. My app.js file
if (process.env.NODE_ENV !== "production") {
require("dotenv").config();
}
const express = require("express");
const mongoose = require("mongoose");
const { ApolloServer } = require("apollo-server-express");
const auth = require("./middleware/auth");
const userController = require("./controllers/userController");
const typeDefs = require("./schema");
const resolvers = require("./resolvers");
const port = process.env.PORT || 4000;
const app = express();
app.set("port", port);
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Methods",
"OPTIONS, GET, POST, PUT, PATCH, DELETE"
);
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
next();
});
app.use(auth);
app.get("/email-confirmation/:token", userController.confirmationPost);
const server = new ApolloServer({
typeDefs,
resolvers,
formatError: (err) => {
if (!err.originalError) {
return err;
}
if (err.message.startsWith("Database Error: ")) {
err.message = "Internal server error";
}
const data = err.originalError.data;
const message = err.message || "Internal server error.";
const code = err.originalError.code || 500;
return { message: message, status: code, data: data };
},
context: ({ req, res }) => ({
req,
res,
}),
});
server.applyMiddleware({ app });
mongoose
.connect(process.env.DB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => {
console.log("conneted to database");
app.listen(port, () => {
console.log("listening for requests on port " + port);
});
});
And my package.json is:
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js",
"dev": "nodemon app.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^2.17.0",
"bcryptjs": "^2.4.3",
"crypto": "^1.0.1",
"express": "^4.17.1",
"graphql": "^15.3.0",
"jsonwebtoken": "^8.3.0",
"mongoose": "^5.10.2",
"nodemailer": "^6.4.16",
"nodemailer-sendgrid-transport": "^0.2.0",
"validator": "^10.8.0"
},
"devDependencies": {
"dotenv": "^8.2.0",
"eslint": "^7.7.0",
"nodemon": "^2.0.6"
}
}
heroku logs --tail command gives following output:
I have tried every solution. But none of them seems to resolve the issue. Please, help.
UPDATE:
After I setup DB_URL in Heroku, it started working but I am getting another error.
Console:
1. GET https://capstone-ecommerce-backend.herokuapp.com/ 404 (Not Found)
2. Refused to load the image 'https://capstone-ecommerce-backend.herokuapp.com/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.
Try setting up the DB_URL in your Heroku application. Use the following command:
$ heroku config:set DB_URL=database_uri_here

Heroku - Express and React app showing blank screen when deployed

I am having a difficult time trying to figure out what is going on here. When I deploy my React/Express app to Heroku, everything builds and deploys with no errors, but my React frontend is completely blank.
I am getting this errors in the browser console:
Uncaught SyntaxError: Unexpected token < 1.b1e0c624.chunk.js:1
Uncaught SyntaxError: Unexpected token < main.48d62be5.chunk.js:1
manifest.json:1 Manifest: Line: 1, column: 1, Unexpected token.
Here is how my server.js file is setup to send the root index.html file:
app.use('/static', express.static(path.join(__dirname, 'client/build')));
app.get('*', function(_, res) {
res.sendFile(path.join('/app/client/build/index.html'), function(err) {
if (err) {
console.log(err);
res.status(500).send(err);
}
});
});
And this is what the top portion (code redacted for brevity) of my React apps package.json looks like:
{
"name": "client",
"version": "0.1.0",
"homepage": "https://radiant-tor-66940.herokuapp.com/",
"private": true,
}
I figured setting the homepage in the client's package.json would do it but nothing. I am really unsure what to do here. I am thinking that something might be off with a path or something like that.
Update
This is still an issue for me. Below I have shared more code in hopes that this is can aid in my case. I am getting a new error this time when the page loads:
{"errno":-2,"code":"ENOENT","syscall":"stat","path":"/app/server/client/build/index.html","expose":false,"statusCode":404,"status":404}
This error above is being sent from the error block in this code:
app.get('*', function(req, res) {
res.sendFile('/client/build/index.html', { root: __dirname }, function(err) {
if (err) {
res.status(500).send(err);
}
});
});
I have changed my server.js file to serve the index.js file like this versus using a template literal (trying anything at this point):
//Express
const express = require('express');
const app = express();
const port = process.env.PORT || 8000;
//Core Node Modules
const fs = require('fs');
const path = require('path');
//Middleware
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static(path.join(__dirname, '/client/build')));
app.get('*', function(req, res) {
res.sendFile('index.html', { root: __dirname }, function(err) {
if (err) {
res.status(500).send(err);
}
});
});
app.listen(port, err => {
if (err) console.info(`Error: The server failed to start on ${port}`);
else console.info(`****** Node server is running on ${port} ******`);
});
This is the root level package.json for my server. I have added the heroku-postbuild script to build the React app located in client:
"scripts": {
"test": "jest",
"start": "node server/server.js",
"heroku-postbuild": "cd client && npm install --only=dev && npm install && npm run build"
},
"engines": {
"node": "~9.10.1",
"npm": "~5.6.0"
}
Here is the package.json for the React app located in /client:
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.19.0",
"lodash": "^4.17.11",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-redux": "^6.0.0",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.3",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"styled-components": "^4.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
],
"proxy": "http://localhost:8000/"
}
Here is what the files looks like on the Heroku server:
1st image: Root Directory
2nd image: /client directory
3rd image: /client/build directory
4th image: /client/build/static directoy
The issue was in my server.js file.
Originally it was express.static(path_join(__dirname, '/client/build'))
it needed to be: express.static(path_join(__dirname, '../client/build'))
This is the case because my server.js file is located in /server and it was trying to find /client/build inside of /server instead of the root app directory on Heroku.
As we don't have access to your server, it's hard to tell the reason behind your problem. I would guess you misconfigured your express server as those three error messages indicate, that the server only returns the index.html file.
And as HTML is not valid Javascript, you get unexpected token errors.
I would also guess, that the following line has no effect at all, which means there are no files in this folder (or not those you want to access).
app.use('/static', express.static(path.join(__dirname, 'client/build')));

Having trouble deploying an app to heroku through git

I am trying to create a simple node.js app on heroku. Here is my app.js:
console.log("Starting App")
const express = require('express')
const app = express()
const port = 3000
app.listen(process.env.PORT || port, () => console.log(`App listening on port ${port}!`))
app.get('/', (req,res) => {
res.sendFile(__dirname+'/public/index.html')
})
app.get('/style', (req,res) => {
res.sendFile(__dirname+'/public/main.css')
})
app.get('/script', (req,res) => {
res.sendFile(__dirname+'/public/script.js')
})
app.get('/changelog', (req,res) => {
res.sendFile(__dirname+'/public/changelog.txt')
})
here is my package.json file:
{
"name": "",
"version": "0.0.0",
"description": "",
"main": "/App.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
and here is my Procfile:
web: node app.js
I am deploying this to heroku via github, and whenever I run the program it gives me an error, saying Cannot find module '/app/app.js.' I have made everything lowercase and removed forward slashes. I still get this error: Error: Cannot find module '/app/app.js' Can anyone help?
In package.json, change "main": "/App.js" to "main": "app.js"
make sure package.json is at the same level as app.js
If app.js is in another folder, make sure to provide the full path from directory holding the package.json file.

reactjs expressjs how to setup proxy? proxy doesn't work with localhost:3000, but works with localhost:3000/test

Trying to work with reactjs (create-react-app) and now including expressjs. What I've done is
move my folder/* to folder/client/* (deleting node_modules)
cd folder/client/ and npm install to recreate the node_modules
*it works as before, the app renders well
cd folder and npm init
npm install express --save
write the folder/server.js
add the proxy settings in /folder/client/package.json
npm run start in /folder and in /folder/client
Then, I go to localhost:3000 and I get the reactjs app, without express anywhere. Then I go to localhost:8080 and I get the express result, which is indeed the same page as before but without being executed by react (nothing wrong here, I assume)
And then I go to localhost:3000/test and it gets proxied to express, where I see in the terminal the console.log of server.js
So I cannot proxy localhost:3000, but I can localhost:3000/whatever. What is wrong?
server.js
const express = require('express');
const path = require('path'); // haven't installed, should I?
const app = express();
app.use(express.static(path.join(__dirname, 'build'))); // of no use here
app.get('/ping', function (req, res) { // this one works
return res.send('pong');
});
// app.get('', function (req, res) { // doesn't work
// app.get('*', function (req, res) { // doesn't work
// app.get('.', function (req, res) { // doesn't work
// app.get('.*', function (req, res) { // doesn't work
// app.get('./', function (req, res) { // doesn't work
app.get('./*', function (req, res) { // doesn't work
console.log('hey') // never seen
res.sendFile(path.join(__dirname, 'client/src', 'index.html'));
});
app.get('/test', function (req, res) { // this one works
console.log('hey2') // I do see this when calling localhost:3000/test
res.sendFile(path.join(__dirname, 'client/src', 'index.html'));
});
app.listen(process.env.PORT || 8080);
package.json (/)
{
"name": "ouyea",
"version": "0.1.1",
"description": "This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "git+https://xxxx"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://xxxx"
},
"homepage": "https://xxxx",
"dependencies": {
"express": "^4.16.4"
}
}
package.json (/client)
{
"name": "client",
"version": "0.1.1",
"private": true,
"dependencies": {
"axios": "^0.18.0",
"googleapis": "^33.0.0",
"papaparse": "4.6.0",
"react": "^16.4.2",
"react-dom": "^16.4.2",
"react-scripts": "1.1.4",
"semantic-ui-css": "^2.4.0",
"semantic-ui-react": "^0.82.5"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"proxy": {
"": { // I know comments don't work, but I put them here for clarity, none of them worked
// "*": {
// ".": {
// "/": {
"target": "http://localhost:8080"
},
"/test": {
"target": "http://localhost:8080"
}
}
}
The purpose of the express server is to simply a) render the base HTML page from your dist folder, and b) supply data from endpoints that you set up as routes in Express which can be accessed by your React client application. There are apps (universal) that can render React pages from Express but that's not what you're doing here with create-react-app.

How to deploy node js app with react to heroku

I trying deploy my MERN app to heroku.
After build success on heroku doesn't see a API routes:
Steps:
On localhost I run concurrently node server and client (create-react-app).
Server on port 5000 and client on port 3000.
After this I fetch from API routes /hotels Array with items and connect it to Redux store and display it.
Properly behavior:
Localhost: works fine
Heroku: broken (didn't connect with API)
This is my server.js file:
const express = require('express');
const path = require('path');
const app = express();
const http = require('http');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const passport = require('passport');
const morgan = require('morgan');
const keys = require('./API/config/keys');
//######### MODELS #########
require('./API/models/Users');
//######### SERVICES #########
require('./API/services/passport');
//######### MONGODB CONNECT #########
mongoose.connect(MONGO_CONNECT);
//######### ROUTES #########
const hotelsRoutes = require('./API/routes/hotels');
const countRoutes = require('./API/routes/count');
const topRoutes = require('./API/routes/top');
// Use routes
app.use('/hotels', hotelsRoutes);
app.use('/count', countRoutes);
app.use('/top', topRoutes);
app.use(morgan('dev'));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
keys: [keys.cookieKey]
})
);
app.use(passport.initialize());
app.use(passport.session());
require('./API/routes/authRoutes')(app);
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
const port = process.env.PORT || 5000;
const server = http.createServer(app);
server.listen(port);
Package.json (server):
{
"name": "root-react-hotel-app",
"version": "0.1.0",
"main": "server.js",
"scripts": {
"client": "cd client && yarn start",
"start": "node server.js",
"start-api": "nodemon server.js",
"dev": "concurrently \"yarn start-api\" \"yarn client\"",
"build": "cd client && npm install && yarn build"
},
"devDependencies": {
//
},
"dependencies": {
//
}
}
Package.json (client):
{
"name": "client-react-hotel-app",
"version": "0.1.0",
"private": true,
"proxy": {
"/auth/google": {
"target": "http://localhost:5000"
},
"/api/*": {
"target": "http://localhost:5000"
},
"/*": {
"target": "http://localhost:5000"
}
},
"dependencies": {
// Here are dependencies
},
"scripts": {
"build-css": "node-sass-chokidar src/ -o src/",
"watch-css": "npm run build-css && node-sass-chokidar src/ -o src/ --watch --recursive",
"start-js": "react-scripts start",
"start": "npm-run-all -p watch-css start-js",
"build-js": "react-scripts build",
"build": "npm-run-all build-css build-js",
"eject": "react-scripts eject",
"compile:sass": "node-sass src/css/styles.scss src/css/styles.css -w",
"generate:doc": "sassdoc src/css/abstracts/_mixins.scss",
"test": "cross-env NODE_ENV=test jest --config=jest.config.json",
"test-coverage": "cross-env NODE_ENV=test jest --coverage --config=jest.config.json",
"test-ci": "cross-env NODE_ENV=test jest --config=jest.config.json --coverage && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js"
},
"devDependencies": {
// Here are devDependencies
}
}
Also trying with static.json file and Procfile:
{
"root": "client/build/",
"setupFiles": [
"<rootDir>/client/src/setupTests.js"
]
}
Anyone can help?
Since your express server is serving both your react bundle and your api routes, in:
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
You need to protect your api routes in the 'app.get' when deploying to heroku (production mode). You can use a simple regex in order to serve all routes to your react bundle except '/api' (or whatever your api endpoint looks like, /API in your case above). It works running locally because you are running your api and react app on separate ports, not the same server.
Usually something like:
if (process.env.NODE_ENV === 'production') {
app.get(/^\/(?!api).*/, (req, res) => { // don't serve react app to api routes
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
};

Categories