webpack 创建与发布 library

除了打包应用程序,webpack 还可以用于打包 JavaScript library。

https://webpack.docschina.org/guides/author-libraries/

https://webpack.docschina.org/configuration/output#output-librarytarget

1)创建

案例:

mkdir library
cd library
npm init -y  //多出个package.json(--yes)
mkdir src
cd src/
touch math.js string.js index.js

math.js:

 export function add(a, b) {
    return a + b;
}
export function minus(a, b) {
    return a - b;
}
export function multiply(a, b) {
    return a * b;
}
export function devision(a, b) {
    return a / b;
}

string.js:

export function join(a, b) {
     return a + '' + b;
}

index.js:

index.js:
import * as math from "./math";
import * as string from "./string";
export default { math, string };

webpack.config.js:

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

npx webpack后生成dist/library.js 则这个library.js就是我们导出的库

2)使用

一般一个模块引用的方式有很多种:ES module(import from)、commonjs、AMD、CMD、script标签引入等,不同的引入方式还需在打包库模块时添加不同的配置。

import library from 'library'; //ES module 

const library = require('library'); //commonjs 

require(["library"], function(library){ //AMD 

    //library.x 

}) 

以上三种方式使用需要在webpack.config.js中配置libraryTarget,来确定library的暴露形式

有以下几种方式暴露 library:

  • 变量:作为一个全局变量,通过 script 标签来访问(libraryTarget:'var')。
  • this:通过 this 对象访问(libraryTarget:'this')。
  • window:在浏览器中通过 window 对象访问(libraryTarget:'window')。
  • UMD:在 AMD 或 CommonJS require 之后可访问(libraryTarget:'umd')。

如果设置了 library 但没有设置 libraryTarget,则 libraryTarget 默认指定为 var,详细说明请查看 output 文档。查看 output.libraryTarget 文档,以获取所有可用选项的详细列表。

在html页面中通过script、全局引用,并通过全局变量如library去使用这个库中的内容library.X,需要配置library: "library"


//library.X

webpack.config.js:

output: {
    filename: "library.js",
    path: path.resolve(__dirname, "dist"),
    library: 'library', //暴露library:增加全局变量library,通过script标签引入js,并通过library全局变量使用
    libraryTarget: 'umd'  //控制以不同形式暴露library,umd:AMD、commonjs、ES import等任何方式都可以引入,this:将上面的全局变量挂载到this上,window同理,node下是global 
  }

思考:

若以上的string.js使用了lodash这个库,如下:

import _ from 'lodash';
export function join(a, b) {
    return _.join([a, b], ' ');
}

当其他人使用上面导出的library库的同时,整个业务逻辑代码中还需要用到lodash

import _ from 'lodash';
const library = require('library');

问题:library中使用了lodash,第三方业务也需要使用lodash=》导致lodash重复引用

解决:打包library时配置externals,排除lodash被打包到library中,而是使用library时额外引入lodash,这样无论业务逻辑中是否需要lodash,都必须引入,而且上面的引入也不会有问题

module.exports = {
  //externals: "lodash",  //字符串"lodash"、数组["lodash"]、对象{lodash: "lodash"},打包的时候遇到lodash忽略,不把lodash打包到输出文件中  这样输出的库在使用时需要引入lodash
  externals: {
    lodash: { //commonjs环境下引入lodash必须叫lodash不能叫_等其他名
      root: "_", //通过script标签引用而不是ES import、commonjs、AMD方式,必须像全局注入_变量,
      commonjs: "lodash" //lodash库在commonjs环境中使用
    }
  }
}

commonjs:
const lodash = require('lodash');
const library = require('library');

externals:https://webpack.docschina.org/configuration/externals/

从输出的 bundle 中排除依赖,防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。此功能通常对 library 开发人员来说是最有用的。

externals:string object function regex(正则)

外部 library 可能是以下任何一种形式:

  • root:可以通过一个全局变量访问 library(例如,通过 script 标签)。
  • commonjs:可以将 library 作为一个 CommonJS 模块访问。
  • commonjs2:和上面的类似,但导出的是 module.exports.default.
  • amd:类似于 commonjs,但使用 AMD 模块系统。

注意:上面只是打包库最简单的配置,正常打包一个复杂的node模块,需要考虑按需加载、按顺序加载、tree shaking等等。

3)发布

打包库成功后,修改package.json中的入口:

{
  ...
  "main": "./dist/library.js", 
  ...
}
或者:module 属性应指向一个使用 ES2015 模块语法的脚本
{
  ...
  "module": "src/index.js", 
  ...
}

在npm网站上注册账号并登陆

在bash中输入npm adduser回车,输入用户名密码,

npm publish发布到npm的仓库上

发布成功之后别人就可以使用这个库:npm install安装库即可(安装包名看package.json中的name,注意库名不能重复,否则npm publish会报错)

你可能感兴趣的:(前端,webpack)