I am trying to use JavaScript decorators (stage 3 proposal) in my NodeJS project, which is written in JavaScript. However, I am having trouble getting this to work with nodemon and babel together, so that the code will be recompiled when it is changed.
I tried two different package.json
configurations:
First one:
"scripts": {
"build": "babel src -d dist",
"start": "npm run build && nodemon dist/app.js"
},
It works the first time only, when I made a change in code it recompiles but I see that runtime is not updated, I see the old result.
Second configuration:
"scripts": {
"start-nodemon": "nodemon --exec babel-node src/app.js"
},
It doesn't work with decorators and I get the following exception:
@test(true)
^
SyntaxError: Invalid or unexpected token
When I remove the decorator it works.
My .babelrc
config is following:
{
"presets": [
[
"@babel/preset-env",
{
"modules": false
}
]
],
"env": {
"development": {
"sourceMaps": "inline",
"retainLines": true
}
},
"plugins": [
"@babel/plugin-syntax-top-level-await",
["@babel/plugin-proposal-decorators", {
"version": "2022-03"
}]
]
}
app.js
file
import MyModule from "./module.js";
const initializedModule = new MyModule();
const description = initializedModule.getDescription();
console.log(description);
decorators.js
file
export function test(test){
return function (value, { kind, name }) {
if (kind === "method" || kind === "getter" || kind === "setter") {
return function (...args) {
console.log(test);
console.log(`starting ${name} with arguments ${args.join(", ")}`);
const ret = value.call(this, ...args);
console.log(`ending ${name}`);
return ret;
};
}
}
}
and module.js
file:
import {test} from "./decorators.js";
export default class MyModule {
@test(true)
getDescription () {
return "MyModule Test12";
}
}
How can I properly configure my project, so code will be recompiled and rerun upon changes?
GitHub repository with my project: babel-test
Thank you!
Try removing @babel/node and replacing it with babel-register-esm:
Then modify the package.json file, the scripts section:
This part
is the most important. It changes the node loader to one that can process ESM features.
And this part:
makes it possible to start a the ESM files.
The expected result is:
I used yarn instead of npm, and my package.json is:
If you don't want to use babel-register-esm and want to call "start", you need to modify the scripts section:
Or if you are using NPM instead of YARN:
Why "--experimental-specifier-resolution=node"?
If you are using type module in your package.json and implementing using import and export instead of CommonJS style, then you need to use this flag (except you use an explicit path on your imports, you need to add the .js extension to the filename; i.e: import someFunc from './dir/someFile.js'). This flag was added in: Node v13.4.0, Node v12.16.0, required until Node v18 (current LTS) at least.
You could get more information here