webpack 打包库和组件
webpack 除了可以⽤来打包应⽤,也可以⽤来打包 js 库。
接下来我们实现⼀个⼤整数加法库的打包
- 需要打包压缩版和⾮压缩版本
- ⽀持 AMD/CJS/ESM 模块引⼊
库的录结构和打包要求
打包输出的库名称:
- 未压缩版 large-number.js
- 压缩版 large-number.min.js
+ |- /dist + |- large-number.js + |- large-number.min.js + |- webpack.config.js + |- package.json + |- index.js + |- /src + |- index.js
支持的使用方式
1、⽀持 ES module
import * as largeNumber from 'large-number'; // ... largeNumber.add('999', '1');
2、⽀持 CJS
const largeNumbers = require('large-number'); // ... largeNumber.add('999', '1');
3、⽀持 AMD
require(['large-number'], function (large-number) { // ... largeNumber.add('999', '1'); });
4、可以直接通过 script 引⼊
<!doctype html> <html> ... <script src="https://unpkg.com/large-number"></script> <script> // ... // Global variable largeNumber.add('999', '1'); // Property in the window object window.largeNumber.add('999', '1'); // ... </script> </html>
如何将库暴露出去?
library
: 指定库的全局变量
libraryTarget
: ⽀持库引⼊的⽅式
module.exports = { mode: "production", entry: { "large-number": "./src/index.js", "large-number.min": "./src/index.js" }, output: { filename: "[name].js", library: "largeNumber", libraryExport: "default", libraryTarget: "umd" } };
如何指对 .min 压缩
通过 include 设置只压缩 min.js 结尾的⽂件
module.exports = { mode: "none", entry: { "large-number": "./src/index.js", "large-number.min": "./src/index.js" }, output: { filename: "[name].js", library: "largeNumber", libraryTarget: "umd" }, optimization: { minimize: true, minimizer: [ new TerserPlugin({ include: /\.min\.js$/, }), ], } };
设置入口文件
package.json 的 main 字段为 index.js,根目录新增index.js文件
if (process.env.NODE_ENV === "production") { module.exports = require("./dist/large-number.min.js"); } else { module.exports = require("./dist/large-number.js"); }
实战开发
1、初始化项目
mkdir large-number
cd large-number
npm init -y
npm i webpack webpack-cli -D
2、创建src/index.js
,在里面实现大整数加法功能
export default function add(a, b) { let i = a.length - 1; let j = b.length - 1; let carry = 0; let ret = ''; while (i >= 0 || j >= 0) { let x = 0; let y = 0; let sum; if (i >= 0) { x = a[i] - '0'; i --; } if (j >= 0) { y = b[j] - '0'; j --; } sum = x + y + carry; if (sum >= 10) { carry = 1; sum -= 10; } else { carry = 0; } // 0 + '' ret = sum + ret; } if (carry) { ret = carry + ret; } return ret; } // add('999', '1'); // add('1', '999'); // add('123', '321'); // console.log(add('999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999', '1'));
3、创建webpack.config.js
需要安装插件:npm i terser-webpack-plugin -D
“terser-webpack-plugin”: “^1.3.0”,4.0会报错
const TerserPlugin = require('terser-webpack-plugin'); module.exports = { entry: { 'large-number': './src/index.js', 'large-number.min': './src/index.js' }, output: { filename: '[name].js', library: 'largeNumber', libraryTarget: 'umd', libraryExport: 'default' }, mode: 'none', optimization: { minimize: true, minimizer: [ new TerserPlugin({ include: /\.min\.js$/, }), ], } }
打包的效果就实现了压缩
4、设置入口文件
根目录新增index.js文件
if (process.env.NODE_ENV === "production") { module.exports = require("./dist/large-number.min.js"); } else { module.exports = require("./dist/large-number.js"); }
package.json的配置,里面添加了prepublish
的处理
{ "name": "large-number", "version": "1.0.0", "description": "大整数加法打包", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", "prepublish": "webpack" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "terser-webpack-plugin": "^1.3.0", "webpack": "^4.44.1", "webpack-cli": "^3.3.12" } }
5、发布npm包,包名需要更改,我这边用了kaimo-large-number
具体可以参考我的另一篇笔记
6、使用自己的npm包
首先在我们的业务安装npm i kaimo-large-number -S
然后在业务代码里面使用’kaimo-large-number’
import React from 'react'; import ReactDOM from 'react-dom'; import './search.less'; import logo from './images/logo.png'; console.log(logo); import '../../common/index.js'; import { kaimo666 } from './tree-shaking.js'; // 引入大加法 import kaimoLargeNumber from 'kaimo-large-number'; class Search extends React.Component { constructor() { super(...arguments); this.state = { Text: null } } loadComponent() { // 动态加在text.js,返回一个promise import('./text.js').then((Text) => { console.log(Text); this.setState({ Text: Text.default }); }) } render() { const kaimo = kaimo666(); const { Text } = this.state; const kaimoLarge = kaimoLargeNumber('777', '666'); return <div className="search-text"> { kaimo } 凯小默的博客666 { Text ? <Text /> : null } 大加法操作'777'+'666':{ kaimoLarge } <img src={ logo } onClick={ this.loadComponent.bind(this) } /> </div> } } ReactDOM.render( <Search/>, document.getElementById('root') )
页面效果:
如果你npm run build
的出现下面问题:说明你发布的包有问题没有把dist目录包含进来,去除你git忽略文件里的dist,你需要更新你的包
找到自己库的.gitignore
文件,去掉dist