1.创建项目并进行基本配置
webpack配置文件: webpack.build.js
javascript
const path = require('path');
module.exports = {
mode:'development',
entry:'./src/webpack-numbers.js',
output: {
filename: 'webpack-numbers.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
};
package.json:
javascript
script:{
"buildJs": "webpack --config ./webpack.build.js",
"dev": "set NODE_ENV=development && webpack serve --open --config ./webpack.dev.js --mode=development",
}
2.暴露库:需要通过 output.library 配置项暴露从入口导出的内容
注意:如果是暴露为ES Module时,不用同时设置name属性,build时会报错
javascript
// 暴露库
library: {
// library.type设置为module时不能设置同时设置name
type: 'module',
},
},
3.使用库
可以通过 script 标签使用,不演示
4.运行在 ES6、CommonJS、AMD、Node.js 等环境中
以上都只能通过script 标签使用,但是希望它能够兼容不同的环境
解决:更新 output.library
配置项,将其 type
设置为 'umd':
javascript
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'webpack-numbers.js',
library: {
name: 'webpackNumbers',
type: 'umd',
},
},
我这里是将其导出为ES Module:
注意:
暴露为ES Module时,不能同时设置name属性;
且需要在output同级设置experiments.outputModule为true
javascript
mode:'development',
entry:'./src/webpack-numbers.js',
output: {
filename: 'webpack-numbers.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
// 暴露库
library: {
// library.type设置为module时不能设置同时设置name
type: 'module',
},
},
// 设置 type: 'module'时,必须加入以下配置
experiments: {
outputModule: true,
},
5.library的type字段详解
library 可接受的数据类型是 string | string[] | object。string 是 object 类型的简写形式,当值为 object 类型时,object 中能包含的属性有 name、type、export、auxiliaryComment 和 umdNamedDefine。本文将重点放在 type 字段上,它决定如何公开当前库,取值基本固定,name 字段可以是任何字符串,它用来指定库的名称。
- library.type = var(默认值),
{type: 'var', name: 'MyLibrary'}:
通过MyLibrary
能访问到add
函数,但不能保证MyLibrary
在全局变量上 - library.type = window ,
{type: 'window', name: 'MyLibrary'}:
通过window.MyLibrary
能访问到add
函数。 - library.type = module,将 library 的值改成
{type: 'module'}
, 此时还要 experiments.outputModule 设置为 true。此时不存在闭包,并且能用 es modules 将库导入。 - library.type = this,将 library 的值改成
{type: 'this', name: 'MyLibrary'},
通过 this.MyLibrary 能访问到 add 函数; - 将 library 的值改成
{type: 'self', name: 'MyLibrary'},
此时通过 self.MyLibrary 可访问到 add 函数,在浏览器环境的全局上下文中 self 等于 window; - 将 library 的值改成 {type: 'global', name: 'MyLibrary'},此时 MyLibrary 会被分配到全局对象,全局对象会根据target值的不同而不同,全部对象可能的值是 self、global 或 globalThis。当 target 的值为 web(默认值),此时的打包结果与 library.type = self 结果一样。
- library.type = commonjs,将 library 的值改成
{type: 'commonjs', name: 'MyLibrary'}
, - 将 library 的值改成
{type: 'commonjs2', name: 'MyLibrary'},CommonJs 规范只定义了 exports ,但是 module.exports 被 node.js 和一些其他实现 CommonJs 规范的模块系统所使用,commonjs 表示纯 CommonJs,commonjs2 在 CommonJs 的基础上增加了 module.exports。
webpack output.library的16 种取值方法示例_output.library.type-CSDN博客
7.使用命令npm run buildJs打包时报错
bash
[webpack-cli] Error: Library name must be unset. Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.
webpack-cli\] Error: Library name must be unset. Common configuration options that specific library names are 'output.library\[.name\]', 'entry.xyz.library\[.name\]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library\[.name\]'. 解决:library.type设置为module时不能设置同时设置name ```javascript // 暴露库 library: { // library.type设置为module时不能设置同时设置name //name:'tools', type: 'module', }, ``` ## 6.外部化 lodash 如果工具包中将lodash也打包进去包体积会很大,所以可以通过设置externals属性将lodash包进行隔离不打包,但是这要求使用工具包的项目环境下安装了lodash这个被隔离的包。 ```javascript externals: { lodash: { commonjs: 'lodash', commonjs2: 'lodash', amd: 'lodash', root: '_', }, }, ``` ## 7.问题:导出为ES6报错: ERROR in external {"commonjs":"lodash","commonjs2":"lodash","amd":"lodash","root":"_"} Cannot read properties of undefined (reading 'length') TypeError: Cannot read properties of undefined (reading 'length') 解决:配置ES6的外置依赖库 module: 'lodash' ```javascript // 依赖工具库外置:要求引用的项目本身有这个工具库 externals: { lodash: { commonjs: 'lodash', commonjs2: 'lodash', amd: 'lodash', // 配置ES module module: 'lodash', root: '_', }, ``` ## 8.问题二:webpack 外部化lodash后报错,reduce()方法找不到 将lodash外部化后,工具类中的引入lodash就不能再使用了,否则就会报错。注释掉引用即可用 ```javascript // 注意外部化的时候,这里引入就不能直接引入了 // import _ from 'lodash'; import numRef from './data/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 ); } ``` ## 9.外部化的限制 对于想要实现从一个依赖中调用多个文件的那些库,无法通过在 `externals` 中指定整个 `library` 的方式将它们从 bundle 中排除,而是需要逐个或者使用正则表达式排除它们。 ```javascript module.exports = { //... externals: [ 'library/one', 'library/two', // 匹配以 "library/" 开始的所有依赖 /^library\/.+$/, ], }; ``` ## 10.优化生产环境下的输出结果 为了优化生产环境下的输出结果。那么,我们还需要将生成 bundle 的文件路径,添加到 `package.json` 中的 `main` 字段中。 ```javascript { ... "main": "dist/webpack-numbers.js", ... } ``` 或者,按照这个 [指南](https://github.com/dherman/defense-of-dot-js/blob/master/proposal.md#typical-usage "指南") 将其添加为标准模块 ```javascript { ... "module": "src/webpack-numbers.js", ... } ``` 另外,为了暴露和库关联的样式表,你应该使用 [MiniCssExtractPlugin](https://www.webpackjs.com/plugins/mini-css-extract-plugin "MiniCssExtractPlugin")。然后,用户可以像使用其他样式表一样使用和加载这些样式表。 ## 11.发布到npm仓库 可以 [将其发布为一个 npm 包](https://docs.npmjs.com/getting-started/publishing-npm-packages "将其发布为一个 npm 包"),并且在 [unpkg.com](https://unpkg.com/#/ "unpkg.com") 找到它,并分发给你的用户。 进入打包好后的文件夹dist,然后npm init 创建package.json文件,并且设置基本信息 ```javascript { "name": "webpack-numbers-lmf", "version": "1.0.4", "description": "修改", "main": "webpack-numbers.js", "private": false, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "limingfang", "license": "ISC" } ``` npm login登录npm仓库 命令行输入用户名和密码后npm publish发布版本即可 ## 12.使用: ```javascript npm i webpack-numbers-lmf lodash -S ``` ```javascript import { numToWord,wordToNum } from "webpack-numbers-lmf" console.log(numToWord(3), wordToNum("Ten") ); ``` ## 13.完整配置代码 webpack.build.js: ```javascript //webpack.build.js const path = require('path'); module.exports = { mode:'development', entry:'./src/webpack-numbers.js', output: { filename: 'webpack-numbers.js', path: path.resolve(__dirname, 'dist'), clean: true, // 暴露库 library: { // library.type设置为module时不能设置同时设置name type: 'module', }, }, // 设置 type: 'module'时,必须加入以下配置 experiments: { outputModule: true, }, // 依赖工具库外置:要求引用的项目本身有这个工具库 externals: { lodash: { commonjs: 'lodash', commonjs2: 'lodash', amd: 'lodash', // 配置ES module module: 'lodash', root: '_', }, }, }; ``` ```javascript //package.json { "name": "webpack-demo", "version": "1.0.0", "description": "", "private": false, "main": "dist/webpack-numbers.js", "module": "src/webpack-numbers.js", "scripts": { "buildJs": "webpack --config ./webpack.build.js", "dev": "set NODE_ENV=development && webpack serve --open --config ./webpack.dev.js --mode=development", "prod": "set NODE_ENV=production && webpack serve --open --config ./webpack.prod.js --mode=production" }, ... } ``` ```javascript //webpack-numbers.js // 注意外部化的时候,这里引入就不能直接引入了 // import _ from 'lodash'; import numRef from './data/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 ); } ``` dist里的package.json ```javascript { "name": "webpack-numbers-lmf", "version": "1.0.4", "description": "修改", "main": "webpack-numbers.js", "private": false, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "xxx", "license": "ISC" } ``` 使用: ```javascript //index.js import _ from 'lodash'; import { numToWord,wordToNum } from "webpack-numbers-lmf" function component() { console.log(numToWord(3), wordToNum("Ten") ); return element; } document.body.appendChild(component()); ```