Webpack 创建 library

除了打包应用程序,webpack 还可以用于打包 JavaScript library。以下指南适用于希望简化打包策略的 library 作者。

创建一个 library

假设我们正在编写一个名为 webpack-numbers 的小的 library,可以将数字 1 到 5 转换为文本表示,反之亦然,例如将 2 转换为 two。

基本的项目结构可能如下所示:

project

+  |- webpack.config.js
+  |- package.json
+  |- /src
+    |- index.js
+    |- ref.json

使用 npm 初始化项目,然后安装 webpack,webpack-cli 和 lodash:

npm init -y
npm install --save-dev webpack webpack-cli lodash

我们将 lodash 安装为 devDependencies 而不是 dependencies,因为我们不需要将其打包到我们的库中,否则我们的库体积很容易变大。

src/ref.json

[
  {
    "num": 1,
    "word": "One"
  },
  {
    "num": 2,
    "word": "Two"
  },
  {
    "num": 3,
    "word": "Three"
  },
  {
    "num": 4,
    "word": "Four"
  },
  {
    "num": 5,
    "word": "Five"
  },
  {
    "num": 0,
    "word": "Zero"
  }
]

src/index.js

import _ from lodash;
import numRef from ./ref.json;

export function numToWord(num) {
  return _.reduce(
    numRef,
    (accum, ref) => {
      return ref.num === num ? ref.word : accum;
    },
    
  );
}

export function wordToNum(word) {
  return _.reduce(
    numRef,
    (accum, ref) => {
      return ref.word === word && word.toLowerCase() ? ref.num : accum;
    },
    -1
  );
}

Webpack 配置

我们可以从如下 webpack 基本配置开始:

webpack.config.js

const path = require(path);

module.exports = {
  entry: ./src/index.js,
  output: {
    path: path.resolve(__dirname, dist),
    filename: webpack-numbers.js,
  },
};

在上面的例子中,我们将通知 webpack 将 src/index.js 打包到 dist/webpack-numbers.js 中。

Expose the Library

到目前为止,一切都应该与打包应用程序一样,这里是不同的部分 – 我们需要通过 output.library 配置项暴露从入口导出的内容。

webpack.config.js

  const path = require(path);

  module.exports = {
    entry: ./src/index.js,
    output: {
      path: path.resolve(__dirname, dist),
      filename: webpack-numbers.js,
+     library: "webpackNumbers",
    },
  };

我们将入口起点公开为 webpackNumbers,这样用户就可以通过 script 标签使用它:

<script src="https://example.org/webpack-numbers.js" rel="external nofollow"  rel="external nofollow" ></script>
<script>
  window.webpackNumbers.wordToNum(Five);
</script>

然而它只能通过被 script 标签引用而发挥作用,它不能运行在 CommonJS、AMD、Node.js 等环境中。

作为一个库作者,我们希望它能够兼容不同的环境,也就是说,用户应该能够通过以下方式使用打包后的库:

  • CommonJS module require:
    const webpackNumbers = require(webpack-numbers);
    // ...
    webpackNumbers.wordToNum(Two);
  • AMD module require:
    require([webpackNumbers], function (webpackNumbers) {
      // ...
      webpackNumbers.wordToNum(Two);
    });
  • script tag:
    <!DOCTYPE html>
    <html>
      ...
      <script src="https://example.org/webpack-numbers.js" rel="external nofollow"  rel="external nofollow" ></script>
      <script>
        // ...
        // Global variable
        webpackNumbers.wordToNum(Five);
        // Property in the window object
        window.webpackNumbers.wordToNum(Five);
        // ...
      </script>
    </html>

我们更新 output.library 配置项,将其 type 设置为 umd:

 const path = require(path);

 module.exports = {
   entry: ./src/index.js,
   output: {
     path: path.resolve(__dirname, dist),
     filename: webpack-numbers.js,
-    library: webpackNumbers,
+    library: {
+      name: webpackNumbers,
+      type: umd,
+    },
   },
 };

现在 webpack 将打包一个库,其可以与 CommonJS、AMD 以及 script 标签使用。

外部化 lodash

现在,如果执行 webpack,你会发现创建了一个体积相当大的文件。如果你查看这个文件,会看到 lodash 也被打包到代码中。在这种场景中,我们更倾向于把 lodash 当作 peerDependency。也就是说,consumer(使用者) 应该已经安装过 lodash 。因此,你就可以放弃控制此外部 library ,而是将控制权让给使用 library 的 consumer。

这可以使用 externals 配置来完成:

webpack.config.js

  const path = require(path);

  module.exports = {
    entry: ./src/index.js,
    output: {
      path: path.resolve(__dirname, dist),
      filename: webpack-numbers.js,
      library: {
        name: "webpackNumbers",
        type: "umd"
      },
    },
+   externals: {
+     lodash: {
+       commonjs: lodash,
+       commonjs2: lodash,
+       amd: lodash,
+       root: _,
+     },
+   },
  };

这意味着你的 library 需要一个名为 lodash 的依赖,这个依赖在 consumer 环境中必须存在且可用。

外部化的限制

对于想要实现从一个依赖中调用多个文件的那些 library:

import A from library/one;
import B from library/two;

// ...

无法通过在 externals 中指定整个 library 的方式,将它们从 bundle 中排除。而是需要逐个或者使用一个正则表达式,来排除它们。

module.exports = {
  //...
  externals: [
    library/one,
    library/two,
    // 匹配以 "library/" 开始的所有依赖
    /^library/.+$/,
  ],
};

最终步骤

遵循 生产环境 指南中提到的步骤,来优化生产环境下的输出结果。那么,我们还需要将生成 bundle 的文件路径,添加到 package.json 中的 main 字段中。

package.json

{
  ...
  "main": "dist/webpack-numbers.js",
  ...
}

或者,按照这个 指南,将其添加为标准模块:

{
  ...
  "module": "src/index.js",
  ...
}

这里的 key(键) main 是参照 package.json 标准,而 module 是参照 一个提案,此提案允许 JavaScript 生态系统升级使用 ES2015 模块,而不会破坏向后兼容性。

现在,你可以 将其发布为一个 npm package,并且在 unpkg.com 找到它,并分发给你的用户。

作者:冒牌SEO,如若转载,请注明出处:https://www.web176.com/webpack/22697.html

(0)
打赏 支付宝 支付宝 微信 微信
冒牌SEO冒牌SEO
上一篇 2023年5月26日
下一篇 2023年5月26日

相关推荐

发表回复

登录后才能评论