许多工具能被构建库工程,例如 Webpack、Snowpack、Vite、Rollup 等。通常用Rollup可能会多一点,不顾webpack也不是不能用,也是常见的解决方案。
用webpack构建lib工程,应该关注一下几个点:

  • 正确配置输入输出,以及package.json中读取使用库的入口;
  • source map生成;
  • 是否需要external;
  • 是不是需要提取css成单文件;

配置输入输出

  1. module.exports = {
  2. mode: "production",
  3. entry: "./src/index.js",
  4. output: {
  5. filename: "[name].js",
  6. path: path.join(__dirname, "./lib"),
  7. // lib特别的输出指定
  8. // umd是比较通用的
  9. library: {
  10. name: "_",
  11. type: "umd",
  12. },
  13. },
  14. }

这里面需要注意的是library我们设置了umd的形式,umd兼容cmd、amd等常见的模块化形式,所以比较通用。
另外,package.json中要指定入口:

  1. {
  2. "main": "dist/main.js",
  3. "module": "src/index.js",
  4. }

比如,我们指定main是dist/main.js,module是esm模式的入口,直接使用源码都可以。

sourcemap

可以使用。devtool 配置项生成 Sourcemap 文件:

  1. {
  2. devtool: 'source-map'
  3. }

extermals

为什么要配置externals呢?

因为我们期望自己的lib打包体积变小:如果你的lib中引用了其他的lib,默认是会将所有的包都打包起来的。这样就造成了体积过大。
这时候如果把引用的包,用external声明起来,打包的时候就不会被加入到最终产物中,这样体积就不会那么大了。自己的lib打包后,生成的UMD 模板通过 require、define 函数中引入 external依赖。

  1. {
  2. externals: {
  3. // 所有node modules的依赖都不打包
  4. // const nodeExternals = require('webpack-node-externals')
  5. // externals: [nodeExternals()]
  6. // lodash将不被打包
  7. lodash: {
  8. commonjs: "lodash",
  9. commonjs2: "lodash",
  10. amd: "lodash",
  11. root: "_",
  12. },
  13. },
  14. }

但是这样存在一个风险就是:external的依赖并不存在在当前环境中。
解决的办法是,package.json中声明peerDependencies:

  1. "peerDependencies": {
  2. "lodash": "^4.17.21"
  3. }

关于peerDependencies可参考:、

当你安装一个包时,其 dependencies 和 devDependencies 会被 npm 自动安装。 peerDependencies 则有所不同,它们不会被自动安装。 当一个依赖项 c 被列在某个包 b 的 peerDependency 中时,它就不会被自动安装。取而代之的是,包含了 b 包的代码库 a 则必须将对应的依赖项 c 包含为其依赖。

抽离css

如果写的是UI库,那么这一步就很重要。
还是借助MiniCssExtractPlugin,这里注意使用了MiniCssExtractPlugin以及MiniCssExtractPlugin.loader,而且MiniCssExtractPlugin.loader是在css-loader之后的。

  1. {
  2. module: {
  3. rules: [
  4. {
  5. test: /\.css$/,
  6. use: [MiniCssExtractPlugin.loader, "css-loader"],
  7. },
  8. ],
  9. },
  10. plugins: [new MiniCssExtractPlugin()],
  11. }