如何为InversifyJS项目配置loader以支持@装饰器语法解析?
问题场景
学习InversifyJS运行官方示例时触发构建报错,核心报错信息如下:
Module parse failed: Unexpected character '@' (30:14) File was processed with these loaders: * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js * ./node_modules/babel-loader/lib/index.js * ./node_modules/react-scripts/node_modules/source-map-loader/dist/cjs.js You may need an additional loader to handle the result of these loaders. | | let Ninja = (_dec3 = injectable(), _dec3(_class3 = class Ninja { > constructor(@inject(TYPES.Weapon) | katana, @inject(TYPES.ThrowableWeapon) | shuriken) {
报错定位到代码中@inject()装饰器位置,现有构建流程无法识别@开头的装饰器语法。
根因说明
- 该问题不需要额外引入webpack loader,本质是当前Babel配置未开启装饰器(Decorator)语法转译能力
- 从报错的loader列表可以判断,当前项目是基于
react-scripts(Create React App)搭建的,默认Babel配置不包含装饰器语法转译插件,遇到@inject、@injectable这类装饰器标记时就会解析失败
解决步骤
根据项目配置状态选择对应方案处理:
场景1:未eject的Create React App项目
推荐用craco修改配置,不需要弹出CRA原生配置:
- 安装必要依赖
npm install @craco/craco @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
- 在项目根目录新建
craco.config.js,写入如下配置:
module.exports = { babel: { plugins: [ ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }] ] } }
- 修改
package.json中的scripts命令,将原有react-scripts调用替换为craco:
{ "scripts": { "start": "craco start", "build": "craco build", "test": "craco test" } }
- 如果是TypeScript项目,需要在
tsconfig.json中开启装饰器编译选项:
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true } }
场景2:自定义webpack配置/已eject的CRA项目
直接修改Babel配置即可:
- 安装缺失的Babel转译插件
npm install @babel/plugin-proposal-decorators @babel/plugin-proposal-class-properties -D
- 在项目根目录的
.babelrc或babel.config.js中添加插件配置,示例如下:
// babel.config.js module.exports = { // 其他原有presets配置保留 plugins: [ ["@babel/plugin-proposal-decorators", { legacy: true }], ["@babel/plugin-proposal-class-properties", { loose: true }] ] }
- 重启本地开发服务、重新执行构建即可正常识别装饰器语法。
注意:两个Babel插件的书写顺序不能颠倒,必须先声明装饰器插件、再声明类属性插件,否则会触发转译顺序错误。
内容的提问来源于stack exchange,提问作者David Cohen
相关产品推荐
相关产品推荐

