I have the following server code for a react app (created from create react app):
import config from './../config/config'
import app from './express'
import mongoose from 'mongoose'
// Connection URL
mongoose.Promise = global.Promise
mongoose.connect(config.mongoUri)
mongoose.connection.on('error', () => {
throw new Error(`unable to connect to database: ${mongoUri}`)
})
app.listen(config.port, (err) => {
if (err) {
console.log(err)
}
console.info('Server started on port %s.', config.port)
})
The other server side files uses "Import" as well..
When trying to run it by node server.js I am getting the following error:
(function (exports, require, module, __filename, __dirname) { import config from
'./../config/config'
^^^^^^
SyntaxError: Unexpected token import
How should I start my react app so the client side would run and also this server.js server from the begining ?, I would usually use the following in package.json:
"dev": "concurrently \"npm run react\" \"npm run server\"",
"react": "react-scripts start",
"server": "node src/server/index.js",
But the node command won't work in this case. I tried this with no success:
Using Import In NodeJS server
The problem that you have is because ESM (import/export) was introduced to Node in version 12. You have two options: if you are using node v12 or higher you can follow this link.
If you are using a lower version of node you'll have to use babel to transpile your code. Check this link.
Related
I modified my server.js(by looking at Vercel site)
connectDB();
const routes = require('./routes');
const blogpost = require('./routes/blogpost');
const auth = require('./routes/auth');
const users = require('./routes/users');
const comments = require('./routes/comments');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare()
.then(() => {
const server = express();
server.use(handler);
server.use(express.json());
server.use(cookieParser());
server.use(mongoSanitize());
server.use(helmet());
server.use(xss());
if (process.env.NODE_ENV === 'development') {
server.use(morgan('dev'));
}
const limiter = rateLimit({
windowMs: 10 * 60 * 1000,
max: 100,
});
server.use(limiter);
server.use(hpp());
server.use(cors());
server.use('/api/v1/auth', auth);
server.use('/api/v1/blogpost', blogpost);
server.use('/api/v1/users', users);
server.use('/api/v1/comments', comments);
const PORT = process.env.PORT || 5000;
server.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`));
});
Backend and frontend are separate folders,so I figured out that concurrently help me solve this.
My package.json
"scripts": {
"start": "node server",
"client": "cd ..//frontend && npm run dev",
"server": "nodemon server",
"dev": "concurrently --kill-others-on-fail \"npm run client\" \"npm run server\"",
"test": "jest"
},
I got error
internal/modules/cjs/loader.js:1083
[1] throw err;
[1] ^
[1]
[1] Error: Cannot find module 'react'
[1] Require stack:
[1] - /home/jholmes/blog_mongo/backend/node_modules/next/dist/next-server/server/render.js
[1] - /home/jholmes/blog_mongo/backend/node_modules/next/dist/next-server/server/nextserver.js
[nodemon] app crashed - waiting for file changes before starting...
[0] ready - started server on http://localhost:3000
[0] event - compiled successfully
I can signup at the frontend but no data is passed to the backend.
What is wrong with my configuration?
From your explanation and package.json file, it seems you were creating a microservices application where the backend standalone from the frontend.
But your server.js file shows that you were creating a monolithic application where the frontend and backend is on the same instance.
The error message explains that to do Server Side Rendering (SSR), it needs reactjs library to render the frontend, unfortunately couldn't find reactjs because your backend supposed to not having reactjs.
If you want to create microservices application, then the way frontend connect to backend is via APIs. If you tend to have monolithic application, then you need to read the SSR documentation of NextJS.
I have a simple nodeJS server and I have it set to watch for changes on the code using tsc --watch. What I was wondering is how do I set up express to reload itself when I make changes to the code (note I am asking specifically on Windows)?
I am presuming it is something to do with chokidar in which I have the following index.ts code
import AWS from "aws-sdk";
import express from "express";
import chokidar from "chokidar";
console.log(AWS.S3);
const route = express.Router();
route.get("/signed-url-put-object", async (req, res) => {
console.log(process.env)
});
if (process.env.NODE_ENV !== "production") {
const watcher = chokidar.watch("./index.js");
watcher.on("all", ()=> {
console.log("reloading...");
// what do I do here?
})
}
express().listen(3000, ()=>console.log('listening'))
Try this snippet that I took from this repo.
watcher.on('ready', function() {
watcher.on('all', function() {
console.log("Clearing /server/ module cache from server");
Object.keys(require.cache).forEach(function(id) {
if (/[\/\\]server[\/\\]/.test(id)) delete require.cache[id];
});
});
});
Keep in mind you might run into some issues.
I usually use nodemon and concurrently for my hot reloading needs when both front-end and back-end are in the same repo.
With concurrently and nodemon, I would have something like this.
"scripts": {
"start": "concurrently \"yarn start:fe\" \"yarn start:watch\"",
"start:watch": "nodemon --inspect=5858 ./server/server.ts",
"start:be": "set TS_NODE_PROJECT=./tsconfig.server.json && node --inspect=5858 -r ts-node/register ./server/server.ts",
"start:fe": "react-app-rewired start --scripts-version react-scripts",
}
I am converting the code to use nodemon to leverage TypeScript.
In my package.json:
"scripts": {
"serve-fake-api": "nodemon fake-api/server.ts --watch 'fake-api/*.*' ",
"serve-vue": "vue-cli-service serve",
"serve": "concurrently -k \"npm run serve-fake-api\" \"npm run serve-vue\"",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
and the fake-api/server.ts file:
import { readFileSync } from 'fs';
import { create, defaults, bodyParser, rewriter, router as _router } from 'json-server';
import { join } from 'path';
const server = create();
const defaultMiddleware = defaults();
// It is recommended to use the bodyParser middleware before any other middleware in your application
server.use(bodyParser);
server.use(defaultMiddleware);
// Define custom routes (routes.json)
const routes = JSON.parse(readFileSync(join(__dirname, 'routes.json'), "utf8"));
server.use(rewriter(routes));
// Add custom middleware before JSON Server router
const customMiddleware = require(join(__dirname, 'middleware.ts'));
server.use(customMiddleware);
// This is where `json-server`'s magic happens ;)
const router = _router(join(__dirname, 'db.json'));
// Start the application by listening to port 3000,
// Although this won't print the nice starting message you see when
// running `json-server` as CLI command, it still runs the app correctly.
server.use(router);
server.listen(3000, () => {
console.log('JSON Server is running')
});
but when running npm run serve:
[0] C:\Users\eperret\Desktop\tabulator-tests\fake-api\server.ts:1
[0] import { readFileSync } from 'fs';
[0] ^^^^^^
[0]
[0] SyntaxError: Cannot use import statement outside a module
I googled a bit and ended up here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
Is there a workaround to keep using this kind of import?
I answered to my question on the related GitHub issue thread:
https://github.com/remy/nodemon/issues/1625#issuecomment-560115741
I solved my issue by changing the module type with commonjs in tsconfig.json instead of esnext:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
...
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.
I know I'm missing something here. I'm running node through babel and using koa2 on my server. Fairly new to this so not quite sure what I'm missing, as I've been referencing a lot of things online.
Versions: Node 6.4, babel-core 6.14.0, babel-polyfill": 6.13.0
Getting a fun error. Looks like a generator is not being produced somehow.
assert.js:89
throw new assert.AssertionError({
^
AssertionError: app.use() requires a generator function
at Application.app.use (/Users/administrator/Dropbox/Development/moonlite/moonlitewww/node_modules/koa/lib/application.js:106:5)
Here's what I'm running off of:
Package.json
"start:dev": "node -r babel-core/register index.js",
.Babelrc
{
"presets": ["es2015", "react", "stage-3"]
}
Index.js
require("babel-polyfill");
import nodeServer from "./web-server.js";
var config = {
prod: process.env.NODE_ENV === "production",
serverPort: process.env.PORT || 3000
};
nodeServer(config);
web-server.js
import Koa from 'koa';
import koaRouter from 'koa-router';
import send from 'koa-send';
import serve from 'koa-serve';
import logger from 'koa-logger';
const router = koaRouter();
const app = new Koa();
export default (config) => {
app.use(logger());
app.use(serve(__dirname + '/client/build'));
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(config.serverPort, () => {
console.log('Server running on port:' + config.serverPort);
});
};
What am I missing here?
Noob mistake on my part. I was merging the packages from another package.json file in, and somehow koa got reverted back to the 1.x branch. Was chasing a red haring thinking it was babel.
If you see a similar error double check your koa version, and upgrade to koa2 like so:
npm install koa#next --save
"NOW YOU KNOW, AND KNOWING IS HALF THE BATTLE..."