乐趣区

windows10-下使用webpack创建library

参考:

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          
退出移动版