带有JS装饰器(阶段3)和Babel的NodeJSJavaScript项目不工作

3bygqnnd  于 2023-01-06  发布在  Babel
关注(0)|答案(1)|浏览(99)
    • bounty将在4天后过期**。回答此问题可获得+100声望奖励。Anatoly希望引起更多人关注此问题。

我正在尝试在我的NodeJS项目中使用JavaScript decorators (stage 3 proposal),它是用JavaScript编写的,但是我很难让这个与nodemon和babel一起工作,这样代码在更改时就会重新编译。
我尝试了两种不同的package.json配置:
第一个:

"scripts": {
    "build": "babel src -d dist",
    "start": "npm run build && nodemon dist/app.js"
  },

它只在第一次工作时,当我对代码进行更改时,它会重新编译,但我看到运行时没有更新,我看到的是旧的结果。
第二种配置:

"scripts": {
    "start-nodemon": "nodemon --exec babel-node src/app.js"
  },

它不适用于装饰器,我得到了以下异常:

@test(true)
    ^

SyntaxError: Invalid or unexpected token

当我拆下装饰器时,它就能工作了。
我的.babelrc配置如下:

{
  "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文件

import MyModule from "./module.js";

const initializedModule = new MyModule();
const description = initializedModule.getDescription();
console.log(description);

decorators.js文件

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;
            };
        }
    }
}

module.js文件:

import {test} from "./decorators.js";

export default class MyModule {
    @test(true)
    getDescription () {
        return "MyModule Test12";
    }
}

如何正确配置项目,以便代码在发生更改时重新编译和重新运行?
包含我的项目的GitHub存储库:babel-test
谢谢大家!

dgiusagp

dgiusagp1#

尝试删除@babel/node并将其替换为***babel-register-esm***:

npm uninstall @babel/core && npm install --save-dev babel-register-esm

然后修改***package. json***文件的脚本部分:

...
"scripts": {
      "build": "babel src -d dist",
      "start": "yarn build && node --experimental-specifier-resolution=node dist/app.js",
      "start-nodemon": "nodemon --watch \"./src/**/*.js\" --ignore \"node_modules\" --exec \"node --loader babel-register-esm src/app.js\""
   },
...

本部分

node --loader babel-register-esm src/app.js

是最重要的,它将节点加载器更改为可以处理ESM特性的节点加载器。
而这一部分:

node --loader babel-register-esm src/app.js

可以启动ESM文件。
预期结果为:

starting getDescription with arguments 
ending getDescription
MyModule Test12

我用Yarn代替了npm,我的package.json是:

{
 "name": "fixstack",
 "version": "1.0.0",
 "main": "dist/app.js",
 "license": "MIT",
 "type": "module",
 "scripts": {
   "build": "babel src -d dist",
   "start": "yarn build && node --experimental-specifier-resolution=node dist/app.js",
   "start-nodemon": "nodemon --watch \"./src/**/*.js\"  --exec \"node --loader babel-register-esm src/app.js\""
 },
   "dependencies": {},
   "devDependencies": {
      "@babel/cli": "^7.20.7",
      "@babel/core": "^7.20.12",
      "@babel/plugin-proposal-decorators": "^7.20.7",
      "@babel/preset-env": "^7.20.2",
      "babel-register-esm": "^1.2.4",
      "nodemon": "^2.0.20"
    }
 }

如果您不想使用babel-register-esm,而想调用"start",则需要修改脚本部分:

"scripts": {
      "build": "babel src -d dist",
      "start": "yarn build && node --experimental-specifier-resolution=node dist/app.js",
      "start-nodemon": "nodemon --watch \"./src/**/*.js\"  --exec \"yarn start\""
  },

或者,如果使用NPM而不是YARN:

"scripts": {
      "build": "babel src -d dist",
      "start": "npm run build && node --experimental-specifier-resolution=node dist/app.js",
      "start-nodemon": "nodemon --watch \"./src/**/*.js\" --exec \"npm run start\""
  },

为什么是"--实验说明符-解析=节点"?
如果你在你的package.json中使用类型模块,并且使用导入和导出而不是CommonJS样式来实现,那么你需要使用这个标志(除非你在你的导入中使用一个显式的路径,你需要在文件名中添加. js扩展名;例如:从'./dir/someFile.js'导入someFunc)。此标志添加到:至少在节点v18(当前LTS)之前需要节点v13.4.0、节点v12.16.0。
您可以在这里获得更多信息

相关问题