I have installed nodemon locally in my workspace, but even though it restarts in the terminal after changes are made, it does not refresh the browser page. I have to manually refresh it each time.
I've got Express, Node, React and Webpack running in the environment.
This is how my setup looks like -
My package.json starts up server.js -
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon server.js"
},
and server.js is -
var express = require('express');
var app = express();
app.use(express.static('public'));
app.listen(3000, function () {
console.log("Express server is up on port 3000");
});
The entry point in the webpack config file is -
module.exports = {
entry: './public/scripts/app.jsx',
output: {
path: __dirname,
filename: './public/scripts/bundle.js'
}
What should I do to fix it?
Update -
I made a video to describe the situation, if it helps.
nodemon is only for restarting the server when your server code changes. It has no functionality to reload your page in the browser. If you want automatic browser reload, you could, for example, run a webpack dev server in addition to your nodemon. webpack dev server is able reload the page in the browser when your client code changes, it can even update the page in the browser without a full page reload, if you use its hot module reloading feature.
in package.json
"scripts": {
"start": "nodemon server.js -e html,js,css"
},
in server js
var reload = require('reload')
app.listen(3000, () => {
console.log(`Listening on port 3000`);
})
reload(app);
in index.html
<body>
<h1>ron</h1>
<script src="/reload/reload.js"></script> <!-- it's necessary -->
</body>
For those needing to use nodemon and reload browser on change as well, I replied here https://stackoverflow.com/a/51089425/7779953
Solution is Nodemon + Browser Sync + Gulp + Express server
Related
I've got a bit of a weird set up here with a codebase that I inherited. It's a CRA app deployed to Vercel but doesn't use Next.js.
Problem: I'm not able to call myapp.com/nonce from Postman or access it in my browser to see the JSON response. There's some configuration stuff that's not quite right, just trying to figure out what that is. Would love any help here!
I have a file structure that looks like this:
Project (create-react-app)
src
bunch of React code
server
index.js
package.json
package.json
(It's not using next.js. If it were, I'd just use the /pages/api/* files)
In my top-level package.json, I have:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && cd server && npm install && npm run start",
}
and in my /server/package.json I have just a simple start command: node index.js
My server/index.js file:
const path = require('path');
const express = require("express");
const PORT = process.env.PORT || 3001;
const app = express();
app.use(express.static(path.resolve(__dirname, '../MyProject/build')));
app.get('/nonce', async (req, res) => {
const { address } = req.query;
const quantity = snapshot[address];
return res.json({ quantity, address }); // for testing
})
Edit:
With this as-is, my build phase never actually completes.. It runs a server at 3001 and that's the last log of the Build log
> MyProject-server#0.1.0 start /vercel/path0/server
> node index.js
Server listening on 3001
I have MERN application, where I serve index.html on all routes. But bellow that, I declare another apis for request.
router.post('/add-bin', newBin);
router.get('/recent-bins', recentBins);
router.get('/fetch-bin/:filename', fetchBin);
app.use(router);
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html')); // Front is built with react
});
In the development mode, where I was using proxy, everything was going fine, but when I deployed my web application on heroku, All the GET apis are overrode by that app.get("*" ...) part.
P.S I am quite new to Node and Express.
First, in client run npm run build this will generate the build folder, where will be your frontend production code. In your backend you should serve that folder (this usually will be done in your index.js).
app.use(express.static('path/to/client/build'))
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html')); // Front is built with react
});
After that, you'll need to add some commands (in your package.json) to prepare the client for the deploy.
"scripts": {
"build": "cd path/to/client && npm run build",
//we'll need to install client packages
"i-client-packages": "cd client && npm install",
//heroku will execute this command post-build
//this will be needed to run the previous commands
"heroku-postbuild": "npm run i-client-packages && npm run build"
//...the other commands (start, test, etc...)
}
More info about how to deploy a MERN app to heroku here.
As of now, my React app runs on port 3000 via npm start.
I've decided that I want to use MySQL for the web app I'm building via yarn add express mysql.
I made server.js listen in on port 3001.
Whenever I run nodemon server.js and then hit refresh, I'm not seeing test on the front page of my React app (which would indicate that everything works fine).
I can see test if I type localhost: 3001 in my browser but it's completely blank, meaning, I only see test and not the original front page of my web app. It's a whole new different page.
Inside package.json file, I tried to include "proxy":"http://localhost:3001" at the bottom of the file as well as various other places, but it still doesn't work.
How do I make it so that I can see test on the original front page of my web app (port 3000) so I can conclude that everything's working fine and can proceed with integrating MySQL?
Here's my server.js file:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/', (req, res) => {
res.send('test');
});
app.listen(3001, () => {
console.log("listening port 3001");
});
Update
If you don't need to build and try your app in production, meaning you only need to run both of them for development then just use a proxy as suggested in the comments. Run both servers and make requests to your Express API routes on the frontend. You can add a proxy like this in your client's (React part) package.json file.
"proxy": {
"/api/*": {
"target": "http://localhost:3001"
}
}
Then, any request made for /api/* on the frontend goes through your Express server.
For starting both servers at the same time, you can use concurrently. First install it on the server side:
yarn add concurrently
After installing it you add something like this in your scripts part:
"scripts": {
"server": "nodemon index.js",
"client": "npm run start --prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\"",
"prod": "NODE_ENV=production nodemon app.js"
},
I misunderstood your intention at first, this is why I gave an answer like the below one.
This is normal behavior since you haven't configured Express to serve your frontend properly.
First of all, for a React app you don't need any server at all. What you are using right now (on port 3000) is for developing purposes. So, after completing your app you should build it and configure Express to serve it statically.
First, build it:
yarn build
After this step, you will have static files in your client's build directory.
Now, your Express config should be something like this:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/test', (req, res) => {
res.send('test');
});
app.use( express.static( "client/build" ) );
app.get( "*", ( req, res ) =>
res.sendFile( path.resolve( __dirname, "client", "build", "index.html" ) ) );
app.listen(3001, () => {
console.log("listening port 3001");
});
Notice the route change for Express. I changed / with /test. So, when you hit /test you will see what your Express route serves. Other than this route you should see your React app.
Also, don't forget to change those if your setup is different:
client/build
and
path.resolve( __dirname, "client", "build", "index.html" )
This means Express searches a client directory and you React app resides there.
PS: You will only start the Express server, there will be no more server for React since you don't need it to serve with Express.
Also, related part can be enhanced like this:
if ( process.env.NODE_ENV === "production" ) {
app.use( express.static( "client/build" ) );
app.get( "*", ( req, res ) =>
res.sendFile( path.resolve( __dirname, "client", "build", "index.html" ) ) );
}
So, at runtime you can pass an environment variable and Express hits this route only in production.
I am using windows ver 10 home, so I am using "docker toolbox for windows" where my docker client is windows/amd64 and server is linux/amd64.
I have built a very simple nodejs application with three files.
server.js
/**
* Created by farhanx on 7/28/2018.
*/
'use strict';
const express = require('express');
// Constants
const PORT = 5000;
const HOST = 'localhost';
// App
const app = express();
app.get('/', function (req, res) {
res.send('Hello world\n');
});
app.get('/students', function (req, res) {
res.send('student page\n');
});
app.listen(PORT, HOST);
console.log('Running on http://'+HOST+':'+PORT);
and package.json
{
"name": "docker_web_app",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last#example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.16.1"
}
}
Docker file
FROM node:8
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm#5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm install --only=production
# Bundle app source
COPY . .
EXPOSE 5001
CMD [ "npm", "start" ]
Then I have built my docker image successfully and ran this command
docker run -p 5001:5000 farhan/mynode
since I have mentioned port 5000 for the server inside the nodejs server file and inside the docker file I have exposed the 5001 as a port.
Now it runs fine and shows on the console that the nodejs server is running but whenever I use localhost:5001, it displays page not found. Which means somehow docker container is working fine but is not accessible to the browser.
Exposing a port means you let through request asking for that port. You have to expose the port 5000 and not the 5001.
EXPOSE 5000
Also, you should not set the HOST of your Express app to localhost. If you do this, only localhost (the container) will be able to make request.
Usually, you do not set the host (it defaults to 0.0.0.0 and accepts everything):
app.listen(PORT);
Since you are using toolbox, you have to access app in your browser via http://linux_docker_host_ip:5001.
To know the host ip, go to virtualbox, and see the docker machine's ip address. Normally you will find a network icon on right bottom corner when you click on vm in virtual box. By default the IP is '192.168.99.100'
I'm using react-router with browserHistory. This function:
app.get('*', function (request, response){
response.sendFile(path.join(__dirname + "/public/index.html"))
})
is supposed to send the Index.html since the routing happens client-side with react-router.
But somehow my index.html is misunderstood by the server and I get this error:
Uncaught SyntaxError: Unexpected token <
I don't know what the problem here is. Is the file path wrong? My tree looks like this:
/app
/app/myJavascriptStuff.js
/public
/public/index.html
/moreStuffThatsNotRelevant
/server.js <- my express file
without the above described function my page usually responds with:
Cannot GET /whatever
on every page refresh that doesn't happen on localhost:3000 (e.g. localhost:3000/whatever)
Because I'm aware that i suck at describing things, here is a link to the repository.
Help is very appreciated. :)
Problem can be because for each request you are sending index.html even when browser asks for your bundle.js or style.css via
app.get('*', function (request, response){
response.sendFile(path.join(__dirname + "/public/index.html"))
});
Define a public folder from where these files can be served let say public(where you have your index.html in your github repo). Let webpack to generate the bundle.js in that folder. Also point in your index.html to use bundle.js from that folder.
Next in your server.js you need to do some changes. Let express to use public path for serving these files when asked by browser.
An example can be -
const app = express();
const publicPath = express.static(path.join(__dirname, 'public'), { redirect : false });
const indexPath = path.join(__dirname, 'public/index.html');
app.use(publicPath);
app.get('/', function (_, res) { res.sendFile(indexPath) });
app.get('*', function (_, res) { res.sendFile(indexPath) });
First of all you did not build your bundle.js file with your webpack. Before you can serve it you need to build it first.
Change you package.json script to
"scripts": {
"build": "webpack --progress --color --config webpack.config.js --watch",
"start": "node server.js"
}
and run the command npm run build before running your server.
If you webpack bundle.js doesn't get created inside /public/build then create a directory build inside public and run the above command again.
This should solve your problem.