React学习笔记 - Create React App 开启装饰器语法

2,260 阅读2分钟

使用 MobX 或 高阶组件时,会用到装饰器语法,但直接使用装饰器语法会报错

Support for the experimental syntax 'decorators-legacy' isn't currently enabled

这是因为装饰器语法是默认未开启的,需要安装 babel 对应的插件来解决

npm install @babel/plugin-proposal-decorators --save-dev

并在 package.json 中做如下配置

// package.json
{
  // ...
  "babel": {
    "plugins": [
      [
        "@babel/plugin-proposal-decorators",
        {
          "legacy": true
        }
      ]
    ],
    "presets": [
      "react-app"
    ]
  },
}

重新 npm run start 即可使用装饰器语法

Create-React-App 中不生效的解决办法

使用新版的 Create-React-App 创建的项目,在 package.json 中做上面的配置后,使用装饰器语法依然会报错

猜测原因是由于 CRA 项目无法读取到 package.json 中添加的配置

目前找到如下两种解决方案:

eject

使用 CRA 创建的项目,在 script 中有 eject 命令,运行该命令可以将 CRA 项目的配置项暴露出来

npm run eject

而后会发现项目中多了一个 config 目录,且各个配置文件都暴露出来了

此时再在 package.json 中添加上面的 babel 插件配置后,就可以生效并使用装饰器语法了

  • PS 此种方法不可逆,且无法后续对 CRA 项目升级,要慎用

react-app-rewired + customize-cra

安装 react-app-rewired 插件后,在根目录下可以创建一个 config-overrides.js 的文件用于修改配置项,项目启动的时候会现在这个文件里读取数据,对 webpack 里的配置进行整合后启动

customize-cra 是依赖于 react-app-rewired 的库,通过 config-overrides.js 来修改底层的 webpack,babel 等配置

首先安装两个插件

npm install react-app-rewired customize-cra --save

package.json 中的 script 做如下修改,即将部分命令的 react-scripts 改为 react-app-rewired

/* package.json */

"scripts": {
-   "start": "react-scripts start",
+   "start": "react-app-rewired start",
-   "build": "react-scripts build",
+   "build": "react-app-rewired build",
-   "test": "react-scripts test --env=jsdom",
+   "test": "react-app-rewired test --env=jsdom",
    "eject": "react-scripts eject"
}

这一步的目的是使用 react-app-rewired 来启动 CRA 项目,这样就可以在启动的时候读取到 config-overrides.js 中的配置

而后在根目录创建 config-overrides.js 文件,并在其中加入如下代码,即可开启装饰器语法

const {override, addDecoratorsLegacy, addBabelPlugin} = require('customize-cra');

module.exports = override(
  // 开启babel装饰器插件的两种方法
  // 直接使用 addDecoratorsLegacy() 或 使用 addBabelPlugin() 添加
  addDecoratorsLegacy()

  // addBabelPlugin 用来配置添加babel插件的 
  // 这里以 @babel/plugin-proposal-decorators 插件为例, 这个插件是用来支持 es7 装饰器语法的
  // addBabelPlugin(
  //   ["@babel/plugin-proposal-decorators", { "legacy": true }]
  // )
)