参考:
https://github.com/kalcifer/webpack-library-example
https://webpack.js.org/guides/author-libraries
说明:
最近结合 webpack 官方文档和示例代码在 windows10 下使用 webpack 创建 library 时遇见一些问题,在此总结一下
创建 library:
-
基础知识准备
1. 库使用方法 ES2015 module import: import * as webpackNumbers from 'webpack-numbers'; // ... webpackNumbers.wordToNum('Two'); CommonJS module require: const webpackNumbers = require('webpack-numbers'); // ... webpackNumbers.wordToNum('Two'); AMD module require: require(['webpackNumbers'], function (webpackNumbers) { // ... webpackNumbers.wordToNum('Two'); }); via a <script>: <!doctype html> <html> ... <script src="https://unpkg.com/webpack-numbers"></script> <script> // ... // Global variable webpackNumbers.wordToNum('Five') // Property in the window object window.webpackNumbers.wordToNum('Five') // ... </script> </html> 2. 暴露 library why:为了让你的 library 能够在各种用户环境 (consumption) 中可用 how:在 output 中添加 library 属性 当你在 import 引入模块时,这可以将你的 library bundle 暴露为全局变量 在 output 中添加 libraryTarget 属性 1) 控制 library 以不同方式暴露,让 library 和其他环境兼容 2) 可以通过以下方式暴露 library:变量:作为一个全局变量,通过 script 标签来访问(libraryTarget:'var')this:通过 this 对象访问(libraryTarget:'this')window:通过 window 对象访问,在浏览器中(libraryTarget:'window')UMD:在 AMD 或 CommonJS 的 require 之后可访问(libraryTarget:'umd')3) 如果设置了 library 但没设置 libraryTarget,则 libraryTarget 默认为 var。output.globalObject string: 'window' 要使 umd 在浏览器和 node.js 上都可用,globalObject 需要设置成 this 示例:output: { ... library: 'webpackNumbers', libraryTarget: 'umd', globalObject: 'this' }
步骤:
-
创建目录并安装相关工具
1. $ mkdir webpack-numbers-library // 创建 webpack-numbers-library 2. $ cd webpack-numbers-library// 进入 webpack-numbers-library 目录 3. $ npm init -y // 初始化 npm 4. $ npm install webpack --save-dev // 在本地安装 webpack 5. $ npm install webpack-cli --save-dev // 安装 webpack-cli 6. $ npm install lodash --save-dev // 安装 lodash
-
添加文件
1. 添加 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); }; 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" } ] 2. 添加 examples/ browser/index.html <html> <head> <title>webpack numbers library</title> <script type='text/javascript' src='https://unpkg.com/lodash@4.16.6'></script> </head> <body> <div id='root'></div> <!-- 通过 <script> 加载库 --> <script type='text/javascript' src='./webpack-numbers.js'></script> <script type='text/javascript'> document.getElementById('root').innerHTML = "This is a browser example where and api is called to transalate'One'to'1'\n Results: wordtonum('One') ===" + window.webpackNumbers.wordToNum('Five'); </script> </body> </html> node/example.js require('lodash'); var webpackNumbers = require('./webpack-numbers.js');//CommonJS module require var out = function () {process.stdout.write('This is the result for numToWord(1) ===' + webpackNumbers.numToWord(1)); }; out(); 3. 添加 webpack.config.js const path = require('path'); module.exports = { mode: 'production',// 启用 uglifyjs 压缩插件进行压缩输出 entry: './src/index.js', output: {path: path.resolve(__dirname, './dist'), filename: 'webpack-numbers.js', library: 'webpackNumbers',// 暴露 library 为 webpackNumbers 的全局变量 libraryTarget: 'umd',// 让 library 和其他环境兼容:umd: 在 AMD 或 CommonJS 的 require 之后可访问 globalObject: 'this',// 使 umd 在浏览器和 node.js 上都可用,globalObject 需要设置成 this }, externals: {// 外部化 lodash: 放弃对外部 library 的控制,而是将控制权让给使用 library 的用户 lodash: { commonjs: 'lodash', commonjs2: 'lodash', amd: 'lodash', root: '_' } }, module: { rules: [ {test: /\.(js)$/, exclude: /(node_modules|bower_components)/, use: 'babel-loader' } ] } }; 4. 最终的文件结构如下:│ package-lock.json │ package.json │ webpack.config.js │ ├─examples │ ├─browser │ │ index.html │ │ │ └─node │ example.js ├─node_modules │ └─src index.js ref.json
-
安装 babel-loader
$ npm install babel-loader --save-dev 最新的 babel-loader 版本是 8.x,直接安装, 后面执行 npm build xxx 的时候会报以下错误 ERROR in ./src/index.js Module build failed (from ./node_modules/babel-loader/lib/index.js): Error: Cannot find module '@babel/core' babel-loader@8 requires Babel 7.x (the package '@babel/core'). If you'd like to use Babel 6.x ('babel-core'), you should install'babel-loader@7'. 根据错误信息的提示,我们安装 babel-loader 7.x 版本 babel-core $ npm install babel-core babel-loader@7 --save-dev babel-loader@7.1.5 babel-core@6.26.3
-
修改 package.json
从 webpack-library-example 示例中 package.json 拷贝以下 code 到 { ... "main": "dist/webpack-numbers.js",// 添加生成 bundle 的文件路径 "scripts": { "build:browser": "webpack && cp dist/webpack-numbers.js examples/browser", "build:node": "webpack && cp dist/webpack-numbers.js examples/node/ && node examples/node/example.js", "test": "echo \"Error: no test specified\"&& exit 1" } ... }
-
测试 browser
1. $ npm run build:browser 2. 在浏览器中打开 index.html 页面显示:This is a browser example where and api is called to transalate 'One' to '1' Results: wordtonum('One') === 5
-
测试 node
1. $ npm run build:node 2. 打印以下信息:This is the result for numToWord(1) === One