Repro here: https://github.com/damianobarbati/yarsk/tree/50ms
Just clone, yarn install and yarn serve:dev.
It fires pm2-runtime which just reports the following:
[WARN] PM2 Daemon is already running
(node:4716) ExperimentalWarning: The ESM module loader is experimental.
(node:4734) ExperimentalWarning: The ESM module loader is experimental.
0 application online, retry = 3
(node:4829) ExperimentalWarning: The ESM module loader is experimental.
0 application online, retry = 2
0 application online, retry = 1
0 application online, retry = 0
With pm2 monit I see several weirds things:
But this does work:
NODE_ENV=development node --experimental-modules index.mjs
Versions:
$ node -v
v10.5.0
$ cat node_modules/pm2/package.json | grep version
"version": "2.10.4",

Hi @damianobarbati
I did a lot of tests today, here are my results :
1) Indeed with your code pm2 or pm2-runtime try to restart app and then stop. It seems your app received a SIGINT signal but i don't know why.
2) It seems .mjs files can work with pm2 (note that I use the latest version on dev branch).
Here is my working sample :
import express from 'express'
let app = express()
app.get('/', function(req, res){
res.send('Home')
});
app.get('/ok', function(req, res){
res.send('Ok')
});
const server = app.listen(process.env.PORT || 5000, function(){
console.log('Server express', 'listening on port', server.address().port);
});
Maybe we should simplify your code to find the root cause of SIGINT signal ?
@wallet77 thanks for helping!
It's not the case, I tried (you can try yourself too) to remove everything from index.mjs and just put the following:
console.log('yo');
setInterval(() => console.log('yo'), 1000);
Nothing happens, just crashing.
SIGINT is popping out from nowhere; if it was being fired from the application then node index.mjs would show the same behaviour but it works without any problem.
PM2 is definitely doing something π
@Unitech can you investigate on this?
@damianobarbati
It seems it's related to watch issue. If you remove "watch" property in package.json, it's working well.
Probably an issue related to of https://github.com/Unitech/pm2/issues/3746 or https://github.com/Unitech/pm2/issues/3693
@wallet77 I donβt think itβs related to the βwatchβ issue.
Hereβs a version of @damianobarbatiβs example with watching explicitly disabled:
// ecosystem.config.js
module.exports = {
apps: [{
name: 'foo',
script: 'index.mjs',
node_args: '--experimental-modules',
instances: 1,
exec_mode: "fork",
wait_ready: false,
watch: false,
listen_timeout: 8000,
kill_timeout: 3000
}]
}
// index.mjs
console.log('yo');
setInterval(() => console.log('yo'), 1000);
$ pm2 start ecosystem.config.js
$ pm2 log
PM2 | App name:foo id:0 online
0|foo | (node:60498) ExperimentalWarning: The ESM module loader is experimental.
PM2 | App [foo] with id [0] and pid [60498], exited with code [0] via signal [SIGINT]
PM2 | Starting execution sequence in -fork mode- for app name:foo id:0
PM2 | App name:foo id:0 online
0|foo | (node:60505) ExperimentalWarning: The ESM module loader is experimental.
PM2 | App [foo] with id [0] and pid [60505], exited with code [0] via signal [SIGINT]
PM2 | Script /srv/foo had too many unstable restarts (16). Stopped. "errored"
$ pm2 show foo
Describing process with id 0 - name foo
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β status β errored β
β name β foo β
β restarts β 15 β
β uptime β 0 β
β script path β /srv/foo β
β script args β N/A β
β error log path β /Users/adam/.pm2/logs/foo-error-0.log β
β out log path β /Users/adam/.pm2/logs/foo-out-0.log β
β pid path β /Users/adam/.pm2/pids/foo-0.pid β
β interpreter β node β
β interpreter args β --experimental-modules β
β script id β 0 β
β exec cwd β /srv/foo β
β exec mode β fork_mode β
β node.js version β N/A β
β watch & reload β β β
β unstable restarts β 0 β
β created at β N/A β
βββββββββββββββββββββ΄ββββββββββββββββββββββββββββββββββββββββ
If you simply remove the --experimental-modules flag from ecosystem.config.js, then it runs successfully and if you run the script without PM2, like @damianobarbati described, it also runs correctly.
Just to reiterate, this is only happening with Node v10.5.0. With v10.4.1, ESM scripts run just fine in PM2. There must be some change to 10.5 that is causing PM2 to issue a SIGINT immediately. Iβll do some more digging myself.
@adamchal you're correct, I forgot to mention that until node v10.4.x everything was working fine and removing --experimental-modules flag and converting to require works.
@Unitech @wallet77
Just tried with pm2 v3.0.0 and node.js v10.6.0 and now I at least see an error reported in pm2 log:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: β¦
at Object.Module._extensions..mjs (internal/modules/cjs/loader.js:724:11)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Proxy.Module._load (internal/modules/cjs/loader.js:530:3)
at /usr/local/lib/node_modules/pm2/lib/ProcessContainer.js:323:23
at /usr/local/lib/node_modules/pm2/node_modules/async/dist/async.js:473:16
at next (/usr/local/lib/node_modules/pm2/node_modules/async/dist/async.js:5329:29)
at /usr/local/lib/node_modules/pm2/node_modules/async/dist/async.js:969:16
at WriteStream.(/usr/local/lib/node_modules/pm2/lib/Utility.js:172:13)
at WriteStream.emit (events.js:182:13)
In pm2/lib/ProcessContainer.js:323:23, I do see the require statement. I tried adding @jdaltonβs standard-things/esm to the ecosystem.config.js:
node_args: '-r esm --experimental-modules',
But, this only suppressed the error log, but did not actually resolve the OP.
I tried every combination of pm2 v3.0.0 v2.10.4 and node.js v10.6.0 v10.5.0 and none of them work. The only thing that works is node.js v10.4.1 with both recent versions of pm2 (including v3.0.0).
Iβm starting to think that beginning with node.js 10.5.0, they have changed the way that CJS scripts (ex. pm2βs ProcessContainer.js) can load ESM scripts through require(). Iβm also surprised that standard-things/esm only suppressed the error messaging, and didnβt actually fix the underlying issue as it has previously before with older versions of pm2.
Hi @adamchal!
The esm loader was recently updated to also error with
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module
when trying to sideload a .mjs file with require from pm2.
In your esm example you don't need to run Node with --experimental-modules though. Using --experimental-modules will bypass the loader. You just need node_args: '-r esm'.
To avoid the sideload issue _(a limitation of the .mjs extension in Node)_ users of esm can just use .js for their ES module files or have an entry .js file that imports the .mjs file with dynamic import().
The use of .mjs in Node is experimental so users should not expect a π― supported experience. I'd also caution users about relying on experimental features in production code.
Update:
Here's an example of using the esm loader to get things to just work:
https://github.com/jdalton/yarsk/commit/7966b2105e1d1adb3b7f43196afbf8f61d665a66
Thanks @jdalton for the great answer.
I think we can close this issue.
@damianobarbati feel free to reopen if necessary.
Thanks @jdalton!
Awesome!
If you all want to create a documentation entry with esm as a workaround for this let me know. I'm happy to review it and provide feedback.
Thanks @jdalton for helping here! However using node_args: '-r esm' results in the following error:
internal/modules/cjs/loader.js:583
throw err;
^
Error: Cannot find module 'esm'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
Full PM2 config file:
const config = require('../package');
module.exports = {
name: config.name,
script: 'index.mjs',
exec_mode: 'cluster',
node_args: '-r esm --harmony --trace-deprecation --max_old_space_size=512',
args: '--color',
max_memory_restart: '512M',
max_restarts: 3,
restart_delay: 3000,
min_uptime: 3000,
error_file: 'logs/error.log',
out_file: 'logs/output.log',
watch: ['package.json', 'index.mjs', 'config/', 'api/', 'services/', 'queries/', '*.mjs'],
env_development: {
NODE_ENV: 'development',
},
env_staging: {
NODE_ENV: 'staging',
},
env_production: {
NODE_ENV: 'production',
}
};
Or on command-line:
$ node -v
v10.6.0
$ node -r esm index.mjs
internal/modules/cjs/loader.js:583
throw err;
^
Error: Cannot find module 'esm'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:581:15)
at Function.Module._load (internal/modules/cjs/loader.js:507:25)
at Module.require (internal/modules/cjs/loader.js:637:17)
at Module._preloadModules (internal/modules/cjs/loader.js:805:12)
at preloadModules (internal/bootstrap/node.js:539:7)
at startup (internal/bootstrap/node.js:226:9)
at bootstrapNodeJSCore (internal/bootstrap/node.js:560:3)
@damianobarbati It sounds silly, but did you add standard-things/esm to your package.json? Alternatively, you can install it globally npm install -g esm.
If you did, you may try @jdaltonβs guidance and rename your index.mjs to index.js. But, based on your invocation, I donβt think this should be a problem. However to avoid issues down the road, I try to only use the .mjs extension when I am running with --experimental-modules. When using standard-things/esm (instead of --experimental-modules), I stick to .js for now.
To avoid the sideload issue (a limitation of the .mjs extension in Node) users of esm can just use .js for their ES module files or have an entry .js file that imports the .mjs file with dynamic import().
@adamchal thanks, I was missing the whole point here: I thought -r esm was some kind of built-in node functionality replacing --experiment-modules and not an external package.
@jdalton the preloaded non-native esm module is indeed very cool and I'll probably move to that even if I'd rather stick to strictly-native solutions even if experimental.
What's the current status over native es6 modules in node? Is there a link to a public discussion going on among the team? :)
@wallet77 the esm module looks good but it's a workaround: are you sure you want to close this without further investigating that unkown SIGINT popping out?
Thank you all guys for the great effort into the community!
Hi @damianobarbati!
What's the current status over native es6 modules in node?
The implementation side is well known. So the hard part is deciding how to paint the API. There's lots of discussions on if Node's ESM support should be maximally minimal _(ship the most basic form, even less that the current WIP implementation)_ so that we can release and build from that. There's others that want various shades of transparent interop _(CJS and ESM working together)_. And there are some that see non-transparent interop _(ESM/CJS separate; require loads CJS; dynamic/static import loads ESM)_ as the way to go.
Is there a link to a public discussion going on among the team?
There are lots of discussions in the working group repo. The working group is comprised of developers _(some Node core, some from npm, some from the ecosystem)_. Feel free to join the discussion.
@jdalton the solution pm2+esm is now broken with [email protected], reverting back to [email protected] to keep going.
Firing the app from command-line with node command works, just PM2+esm does not.
No error or warning is logged from PM2.
@damianobarbati Would you please file an issue on our end so I can cover this with a scenario test to help prevent a regression like this in the future.
Update:
No worries, a bug and repro has been filed.
Update:
v3.0.72 is released :tada:
I don't want esm package, I don't want .js file. It is a regression to disable the parameter "--experimental-modules"!
@jim-king-2000 Node --experimental-modules are exciting for sure, but they are experimental with no support guarantees. In this case any support you previously had was likely the result of a Node implementation bug which is now resolved. As time goes on there will be other changes. I'd caution against relying on experimental features in production code. However, outside of production code, please keep experimenting and trying things out π¬
It is our choice(freedom) to use --experimental-modules in production environment (only this one, no other experimental feature). And we have a reasonable plan to deal with almost any situations node would introduce. So I do think this behavior should be supported even if it could be against by everyone else. Further, from a PM's view point, we should be extremely careful to introduce break changes. Now I update PM2, all my projects fail, I have to spend time investigating & resolving it. That is terrible user experience.
@jim-king-2000
Now I update PM2, all my projects fail, I have to spend time investigating & resolving it. That is terrible user experience.
I believe the fail is out of PM2's control as it was a change in Node's --experimental-modules implementation. This is why I was stressing the wiggliness of experimental features.
It is our pm2.json
{
"apps": [
{
"name": ...,
"script": "./src/app.mjs",
"exec_mode": ...,
"instances": ...,
"node_args" : "--experimental-modules",
"env": {
"NODE_ENV": "production",
"NODE_PORT" : ...,
"NODE_CONFIG_DIR": ...
},
"max-memory-restart": ...
}
]
}
And we got the error message below:
"Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: D:projectstenantsrcapp.mjs"
It works with the previous version of PM2.
I read all the threads above. It seems that the break change has been introduced by node 10.5.0. I'm sorry for my misunderstanding. I had ever thought it had been introduced by PM2.
I still don't like "standard-things/esm" and "*.js" file. So, I'm looking forward to the fix which could lead me back to "--experimental-modules".
By the way, I'm using node 10.7.0. I always use the latest one if possible.
09/27/2018 15:55:39: Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/artemxgruden/projects/p1/provider/functions/unbundled/server/main.mjs
at Object.Module._extensions..mjs (internal/modules/cjs/loader.js:724:11)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Proxy.Module._load (internal/modules/cjs/loader.js:530:3)
at Proxy.Module_load (/usr/local/lib/node_modules/pm2/node_modules/vxx/src/trace-plugin-loader.js:177:33)
at Object.<anonymous> (/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js:75:21)
at Module._compile (internal/modules/cjs/loader.js:689:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
the same result with node v10.11.0 and pm2 3.1.3
in main.mjs just "console.log( 'OK' )"
Use "-r esm".
// pm2.json
{
"apps": [
{
"name": "realTimeSender/fireeye",
"script": "./src/pm2App.js",
"exec_mode": "fork",
"instances": 1,
"node_args" : "-r esm",
"env": {
"NODE_ENV": "production",
"NODE_PORT" : "8091"
},
"max-memory-restart": "300M"
}
]
}
// pm2App.js
import "./app.mjs"
@jim-king-2000 thank you, it works, but is it a workaround until 10 LTS?
@artemxgruden
π Node core and Node Module WG member here. There is no set date for when --experimental-modules will be unflagged. There is a goal of having it done before Node 10 maintenance LTS starts in 2020, but nothing is set in stone.
Hi @jdalton , we do not expect --experimental-modules would be unflagged tomorrow. However, we do expect PM2 can use "node_args" : "--experimental-modules" again tomorrow. We like native things. Transpiler like esm or bable will lead to messy call stack, and it is very hard to map it back to the original line of code.
@jim-king-2000
However, we do expect PM2 can use
"node_args" : "--experimental-modules"again tomorrow.
I hear ya. There's reasons for that not happening.
Transpiler like esm or bable will lead to messy call stack, and it is very hard to map it back to the original line of code
You may dig that esm sanitizes call stacks, provides helpful native-like-or-better errors, transforms code inline _(without pushing it off line)_, and preserves ESM source references when using the Node inspector.
Hi @jdalton , thanks for the reply. I see the "reasons" and find that it is an old comment. I remember we have discussed this topic several times. So, here I can explain thoroughly why I choose to use --experimental-modules in production.
--experimental-modules is for experiment and should NOT be used in production.--experimental-modules brings a lot of benefits, such as simple project structure(no babel, no babel config, no target files), easy to deploy(no transpiling, save a lot of time), correct call stack, etc.--experimental-modules. See the next items.--experimental-modules is quite low. Even if there would be some huge break changes, we could use -r esm temporarily and change our code immediately.In a sentence, we prepare for the worst situation so that we can take the risk of using --experimental-modules online. But no other experimental features would be enabled online. So I really need PM2 support --experimental-modules, if there is no technique issue.
By the way, I never use Node inspector. Since our projects are quite small, I only use logs for debugging.
@jim-king-2000
So, here I can explain thoroughly why I choose to use
--experimental-modulesin production.
No need to defend your choice to use --experimental-modules in production.
As long as you understand there's no obligation for Node, or anyone else, to support it we're π
So I really need PM2 support
--experimental-modules, if there is no technique issue.
The reasons I mentioned above are the blocking technical issue.
@jdalton , thanks for the replay and your patience. Hope the technical issue be conquered soon. We have waited a very long time.
Node 13.2.0 drops "--experimental-modules". How about this issue?
Most helpful comment
Node 13.2.0 drops "--experimental-modules". How about this issue?