Cannot use import statement outside modules - node.js

I am using NextJS with typescript, mongo Atlas, mongoose, node and express.
I am getting the following error when I run node pages/server:
I have uploaded my package.json file and have added babel as well
import express from 'express'; ^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1072:16)
at Module._compile (internal/modules/cjs/loader.js:1122:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
at Module.load (internal/modules/cjs/loader.js:1002:32)
at Function.Module._load (internal/modules/cjs/loader.js:901:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
at internal/main/run_main_module.js:18:47
This is my server.js code:
import express from 'express';
import { connect, connection } from 'mongoose';
import morgan from 'morgan';
import path from 'path';
const app = express();
const PORT = process.env.PORT || 8080;
//Success
import routes from './routes/api.tsx';
const MONGODB_URI = 'xxx';
// const routes=require('./routes/api')
connect(MONGODB_URI ||'mongodb://localhost/success', {
useNewUrlParser: true,
useUnifiedTopology: true
});
connection.on('connected', () => {
console.log('Mongoose is connected');
});
const newBlogPost = new BlogPost(data); //instance of the model
app.use(morgan('tiny'));
app.use('/',routes)
app.listen(PORT, console.log(`Server is starting at ${PORT}`));
package.json file
{
"name": "la-sheild",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "next",
"build": "next build",
"start": "babel-node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"#types/express": "^4.17.2",
"#types/mongoose": "^5.7.1",
"axios": "^0.19.2",
"concurrently": "^5.1.0",
"express": "^4.17.1",
"mongoose": "^5.9.1",
"morgan": "^1.9.1",
"next": "^9.2.2",
"node": "^13.8.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
},
"devDependencies": {
"#babel/core": "^7.8.4",
"#babel/preset-env": "^7.8.4",
"#babel/register": "^7.8.3",
"#types/node": "^13.7.4",
"#types/react": "^16.9.21",
"babel-cli": "^6.26.0",
"typescript": "^3.7.5"
},
"proxy": "http://localhost:8080"
}

Since Node v12, you can use either the .mjs extension or set "type": "module" in your package.json.
And you need to run node with the --experimental-modules flag.
node --experimental-modules server.mjs
You can check the SO link
Or you can create .babelrc file in the root of your project.
Add following (and any other babel presets you need, can be added in this file):
{
"presets": ["env"]
}
Install babel-preset-env using
npm install babel-preset-env
npm install babel-cli -g
# OR
yarn add babel-preset-env
yarn global add babel-cli
Now, go to the folder where your server.js file exists and
run using:
babel-node fileName.js
Or you can run using npm start by adding following code to your package.json file:
"scripts": {
"start": "babel-node server.js"
}
There is a tutorial link for Set Up Next.js with a Custom Express Server + Typescript on a medium that will be very helpful for you.

The following solution worked for me;
install needed packages
npm install nodemon #babel/core #babel/node #babel/preset-env -D
create a .babelrc file in the working directory and paste the following in it
{
"presets": [
"#babel/preset-env" ]
}
lastly, add the code below to "scripts" in package.json
"dev": "nodemon —exec babel-node server.js"
where server.js is your file in this case.
Hope this works :)

Here is the solution based on ts-next-express.
npm i --save ts-node
create another config file for express because node is using common.js module but if you check the tsconfig.json you will see this:"module": "esnext"
tsconfig.server.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"outDir": "dist",
"noEmit": false
},
"include": ["server"]
}
set the script as follow:
"start": "ts-node --project tsconfig.server.json server.ts"

I was getting same error "SyntaxError: Cannot use import statement outside a module" first i add tye : module but still face another error. Finaly its work for me the issue was this i was running my Driver.js file that why i was getting this issue. i run my Driver.ts file its work ok for me.
enter image description here
But after run my with extenstion .ts file its work.
enter image description here

I had my index.ts importing an exported var from my schema.js file.
I was doing an import inside this schema.js file
It was this second import causing the 'Cannot use import statement outside modules'.
Finally renaming the file from schema.js to schema.ts solved the issue.\

"scripts": {
"start": "babel-node server.js"
}
adding above worked for me

Related

Express + Node 18 + TypeScript - dev server won't run

Problem:
When I run this command: npx ts-node-dev --respawn --transpile-only index.ts, I get this error:
rob#hi~/dev/robrendellwebsite$ npx ts-node-dev --respawn --transpile-only index.ts
[INFO] 06:23:55 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.1, typescript ver. 4.8.4)
Compilation error in /home/rob/dev/robrendellwebsite/index.ts
Error: Must use import to load ES Module: /home/rob/dev/robrendellwebsite/index.ts
at Object.<anonymous> (/home/rob/dev/robrendellwebsite/index.ts:1:7)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._compile (/home/rob/dev/robrendellwebsite/node_modules/source-map-support/source-map-support.js:568:25)
at Module.m._compile (/tmp/ts-node-dev-hook-6490566241511986.js:69:33)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at require.extensions..jsx.require.extensions..js (/tmp/ts-node-dev-hook-6490566241511986.js:114:20)
at require.extensions.<computed> (/tmp/ts-node-dev-hook-6490566241511986.js:71:20)
at Object.nodeDevHook [as .ts] (/home/rob/dev/robrendellwebsite/node_modules/ts-node-dev/lib/hook.js:63:13)
at Module.load (node:internal/modules/cjs/loader:1037:32)
at Function.Module._load (node:internal/modules/cjs/loader:878:12)
[ERROR] 06:23:55 Error: Must use import to load ES Module: /home/rob/dev/robrendellwebsite/index.ts
What I've tried:
adding "type":"module" to my package.json:
Here's my package.json
{
"name": "robrendellwebsite",
"version": "1.0.0",
"description": "nodejs backend api for robrendellwebsite",
"main": "index.js",
"engines": {
"node": "18.x"
},
"type": "module",
"scripts": {
"start": "node dist/index.js",
"build": "tsc",
"postinstall": "npm run build",
"dev:slow": "ts-node index.ts",
"dev": "ts-node-dev --respawn --pretty --transpile-only index.ts",
"test": "jest",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"update-common": "npm install robrendellwebsite-common"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Robert-Rendell/robrendellwebsite.git"
},
"author": "Robert Rendell",
"license": "ISC",
"bugs": {
"url": "https://github.com/Robert-Rendell/robrendellwebsite/issues"
},
"homepage": "https://github.com/Robert-Rendell/robrendellwebsite#readme",
"devDependencies": {
"#babel/core": "^7.19.6",
"#babel/preset-env": "^7.19.4",
"#babel/preset-typescript": "^7.18.6",
"#types/cors": "^2.8.12",
"#types/express": "^4.17.14",
"#types/jest": "^27.0.2",
"#types/morgan": "~1.9.3",
"#types/node": "^18.11.8",
"#types/uuid": "^8.3.1",
"#typescript-eslint/eslint-plugin": "~5.2.0",
"#typescript-eslint/parser": "~5.2.0",
"babel-jest": "^27.3.1",
"googleapis": "^108.0.1",
"husky": "^8.0.1",
"jest": "^27.3.1",
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"typescript": "^4.8.4"
},
"dependencies": {
"aws-sdk": "^2.1243.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-rate-limit": "^6.6.0",
"helmet": "^6.0.0",
"morgan": "~1.10.0",
"robrendellwebsite-common": "^1.2.0",
"uuid": "^8.3.2"
}
}
Here's my index.ts:
import { config } from 'dotenv';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import { HomePage } from './src/pages/home/home.page';
import SudokuAPI from './src/pages/sudoku/sudoku.page';
import TechTestUniDataAPI from './src/pages/technical-tests/uni-data-291121/uni-data-291121.page';
import { NatureRouting } from './src/pages/photos-ive-taken/nature/nature.routing';
import { WildFlowersPage } from './src/pages/photos-ive-taken/nature/pages/wild-flowers.page';
import { ArachnidsPage } from './src/pages/photos-ive-taken/nature/pages/arachnids.page';
import { InsectsPage } from './src/pages/photos-ive-taken/nature/pages/insects.page';
import { LichenPage } from './src/pages/photos-ive-taken/nature/pages/lichen.page';
import { FungiPage } from './src/pages/photos-ive-taken/nature/pages/fungi.page';
config();
if (!process.env.PORT) {
process.exit(1);
}
// Heroku exposes PORT env var by default
const PORT = process.env.PORT || 80;
const app = express();
// app.use(helmet());
app.use(cors());
app.use(morgan('combined'));
app.use(express.json());
// === Rate Limiting =======================
// only if you're behind a reverse proxy
// eg. (Heroku, Bluemix, AWS if you use an ELB, custom Nginx setup, etc)
app.enable('trust proxy');
// const limiter = RateLimit({
// windowMs: 15 * 60 * 1000, // 15 minutes
// max: 100, // limit each IP to 100 requests per windowMs
// });
// apply to all requests
//app.use(limiter);
// =========================================
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
// === Routes =========================================
app.get('/', HomePage);
app.get('/', HomePage);
app.get(NatureRouting.WildFlowers, WildFlowersPage);
app.get(NatureRouting.Arachnids, ArachnidsPage);
app.get(NatureRouting.Insects, InsectsPage);
app.get(NatureRouting.Lichen, LichenPage);
app.get(NatureRouting.Fungi, FungiPage);
app.get(SudokuAPI.Routes.getSudoku, SudokuAPI.getSudoku);
app.get(SudokuAPI.Routes.getSudokuLeaderboard, SudokuAPI.getSudokuLeaderboard);
app.post(SudokuAPI.Routes.postSudokuList, SudokuAPI.postSudokuList);
app.post(SudokuAPI.Routes.postSubmission, SudokuAPI.postSubmission);
app.post(SudokuAPI.Routes.postGenerateSudoku, SudokuAPI.generateSudoku);
app.post(SudokuAPI.Routes.postGenerateSudokuCallback, SudokuAPI.generateSudokuCallback);
app.get(TechTestUniDataAPI.Routes.getDashboardGraphs, TechTestUniDataAPI.getDashboardGraphs);
The error in my case was to do with a dependency: "robrendellwebsite-common": "^1.2.0", which wasn't configured correctly and caused transpiled JavaScript to be different to the project that imported it. Didn't get to the root cause exactly, but the answer in this case was to rollback. This is a lesson in committing small changes at a time so you can easily isolate where you went wrong.

Why does bundling Node.js backend api with Webpack fails with "TypeError: i is not a function"?

I'm trying to create a docker container to house my front (React) and backend (express REST service) but my efforts to bundle the backend with Webpack are failing to execute claiming that "i is not a function". I should be clear that this is not running in Docker yet. I'm just trying to execute it in my dev environment manually first.
I simply webpack, then try running the bundled js directly (e.g. node ./dist/server.bundle.js). Here's my webpack.config.js:
{
"name": "test-backend",
"version": "1.0.0",
"description": "Test Backend",
"scripts": {
"start": "nodemon ./server.js",
"build": "webpack",
"debug": "node --inspect ./server.js",
"debug-brk": "node --inspect-brk ./server.js"
},
"dependencies": {
"body-parser": "1.19.0",
"cors": "2.8.5",
"express": "4.17.1",
"express-jwt": "5.3.3",
"ioredis": "4.17.3",
"jsonwebtoken": "8.5.1",
"ldapjs": "2.0.0",
"ldapjs-client": "0.1.1",
"lodash": "4.17.19",
"node-cache": "5.1.0",
"redis": "3.0.2",
"rootpath": "0.1.2",
"superagent": "5.2.2",
"uuid": "8.2.0"
},
"devDependencies": {
"nodemon": "2.0.4",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack-node-externals": "^2.5.2"
}
}
The error line/position points to what looks like an import for "crypto", and others, in my bundled backend js:
TypeError: i is not a function
at Object.<anonymous> (/var/test/test-services/images/test-unified/backend/dist/server.bundle.js:333:90327)
at n (/var/test/test-services/images/test-unified/backend/dist/server.bundle.js:1:110)
...
...var r=i("crypto"),a=i("fs"),o=i("util"),s=i("path"),...
I feel like the webpacking failed to include necessary node modules. It's most likely that I'm missing something from my webpack.config.js:
const path = require('path');
module.exports = {
entry: './server.js',
mode: 'production',
target: 'node',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'server.bundle.js'
}
};
There are some examples and tutorials on bundling server side js, but they're examples and just include simple server.js code without Express and other modules.
Any tips are greatly appreciate. Thank you.
I'll close this question by sharing my webpack.config.js change:
const path = require('path');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: './server.js',
mode: 'production',
target: 'node',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'server.bundle.js'
},
externals: [nodeExternals()]
};
Using webpack-node-externals will basically expect that node_modules be locally relative and not try to bundle them in. Your source will be, but not the external modules. I can live with that.
To answer jonsharpe's Q as to why bundle a Node.js app was primarily for simplicity of my docker container and in a way security by packing and optimizing my application. I have a bunch of various components, services and controllers in the app and it's all one file now.
I found this guide after the fact that mentions the issue with require and external nodes. She also used webpack-node-externals: https://jasminexie.github.io/using-webpack-for-node-backend/

SyntaxError: Unexpected token import - Express

I have this in my index.js
import express from 'express'
import data from './data/data'
const app = express();
const PORT = 3000;
app.listen(PORT, () =>
console.log(`Your server is running on ${PORT}`)
);
This is my package.json
{
"name": "express-app",
"version": "1.0.0",
"description": "backend provisioning",
"main": "app.js",
"scripts": {
"start": "nodemon ./index.js --exec babel-node -e js"
},
"author": "B",
"license": "ISC",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-stage-0": "^6.24.1"
},
"dependencies": {
"express": "^4.16.3"
}
}
When I run nodemon , I got
[nodemon] 1.17.3
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node index.js`
/Users/b/Desktop/express-app/index.js:1
(function (exports, require, module, __filename, __dirname) { import express from 'express'
^^^^^^
SyntaxError: Unexpected token import
at createScript (vm.js:80:10)
at Object.runInThisContext (vm.js:139:10)
at Module._compile (module.js:607:28)
at Object.Module._extensions..js (module.js:654:10)
at Module.load (module.js:556:32)
at tryModuleLoad (module.js:499:12)
at Function.Module._load (module.js:491:3)
at Function.Module.runMain (module.js:684:10)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3
[nodemon] app crashed - waiting for file changes before starting...
Did I forget to do anything to be able to use the import command?
I did this :
npm install --save-dev babel-cli babel-preset-env babel-preset-stage-0
npm install express
nodemon
same result
I also try this
rm -rf node_modules/
npm install
nodemon
same result
.babelrc
{
"presets":[
"env",
"stage-0"
]
}
NodeJS supports import natively only experimentally, and only if your script has the .mjs extension.
That's why the start in your package.json is referring to babel-node, which transpiles ES6 code into classic JS on-the-fly before running it. But I doubt even that command will work, because you're not passing any presets to babel to run the script. Try this command:
nodemon --exec babel-node --presets env index.js
[OR]
Rename your file to have .mjs extension, then run this:
nodemon --experimental-modules index.mjs
This happens if you have lower version of node. please upgrade it to at least v10.0
I just want to give a overview who came to this situation, becouse its very painfull.
Firstly in ES6 there is no support for import Express or require express together and inspite of this we can implement it with esm or dynamic-babel
What is reason, James explained in here Update on ES6
and the reason Node.js, TC-39, and Modules
In my case i have using import and require in the same project and also i need to debugging and hot-reloading features, i have assaulted with this error and figureout a way.
first i decide to use nodemon to debugging and hot reloading in my package.json
like below:
"debug-api": "nodemon --inspect -r esm src/api/server/index.js",
"debug-store": "nodemon --inspect -r esm dist/store/server/index.js",
"debug": "concurrently npm:debug-*" // if you add --source-maps to here it will make HMR
i have deleted .babelrc file and i have defined loaders on just one place in the webpack like below
use: {
loader: 'babel-loader',
options: {
presets: ["#babel/react", ["#babel/preset-env", {
"useBuiltIns": "usage",
"shippedProposals": true,
"debug": true,
"include": ["es7.promise.finally", "es7.symbol.async-iterator", "es6.array.sort"],
"modules": false,
}]
],
plugins: [
["#babel/plugin-transform-regenerator", {
"asyncGenerators": true,
"generators": true,
"async": true
}],
[
"#babel/plugin-transform-runtime",
{
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": true
}
],
"#babel/plugin-proposal-class-properties",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-object-rest-spread",
"react-hot-loader/babel"]
}
}
},
And at the and i can pick-up process from vscode debugging console, launch.json like below
{
"type": "node",
"request": "attach",
"name": "Node: Nodemon",
"processId": "${command:PickProcess}",
"restart": true,
"protocol": "inspector",
},
Now it has been working with debugging and hotreloading, if there is a overlooked problem or feature please comment
use require instead of import. this might help
for example :
write this :
const express = require('express')
instead of:
import express from 'express'
it's better to use
const express = require('express');
instead of
import express from 'express';

Babel 7 with Express

I am trying to use Babel 7 with Express and I have resolved all errors that have come my way, but I cannot get the Express server to start. I'm unsure if this is because there is no substitute (to my knowledge) for babel-node or if I am doing something wrong.
Here is my package.json
{
"name": "MEAN-Package",
"version": "0.1.0",
"description": "A package for the exercises",
"main": "index.js",
"author": "Chasen Bettinger",
"license": "MIT",
"scripts": {
"start": "nodemon server.js --exec babel"
},
"dependencies": {
"connect": "^3.6.6",
"express": "^4.16.3",
"mongodb": "^3.0.4"
},
"devDependencies": {
"#babel/cli": "^7.0.0-beta.42",
"#babel/core": "^7.0.0-beta.42",
"#babel/preset-env": "^7.0.0-beta.42",
"nodemon": "^1.17.2"
}
}
Here is server.js
import express from "express";
const app = express();
app.use("/", (req, res) => {
res.status(200).send("Hello World");
});
app.listen(3000);
console.log("Server running at http://localhost:3000/");
export { app as default };
My .babelrc file
{
"presets": ["#babel/preset-env"]
}
Console output:
Trying to learn express so any help is appreciated!
You should you babel-node instead of babel. Follow these steps to fix it:
Add babel-node:
yarn add #babel/node --dev
2- Change your start script on package.json to:
"scripts": {
"start": "nodemon server.js --exec babel-node",
}
You should not be using babel-node in production. It is unnecessarily heavy, with high memory usage due to the cache being stored in memory. You will also always experience a startup performance penalty as the entire app needs to be compiled on the fly.
the correct way is:
npm i -D #babel/node
and
"scripts": {
"start": "nodemon server.js --exec babel-node",
}
npm run start

How to add NODE_PATH to webpack in package.json?

How do I add NODE_PATH to webpack in package.json?
Part of my packcage.json:
"dependencies": {
"axios": "^0.16.2",
"cross-env": "^5.0.1",
"koa": "^2.3.0",
"koa-mount": "^3.0.0",
"koa-static": "^4.0.1",
"koa-trie-router": "^2.1.5",
"mongodb": "^2.2.31",
"nuxt": "^1.0.0-rc3",
"socket.io": "^2.0.3"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"backpack-core": "^0.4.1"
},
"scripts": {
"test": "mocha --harmony",
"dev": "NODE_PATH=./app backpack dev",
"build": "nuxt build && backpack build",
"start": "cross-env NODE_ENV=production NODE_PATH=./app node build/main.js"
},
backpack.config.js:
module.exports = {
webpack: (config, options, webpack) => {
config.entry.main = './server/index.js'
return config
}
}
In my server.js:
import Koa from 'koa'
import { Nuxt, Builder } from 'nuxt'
import socket from 'socket.io'
import http from 'http'
import config from 'config' // this is './config' without NODE_PATH=./app
Error at npm run dev:
This dependency was not found:
* config in ./server/index.js
But if I run npm start, it is working fine.
Any ideas?
You should edit your webpack configuration to include the app directory for resolving modules.
Based on your code example, it would look like this:
module.exports = {
webpack: (config, options, webpack) => {
config.entry.main = './server/index.js'
config.resolve.modules = ['./app']
return config
}
}
See webpack documentation for details:
https://webpack.js.org/configuration/resolve/#resolve-modules

Resources