如何使你的React组件库树可以摇动

249 阅读4分钟

这些天来,公司建立自己的可重用组件是相当普遍的,这些组件可以在多个应用程序中使用。在这篇文章中,我们将学习如何配置一个可重用的组件库,以便它能被使用它的应用程序树起:

How to make a reusable react component library tree shakeable

照片:Khamkéo VilaysingonUnsplash

什么是树状摇动,为什么?

树摇是webpack和rollup等捆绑程序为移除未使用的代码而进行的一个过程。

树状摇动意味着只有应用程序中使用的我们库中的组件才会被包含在应用程序捆绑包中。如果不进行树状摇动,所有的组件都会被包含,即使它们没有被使用。因此,树状摇动减少了应用包的大小,并提高了应用的性能,因为下载、解压、解析和执行的时间更少。

需要注意的是,进行树状摇动的是消费应用程序,而不是组件库。因此,我们需要确保我们的组件库的结构、格式和设置将允许树状摇动。

包括本地模块格式

我们正在使用rollup来捆绑组件库。如果我们包括ESM格式的捆绑,该库将比CommonJS(CJS)格式或其他格式有更大的机会被树形摇动。这是因为未使用的出口可以更容易被检测到,因为它们是静态的。

下面是如何配置rollup以包括ESM捆绑程序:

export default {
  ...,
  output: [
    ...,
    {
      ...,
      format: 'esm',      ...,
    },
  ],
  ...

告知应用程序捆绑者没有副作用

有些情况下,捆绑者不确定代码是否是未使用的。例如,导入一个组件的样式可能意味着按钮样式会影响应用程序的其他部分:

Import "./button.css"

sideEffectspackage.json 中的字段通知捆绑者,组件库中的所有文件都是纯净的,没有副作用:

{
  "name": "my-react-library",
  "version": "0.0.1",
  "main": "dist/index.cjs.js",
  "sideEffects": false,  ...
}

保留模块结构

Rollup默认会捆绑成一个文件。单一文件意味着构建者不能使用sideEffects 标志来跳过模块。

模块结构可以通过rollup配置中的preserveModules 字段来保留:

export default {
  ...,
  output: [
    ...,
    {
      format: 'esm',
      sourcemap: true,
      dir: 'dist',      preserveModules: true,    },
  ],
  ...

注意,需要提供dir 字段,而不是file ,因为现在会有许多文件被捆绑,而不是一个。dir 字段的值是放置捆绑文件的文件夹。

通知应用程序捆绑者有一个本地模块捆绑可用

使用package.json 中的module 字段来指定模块捆绑的入口点:

{
  "name": "my-react-library",
  "version": "0.0.1",
  "main": "dist/index.cjs.js",
  "module": "dist/src/index.js",  "sideEffects": false,  
}

然后应用程序捆绑器将使用ESM捆绑包,而不是由main 字段指定的捆绑包。

用最新的babel预设对组件进行移植

Babel可以用/*#__PURE__*/ 标记将React代码的一部分标记为纯代码,如下图所示:

function Button(_a) {
  var children = _a.children;
  return /*#__PURE__*/React__default.createElement("button", null, children);
}

这些标记可以帮助bundlers确定组件是纯洁的,因此是可树摇的。

因此,请确保组件库的构建包括带有最新预设的babel。例如,这里是rollup配置中的babel:

...
import { babel } from "@rollup/plugin-babel";
export default {
  ...,
  plugins: [
    ...,
    babel({      babelHelpers: "runtime",      exclude: /node_modules/,      extensions: [".js", ".ts", ".tsx"],    }),    ...
  ]
};

这里是babel的配置:

{
  "presets": [
    ["@babel/env", { "modules": false }],
    "@babel/typescript",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ]
  ],
  "plugins": [
    ["@babel/plugin-transform-runtime", { "useESModules": true }]
  ]
}

{ "modules": false } "@babel/env" 的设置对于保留ESM格式很重要。

确保第三方库是可以树状摇动的

在构建组件库时,如果利用第三方库,请确保它们是可以树状摇动的。例如,你可以执行以下步骤来快速检查一个库是否是可摇动的:

  • 使用Create React App创建一个应用。
  • 构建应用程序并记下文件大小。
  • 安装第三方库。
  • 在应用程序中引用第三方库的一小部分。
  • 构建应用程序并比较捆绑文件的大小。希望文件包的大小没有增加很多。如果捆绑文件的大小显著增加,第三方库可能不是树状晃动。
  • 在应用程序中多引用一点第三方库。
  • 构建应用程序并比较捆绑文件的大小。如果捆绑文件的大小没有变化,第三方库可能不是树状晃动。

总结

综上所述,为了确保React组件库是可树状摇动的:

  • 包括ESM格式并保留该格式。
  • 使用module package.json 字段,让捆绑者知道组件是ESM格式的。
  • 使用sideEffects package.json 标志,让捆绑者知道组件是纯的。
  • 使用最新的babel预设,以确保最新的树状摇动标记被设置。
  • 在你利用第三方库之前,测试它们是否可以树状摇动。