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';
Related
My goal is to run a typescript project, compiled for the production, launched in cluster mode with pm2.
For development purposes, I used relative paths.
This is the project in its simplest form :
src/app.ts:
import { ModuleA, ModuleB } from 'TestModules';
console.log('Started !');
new ModuleA();
ModuleB();
console.log('Never stop !')
setInterval(() => { }, 1 << 30);
src/TestModules/ModuleA.ts:
export default class TestModuleA{
constructor(){
console.log('New Test Module A !!');
}
}
src/TestModules/ModuleB.ts:
export default function testModuleB(){
console.log('Test Module B called !!');
}
src/TestModules/index.ts:
export { default as ModuleA } from './ModuleA';
export { default as ModuleB } from './ModuleB';
tsconfig.json:
{
"ts-node": {
"files": true
},
"include": ["src/**/*"],
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"baseUrl": "./src",
"sourceMap": true,
"outDir": "./dist/src",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
package.json
{
"name": "nodejs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "if [ \"${NODE_ENV}\" = production ]; then npm run start:prod; else npm run start:dev;fi",
"start:prod": "node -r ts-node/register/transpile-only -r tsconfig-paths/register src/app.js",
"start:dev": "npm run build && node -r ts-node/register/transpile-only -r tsconfig-paths/register dist/src/app.js",
"build": "npm run clean && tsc && npm run copy-files",
"clean": "rm -rf ./dist",
"copy-files": "cp ./package.json ./dist;cp ./tsconfig.json ./dist;"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"typescript": "^4.5.5"
},
"dependencies": {
"ts-node": "^10.7.0",
"tsconfig-paths": "^3.14.1"
}
}
As you can see, I use -r ts-node/register/transpile-only -r tsconfig-paths/register as node parameters to link relative paths. I didn't find a better solution.
Here is the pm2 file to launch it:
{
"apps": [{
"name": "test",
"script": "src/app.js",
"interpreter_args": "-r ts-node/register/transpile-only -r tsconfig-paths/register",
"instances": 2,
"exec_mode": "cluster",
"env": {
"NODE_ENV": "production"
}
}]
}
When I launch that, sometimes it works fine. But most of the time it fails and it generates these errors in ~/.pm2/pm2.log
2022-11-22T09:22:41: PM2 log: App [nix-shell:0] starting in -cluster mode-
2022-11-22T09:22:41: PM2 log: App [nix-shell:0] online
2022-11-22T09:22:41: PM2 log: App [nix-shell:1] starting in -cluster mode-
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module 'ts-node/register/transpile-only'
Require stack:
- internal/preload
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at Module._preloadModules (node:internal/modules/cjs/loader:1282:12)
at loadPreloadModules (node:internal/bootstrap/pre_execution:539:5)
at prepareMainThreadExecution (node:internal/bootstrap/pre_execution:85:3)
at node:internal/main/run_main_module:7:1 {
code: 'MODULE_NOT_FOUND',
requireStack: [ 'internal/preload' ]
}
2022-11-22T09:22:41: PM2 log: App name:nix-shell id:0 disconnected
2022-11-22T09:22:41: PM2 log: App [nix-shell:0] exited with code [1] via signal [SIGINT]
When I launch it by hand with NODE_ENV=production node -r ts-node/register/transpile-only -r tsconfig-paths/register src/app.js it works fine.
It also works fine when I launch it in fork mode :
{
"apps": [{
"name": "test",
"script": "src/app.js",
"interpreter_args": "-r ts-node/register/transpile-only -r tsconfig-paths/register",
"instances": 2,
"exec_mode": "fork",
"env": {
"NODE_ENV": "production"
}
}]
}
I have replicate it in a repl.it sandbox (sorry, you need an account to use it): https://replit.com/join/uxewvlklxf-themadocarina
All sources are in source directory.
The bulidTest.sh will generate a build for cluster and one for fork in testCluster and testFork.
And in each of these folders, you will find a pm2*.config.json that will start it in given mode and a pm2Clear.sh that will clear everything.
I don't fully understand why it fails in cluster mode but works fine in other launching modes.
There must be a better way to handle the relative links in production mode but I didn't find any others despite my searchings.
I am looking to develop a nodejs application using typescript and was wondering if it is possible to do so.
I tried just installing typescript but I get an error when I try to export by default / import from :
(node:1696) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
import test from "./test";
^^^^^^
SyntaxError: Cannot use import statement outside a module
at wrapSafe (internal/modules/cjs/loader.js:1054:16)
at Module._compile (internal/modules/cjs/loader.js:1102:27)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1158:10)
at Module.load (internal/modules/cjs/loader.js:986:32)
at Function.Module._load (internal/modules/cjs/loader.js:879:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:71:12)
at internal/main/run_main_module.js:17:47
i also tried with < ES6 notation (module.exports and require) but it seems that typescript is not supported with this notation...
i'm starting my application using npm link and yyyyyy with the following package.json :
{
"name": "yyyyyy",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"test": "tslint -c tslint.json -p tsconfig.json"
},
"bin": {
"yyyyyy": "./bin/index.ts"
},
"repository": {
"type": "git",
"url": "git+https://github.com/xxx"
},
"author": "xxx",
"license": "ISC",
"bugs": {
"url": "https://github.com/xxx"
},
"homepage": "https://github.com/xxx",
"devDependencies": {
"#types/node": "^17.0.18",
"tslint": "^5.12.1",
"typescript": "^4.5.5"
}
}
To enable ES6 you need to add
'type': 'module
Inside package.json. ones do that you can use import, otherwise you need to use require.
For more info check it here
UPDATE:
Based on your comment, if you want to use import then you need to add in your tsconfig.json:
{
"compilerOptions": {
"esModuleInterop": true,
}
}
Then you can install:
npm install -g ts-node
After this you can run:
ts-node my_server.ts
If not work yet you can update your tsconfig.json change
module: "es6"
To
module: "commonjs"
And removing:
{
"compilerOptions": {
"esModuleInterop": true,
}
}
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
I am able to run mjs files with nodejs using --experimental-modules flag.
node --experimental-modules index.mjs
package.json:
{
"name": "mjs-tests",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "nodemon index.mjs"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^2.4.2",
"uuid": "^3.3.2"
},
"devDependencies": {
"nodemon": "^1.19.1"
}
}
And index.mjs
import http from 'http'
const server = http.createServer((req, res) => {
res.end('hello')
})
const PORT = 5000
server.listen(PORT, () => {
console.log(`🏃♀️ Server is running at http://localhost:${PORT}`)
})
But if I try to
npm run dev
or (with nodemon installed globally)
nodemon index.mjs
I get this error
[nodemon] 1.19.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node index.mjs`
internal/modules/cjs/loader.js:821
throw new ERR_REQUIRE_ESM(filename);
^
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
So, How I can enable support for ECMAScript in nodemon? Or should I use something like esm?
Offcourse yes, All you need to modify your package.json a bit
"scripts": {
"dev": "nodemon --experimental-modules index.mjs"
},
I am studying Full-Stack Redux on the following page: http://teropa.info/blog/2015/09/10/full-stack-redux-tutorial.html#introducing-the-redux-store
After created new server using socket-io in server.js and run app using babel-node, I got the following error:
/home/ubuntu/workspace/src/server.js:15
var io = new _socket2.default().attach(8090);
^
TypeError: _socket2.default is not a function
at startServer (server.js:4:16)
at Object.<anonymous> (index.js:5:1)
at Module._compile (module.js:409:26)
at loader (/home/ubuntu/workspace/node_modules/babel-cli/node_modules/babel-register/lib/node.js:126:5)
at Object.require.extensions.(anonymous function) [as .js] (/home/ubuntu/workspace/node_modules/babel-cli/node_modules/babel-register/lib/node.js:136:7)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at /home/ubuntu/workspace/node_modules/babel-cli/lib/_babel-node.js:161:27
at Object.<anonymous> (/home/ubuntu/workspace/node_modules/babel-cli/lib/_babel-node.js:162:7)
This is the code of server.js
import Server from 'socket.io';
export default function startServer() {
const io = new Server().attach(8090);
};
This is the code of index.js
import makeStore from './src/store';
import startServer from './src/server';
export const store = makeStore();
startServer();
and this is package.json file:
{
"name": "chat-example",
"version": "0.0.0",
"description": "A chat example to showcase how to use `socket.io` with a static `express` server with `async` for control flow.",
"main": "server.js",
"repository": "",
"author": "Mostafa Eweda <mo.eweda#gmail.com>",
"scripts": {
"start": "babel-node index",
"test": "mocha --compilers js:babel-core/register --require ./test/test_helper.js --recursive",
"test:watch": "npm run test -- --watch"
},
"devDependencies": {
"babel-cli": "^6.6.5",
"babel-core": "^6.7.2",
"babel-preset-es2015": "^6.6.0",
"chai": "^3.5.0",
"chai-immutable": "^1.5.3",
"mocha": "^2.4.5"
},
"babel": {
"presets": [
"es2015"
]
},
"dependencies": {
"async": "~0.2.8",
"express": "~3.2.4",
"immutable": "^3.7.6",
"redux": "^3.3.1",
"socket.io": "^0.9.17"
}
I did exactly the same as what was written on the page. Please give me suggestions on this case. Thanks
I found the solution for this problem, I answer here in case somebody need it.
I believe socket.io no longer uses attach function. Instead they use the following code to create socket server:
const io = Server(8090);
You should change socket.io version to at least 1.4.5: it will be fine!
Please refer to the original source code: https://github.com/teropa/redux-voting-server/blob/master/package.json
Good luck!
In your server.js
import Server from "socket.io";
const startServer = port => {
console.log(`Listening on ${port}`);
const io = new Server().attach(port);
};
export default startServer;
In your index.js
import makeStore from "./src/store";
import startServer from "./src/server";
export const store = makeStore();
startServer(8090);