close
  • 简体中文
  • 处理三方依赖

    本节介绍如何在 bundle 模式下处理三方依赖。

    通常,项目所需的三方依赖可以通过包管理器的 install 命令安装。安装成功后,它们通常会出现在项目的 package.json 文件中的 dependenciesdevDependencies 字段下。

    package.json
    {
      "dependencies": {},
      "devDependencies": {}
    }

    dependencies 字段下的依赖通常来说是这个包运行所需的依赖,如果这些三方依赖声明在 devDependencies 字段下,那么在生产运行时会出现缺失依赖。

    除了 dependencies 字段,peerDependencies 也可以声明在生产环境中需要的依赖,但它更强调这些依赖在项目运行时的存在,类似于插件机制。

    三方依赖的默认处理

    默认情况下,当生成 CJS 或 ESM 产物时,dependenciesoptionalDependenciespeerDependencies 字段下的三方依赖不会被 Rslib 打包。

    这是因为在 npm 包安装时,其 dependencies 也会被安装。通过不打包 dependencies,可以减少包的体积。

    如果需要打包某些依赖,建议将它们从 dependencies 移动到 devDependencies,这相当于预打包依赖,并减少依赖安装的体积。

    以下是一个简单示例,假设项目依赖 foo

    package.json
    {
      "dependencies": {
        "foo": "^1.0.0"
      },
      // 或
      "peerDependencies": {
        "foo": "^1.0.0"
      }
    }

    当在源代码中使用 foo 依赖时:

    src/index.ts
    import foo from 'foo';
    console.info(foo);

    此时产物中不会包含 foo 的代码:

    dist/index.js
    import foo from 'foo';
    console.info(foo);

    自定义三方依赖处理

    Rslib 主要通过 output.autoExternaloutput.externals 控制三方依赖是否被打包。

    配置 autoExternal

    如果希望覆盖 output.autoExternal 的上述默认行为,使这些依赖被打包进产物,可以将其设置为 false

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            autoExternal: false,
          },
        },
      ],
    });

    如果只想调整某几类依赖,可以使用对象形式:

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            autoExternal: {
              dependencies: true,
              optionalDependencies: true,
              peerDependencies: true,
              devDependencies: false,
            },
          },
        },
      ],
    });

    使用 exclude 可以从 output.autoExternal 自动生成的 external 规则中排除指定包。如果某个包被排除,它的子路径导入也不会被 external:

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            autoExternal: {
              exclude: ['react', /^@scope\//],
            },
          },
        },
      ],
    });

    配置 externals

    当你需要指定某些模块不被 Rslib 打包,或需要改变 external 后的请求路径时,可以使用 output.externals

    数组形式适合保留原始请求路径:

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            externals: ['react', 'react/jsx-runtime'],
          },
        },
      ],
    });

    对象形式可以指定 external 后的请求路径,常用于给 external 的模块改名:

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            externals: {
              react: 'react-18',
              'react/jsx-runtime': 'react-18/jsx-runtime',
            },
          },
        },
      ],
    });
    Tip

    react/jsx-runtime 这类子路径需要单独处理。只配置 react 不代表 react/jsx-runtime 也会使用相同的 external 规则。

    如果要匹配一组模块,可以使用正则:

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          output: {
            externals: [/^react($|\/)/],
          },
        },
      ],
    });

    在一些复杂场景中,如果需要根据请求来源、上下文等信息决定是否 external,可以通过 tools.rspack 配置 Rspack 的 externals

    rslib.config.ts
    export default defineConfig({
      lib: [
        {
          tools: {
            rspack: {
              externals: [
                ({ request }, callback) => {
                  if (request?.startsWith('react')) {
                    callback(null, request);
                    return;
                  }
    
                  callback();
                },
              ],
            },
          },
        },
      ],
    });

    更多用法可参考 Rspack 的 Externals 文档。