webpack高级应用篇(十二):创建 library

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


创建一个 library

假设我们正在编写一个名为 my-math 的小的 library,包含加法和减法。

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

 |- webpack.config.js
 |- package.json
 |- /test // 测试 library
    |- index.html
 |- /src
   |- index.js

使用 npm 初始化项目,然后安装 webpackwebpack-clilodash

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

src/index.js

export const add = (x, y) => x + y;

export const subtract = (x, y) => x - y;

webpack.config.js

const path = require('path');

module.exports = {
    
    
  mode: 'development',
  entry: './src/index.js',
  output: {
    
    
    path: path.resolve(__dirname, 'dist'),
    filename: 'myMath.js',
  },
};

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


导出 library

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

webpack.config.js

  const path = require('path');

  module.exports = {
    
    
    mode: 'production',
    entry: './src/index.js',
    output: {
    
    
      path: path.resolve(__dirname, 'dist'),
      filename: 'myMath.js',
+     library: "myMath",
    },
  };

我们导出了 myMath以便用户可以通过脚本标签使用它:

test/index.html

<script src="../dist/myMath.js"></script>
<script>
  myMath.add(1, 2);
</script>

然而它只能通过被脚本标签引用而发挥作用,它不能运行在 CommonJSAMDNode.jsES module 等环境中。


输出 ES 模块

该特性仍然是实验性的,并且没有完全支持,所以请确保事先启用 experiments.outputModule。除此之外,你可以在 这里 追踪开发进度。

const path = require('path');

module.exports = {
    
    
  mode: 'production',
  entry: './src/index.js',
  experiments: {
    
    
    outputModule: true,
  },
  output: {
    
    
    path: path.resolve(__dirname, 'dist'),
    filename: 'myMath.js',
    library: 'myMath',
    library: {
    
    
      // name: 'myMath', // 这里不要执行 name
      type: 'module',
    },
  },
};

执行 npx webpack

test/index.html

<script type="module">
  import {
    
     add } from '../dist/myMath.js'

  console.log(add(1, 2));
</script>

可以看到能正常输出


输出 umd

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

  • CommonJS module require:

    const myMath = require('myMath');
    // ...
    myMath.add(1, 2);
    
  • AMD module require:

    require(['myMath'], function (myMath) {
          
          
      // ...
      myMath.add(1, 2);
    });
    
  • script tag:

    <!DOCTYPE html>
    <html>
      ...
      <script src="https://example.org/myMath.js"></script>
      <script>
        // ...
        // 全局变量
        myMath.add(1, 2);
        // 挂载到window上的属性
        window.myMath.subtract(2, 2);
        // ...
      </script>
    </html>
    

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

const path = require('path');

module.exports = {
    
    
  mode: 'development',
  entry: './src/index.js',
  output: {
    
    
    path: path.resolve(__dirname, 'dist'),
    filename: 'myMath.js',
    library: {
    
    
      name: 'myMath',
      type: 'umd',
    },
    globalObject: 'this',
  },
};

output.globalObject

string = 'window'

当输出为 library 时,尤其是当 libraryTarget'umd'时,此选项将决定使用哪个全局对象来挂载 library。为了使 UMD 构建在浏览器和 Node.js 上均可用,应将 output.globalObject 选项设置为 'this'。对于类似 web 的目标,默认为 self

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


externals 依赖外部化

当我们在创建 library 的时候可能会用到一些第三方 library,比如 loadsh

npm i loadsh -S

src/index.js

import _ from 'lodash';

export const add = (x, y) => _.add(x, y);

export const subtract = (x, y) => x - y;

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

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

webpack.config.js

  const path = require('path');

  module.exports = {
    
    
    mode: 'development',
    entry: './src/index.js',
    output: {
    
    
      path: path.resolve(__dirname, 'dist'),
      filename: 'myMath.js',
      library: {
    
    
        name: "myMath",
        type: "umd"
      },
      globalObject: 'this',
    },
+   externals: {
    
    
+     lodash: {
    
    
+       commonjs: 'lodash',
+       commonjs2: 'lodash',
+       amd: 'lodash',
+       root: '_',
+     },
+   },
  };

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

package.json

{
    
    
  ...
  "main": "dist/myMath.js",
  ...
}

发布 npm publish

npm(三):npm包发布、更新、废弃

Tip

为了暴露和 library 关联着的样式表,你应该使用 MiniCssExtractPlugin。然后,用户可以像使用其他样式表一样使用和加载这些样式表。

待续:【webpack 创建 library】实战篇

猜你喜欢

转载自blog.csdn.net/qq_41887214/article/details/122045935