Prevent Nodemon to restart some specific code - node.js

I'm using nodemon in my nodejs project because I want whenever I made any changes it will restart automatically everything works fine but now problem is I want to use a lib
which include puppeteer lib whenever I made any changes nodemon close the chromium browser and re-open it which take some time. This is making me slow in development. Is there any way I can stop this behaviour.
Here is my code.
const express = require("express");
const app = express();
const http = require("http");
const server = http.createServer(app);
const { Client } = require("whatsapp-web.js");
const client = new Client({ puppeteer: { headless: false } });
client.initialize();
console.log("changes 7");
server.listen(3000, () => {
console.log("listening on *:3000");
});
Whenever I made any changes it restart everything. I don't want to restart the client every time.

I don't know about nodemon, but if you can edit the library, you can re-use an existent browser.
Try, from node shell:
(await require('puppeteer').launch()).wsEndpoint()
this return a connection string that you can reuse.
And, then, you can connect with the created instace with connect api
Edit: your library allows ws socket! :-)
const client = new Client({
puppeteer: {
browserWSEndpoint: `ws://localhost:3000`
}
});

create nodemon.json in your project directory
nodemon will automatically look for this file and use it if exist
and write in nodemon.json
{
//list of directory you want to watch
"watch": ["./","server","someOtherDir"],
"ext": "js,ts,json", //file extension to watch
"ignore": ["ignoreThisDir","someDir/*.js"], //specify files or directory to ignore
// specify entry of the project
"exec" : "node app.js"
//another example for exec "exec": "ts-node --project tsconfig.server.json server/app.ts"
}

Related

Handling absolute urls in nodejs server

this is my firs project with electron and nodejs
I need to load a specific folder in my electron application
the final structure should be like:
Myapp.app
folder-contents
MyApp must read contents from folder-contents directory
import httpServer from './server'
function createMainWindow() {
const window = new BrowserWindow()
if (isDevelopment) {
window.webContents.openDevTools()
}
window.loadURL(`http://localhost:18081/${app.getAppPath()}/folder-contents/`)
}
in server.js
const path = require("path");
const http = require('http');
const express = require('express');
const PORT = 18081;
const app = express();
app.use(express.static(process.cwd()));
app.set('port', PORT);
const server = http.createServer(app);
server.listen(PORT, "127.0.0.1");
module.exports = app;
In my package.json
"scripts": {
"dev": "electron-webpack dev",
"compile": "electron-webpack",
"dist": "yarn compile && electron-builder",
"dist:dir": "yarn dist --dir -c.compression=store -c.mac.identity=null",
"start": "electron ."
},
launching npm run dist --mac and open myapp.app i get this error
Cannot GET /folder-contents/
any idea?
you can add your files to a folder name public and inside that you can have all your static files stored and then you need to call it in your app.js like:
app.use(express.static('public') //Public is the name of the folder and then you might be able to use all of your static files presented in that folder in your project if this didn't clear you here's a refrence if i am wrong and you get the correct answer else where please correct me.Thank you.
This is an express documentation

Use newrelic in nuxt

I am trying to add newrelic agent to my nuxt application. I have installed the needed package and added my license key and set an application name in newrelic.js configuration file:
npm i newrelic
cp node_modules/newrelic/newrelic.js .
nano newrelic.js
My problem is that I also need to require this configuration file at the top of my server.js file and since this file is dynamically created and placed under the .nuxt folder I have no idea how to do this.
In a standard nodejs application I would simply add the require('newrelic'); to the top of my startup script or perhaps add a new script entry in package.json looking something like this:
"scripts": {
"dev": "node -r newrelic.js app.js"
}
I ended up using express to solve this:
npm i express
touch server/index.js
We will now load newrelic in the server/index.js file and after that create our nuxt instance:
require('newrelic');
const express = require('express');
const consola = require('consola');
const { Nuxt, Builder } = require('nuxt');
const app = express();
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js');
config.dev = process.env.NODE_ENV !== 'production';
async function start () {
// Init Nuxt.js
const nuxt = new Nuxt(config);
const { host, port } = nuxt.options.server;
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt);
await builder.build();
} else {
await nuxt.ready();
}
// Give nuxt middleware to express
app.use(nuxt.render);
// Listen the server
app.listen(port, host);
consola.ready({
message: `Server listening on http://${host}:${port}`,
badge: true
});
}
start();
I also updated the script section in my package.json:
"scripts": {
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
"build": "nuxt build",
"start": "cross-env NODE_ENV=production node server/index.js"
}
Hope this can help anyone who faces the same kind of problem.
For anyone struggling with this I found a much simpler solution by using Nuxt modules and hooks.
Create a new file modules/newRelic.js with the following content:
module.exports = function () {
this.nuxt.hook("listen", () => {
require("newrelic");
});
};
Import the module in nuxt.config.js
modules: [
"~/modules/newRelic.js"
]
Don't forget to install newrelic (npm i newrelic) and paste newrelic.js into the applications root folder.
In Node.js, you can require a module with the -r [module] syntax (see Node.js docs) before your actual script starts up.
For Nuxt, alter your npm run scripts like this (instead nuxt start):
node -r newrelic node_modules/nuxt/bin/nuxt.js start
This way, Node loads NewRelic first, then Nuxt, and ensures NewRelic is able to instrument all dependencies. If you let Nuxt bootup first, NewRelic is not aware of some dependencies, e.g. express.
This is recommended by NewRelic, see their docs.

Use Nuxt programmatically without builder

I am using nuxt programmatically inside express with nuxt.render middleware like below
const { Nuxt, Builder } = require('nuxt')
const app = require('express')()
const api = require('../api')
app.use('/api', api)
let config = require('../nuxt.config.js')
config.dev = !(process.env.NODE_ENV === 'production')
// Init Nuxt.js
const nuxt = new Nuxt(config)
app.use(nuxt.render)
async function start() {
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
// Listen the server
app.listen(port, host)
console.log('Server listening on ' + host + ':' + port)
}
start()
When I am developing the server api routes and make some changes to the server side api files and restart the server, the whole nuxt project builds everytime which takes too much time. This is inconvenient as there were no changes in the nuxt files, only changes in the api route files.
So after building once, I comment out the following lines:
if (config.dev) {
// const builder = new Builder(nuxt)
// await builder.build()
}
I then restart the server which of course does not start the nuxt builder. But then I am now not able to access nuxt on browser. The server api routes work but the nuxt page routes just show "Nuxt loading…" screen.
How can I use nuxt app in development mode without building it everytime?
It might be a valid use case, sometimes one doesn't want to use two servers for a very small api/ui pair. What I would suggest is also to have a detached mode which works through nuxt/proxy and you could run it whenever you are doing dev work. In detached mode your nuxt works separately and api runs also separately and nuxt imitates above setup via `nuxt/proxy. It's very easy to setup via adding smth like this in nuxt config
modules: [
['#nuxtjs/proxy', { "/api/": { target: 'http://localhost:888/api'} }]
]
In prod you could run as before.
You can use build.parallel, build.cache, and build.hardSource. This will dramatically speed up your build times after the initial build.
I do not recommend this for production builds though. This is how I have it in my code:
nuxt.config.js:
const isDev = process.env.NODE_ENV === "development";
module.exports = {
// ...
build: {
parallel: isDev,
cache: isDev,
hardSource: isDev
},
// ...
};
And in the package.json I set the NODE_ENV to production for the build script:
"scripts": {
"build": "NODE_ENV=production nuxt build"
}
P.S.: You might also need to set build.publicPath for the dev builds.

electron-packager win32 don't open window

I have tried to build a very simple app with Electron, Node and AngularJS. The app is working well till I pack it. After packing, it doesn't show the window.
The ideea was to run a NodeJS process on localhost:5000, then to load the url in ElectronJS main window. When I double-click on .exe file, the process is starting at localhost:5000 and it's working in the browser only, but the Electron window is not shown.
Also, It crash when trying to open with npm run start / npm start
"Windows Script Host. Error: Syntax error. Code: 800A03EA. Source: Microsoft JScript compilation error."
package.json
"scripts": {
"start": "electron ."
}
server.js
'use strict';
const
express = require('express'),
app = express();
app.set('port', (5000));
app.use(express.static('app'));
app.use(express.static('dist'));
app.use(express.static('node_modules'));
app.get("*", (req,res)=>{
res.sendFile(__dirname+"/app/index.html");
});
app.listen(app.get('port'), function() {
console.log("Node server is running at localhost:" + app.get('port'));
});
electron.js
'use strict';
const
electron = require('electron'),
server = require('./server.js'),
{app, BrowserWindow} = electron;
app.on('ready', () => {
var win = new BrowserWindow({
show: false,
width: 800,
height: 600
});
win.loadURL("http://localhost:5000/");
win.on('ready-to-show', function() {
win.show();
win.focus();
});
win.on('closed', () => {
win = null
});
});
I can find the process in task manager.
NodeJS is running on localhost:5000. I can see it in the browser.
I can't see any issues with your code. But I did find a related issue which might be impacting you: https://github.com/electron/electron/issues/7779
Can you start electron in debug mode and check if the ready-to-show event fired?
I discovered that is a versioning incompatibility. At least, in my case was.
The following combination fixed my problem:
"electron": "^3.0.4" with "electron-packager": "^12.2.0"

MERN Stack - Express and React on same port?

I'm working on a project with the MERN (MongoDB, Express, React, Node) stack and I'm having issues when posting data from a form within a React component to an API endpoint defined in Node.js. When I submit the form the browser just shows a CANNOT POST error. I'm pretty confident that if I create an event handler for the form submit within React and handle the POST using a library such as Axios that I could get around this issue.
But ultimately I believe this problem is because the Node backend is running on a different port to the React front end. Is there a way that I can configure my stack so I can use a standard form POST and potentially have the FE and BE running on the same port?
I see that you are running an un-ejected CRA. That means that when you run npm run start from your create-react-app folder you should have react running on port 3000, the default port.
First I would recommend keeping your server and client code into a separate folder with separate package.json files
Now let suppose you have this code in /server/index.js Its straight out of the express example but the route starts with /api and also will run on port 5000. This is very important and you will see why in a minute.
const express = require('express');
const app = express();
app.get('/api/hello', (req, res) => res.send('Hello World!'))
app.listen(5000, () => console.log('Example app listening on port 5000!'))
Now back into your /client folder where I will assume your CRA is, open package.json and add the following lines:
"proxy": {
"/api/*": {
"target": "http://localhost:5000"
}
},
Try now to do a call the server from react with axios for example:
const helloFromApi =
axios
.get('/api/hello')
.then(res => res.data);
Hope it helps
UPDATE 10/21/2019
proxy field in package.json must be a string
"proxy": "http://localhost:5000"
For developing add the following line to the package.json file
"proxy": "http://localhost:{your API port}/"
For production you can setup proxying in app (Express, Nginx, ...) which will serve your static files (React app, styles, etc). Usually using "/api/" mask for determination API request.
I know this is late to answer but could be helpful for anyone looking for one more solution.
This solution could be applied for a react application or a angular application with a node backend at same port and if you are creating your image with the help of Docker.
So whenever you are deploying your project at production level. Just build your angular or react project with the help of npm run build and in your express app just serve the whole build folder with the help of express static.
So your Docker file could be something like this
# The builder from node image
FROM node:8-alpine as web-app
# Move our files into directory name "app"
WORKDIR /app
COPY package.json /app/
RUN cd /app && npm install
COPY . /app
RUN cd /app && npm run build // build your front end
EXPOSE 5000
CMD [ "node", "server.js" ] // start your backend
This will start the backend on port 5000.
Now in app.js file or wherever you have your server file in express of yours, serve the build folder like this
app.use(express.static(path.join(__dirname, 'build')))
If you want to test it in your local. You can create above docker file and change the app.js as shown above to serve static files. And then build and start the docker image like this
docker build . -t web-app
docker run -p 5000:5000 web-app
Now your front end gets build at production level and served from express.
Remember in local you can always start both ports for development and use the feature provided by react or angular like auto reloading after changes in your front end and make development easy.
But ultimately I believe this problem is because the Node backend is running on a different port to the React front end.
Okay,
MERN is fantastic.
My only problem was I couldn't use Mongoose on the React side, I came across this issue and after a few hours, I found a better solution,
No need to put anything on package.json, no need to worry about CORS,
here's a working example of a user registration using mongoose (mongoose will never run on client side, don't waste time, the library modification is time consuming),
start your express server on a port, lets say 3030, and React runs on 3000,
on React side,
constructor(){
...
this.server = server || 'https://my.ip.add.ress:3030'
...
}
register(username, password, signup = true) {
return this.fetch(`${this.server}/server/register`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password,
signup
})
}).then(res => { console.log(res);
this.setToken(res.token) // Setting the token in localStorage
return Promise.resolve(res);
})
}
On Node.JS server (express) side,
Create a folder 'server' and create a file server.js,
var MongoNode = require('mongoosenode') // I created this package for just to test mongoose which doesn't run on React side,
var cors = require('cors'); //use cors for cross-site request
var options = {
key : fs.readFileSync('server.key'),
cert : fs.readFileSync('server.cert'),
};
/*
* Cors Options
*/
var whitelist = config.allowedOrigins //put https://my.ip.add.ress:3000 in the allowedOrigins array in your config file
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
//specify the port
var https_port = config.server.port || 3030;
//use app or any route included to server.js
app.post('/register', cors(corsOptions),function(req, res) {
//Process requests
console.log(req.body); //see if request payload popping up
var mn = new MongoNode('mongodb://username:password#127.0.0.1:27017/databasename')
var user = mn.retrieveModel('User','User').then(async(res) => {
try {
user = res.model;
console.log(user);
user.username = req.body.username
user.password = req.body.password
user.token = token_str //jwt web token to save browser cookie
user.save(function(err) {
if (err) throw err;
console.log('user saved successfully');
res.json({ success: true, token: user.token});
});
}catch(e) {
console.log(e);
}
})
user.save(function(err) {
if (err) throw err;
//console.log('user saved successfully');
res.json({ success: true , message: 'user saved successfully', token : user.token });
});
}
Voila! it's done easily after a few hours of reading.
This is probably what you want:
https://mty-tidjani.medium.com/deploy-nodejs-react-app-on-a-single-port-domain-54a40f1abe16
To summarize, you can set up express to serve the React app as static content from a subdirectory of the server tree. This is the only way I've been able to find to get all content served over a single port, but there may be others. Likely the concept is the same since, as others have mentioned, you can't have two services sharing the same port.

Resources