当我们要打包一个Library 的时候,比如组件库或者函数库的时候,就不是像之前那样的打包方式了。这里我们就来试试Library 的打包。
这里我们来做一个函数库的打包。
先初始化一个项目(node 项目)
初始化:新建一个文件夹,然后进入这个文件夹 运行命令 npm init -y 然后就可以初始化一个node 项目啦!
初始化后,会在项目跟目录下,新建一个package.json 文件。内容如下。
{
"name": "myLibrary",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
我们可以将liscense 改为MIT,test 这儿暂时不用也可以去掉。
{
"name": "myLibrary",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
},
"keywords": [],
"author": "",
"license": "MIT"
}
接下来,我们创建库代码。首先,在项目跟目录下创建目录src 。然后在src 下创建 math.js , string.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
}
然后,在项目src 下新建文件 index.js。它是一个公共入口文件。如下。
import * as math from './math'
import * as string from './string'
export default {
math,
string
}
下面,开始对这个库对打包。
首先,我们在项目中安装webpack 和 webpack-cli
npm install webpack webpack-cli --save
同时,我们在项目中创建一个webpack 的配置文件 webpack.config.js (在项目跟目录下)
并在package.json 的script 中加入webpack 的命令,如下。
"scripts": {
"build": "webpack"
},
接下来,我们来配置一下webpack 配置文件 webpack.config.js 如下。
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js'
}
}
然后,我们去运行打包命令。如下生成了 library.js 文件。
如果这是我们的业务代码,那么打包到这儿就结束了,但是,我们这儿是一个库。
外部引入我们的库:
// 可能使用 ES6 的导入
import library from 'library'
// 可能使用Common JS 导入
const library = require('library')
// 可能使用AMD 方式导入
// ...
如果我们想要我们的库在外部能正常引用,我们可以在打包的时候做一个配置。在webpack.config.js 中output 配置项中加入‘libraryTarget’ 项,值为‘umd’。
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js',
'libraryTarget': 'umd'
}
这样,就能使打包的代码,对import , require, AMD 的引入方式都能正常运行。
当然,也许还想使用 script 标签引入这个库,并通过一个全局变量来使用库。如下。
<script src="library.js"></script>
<script>
library.xxx
</script>
这种需求,同样也可以在webpack 中配置就能达到。在webpack 的output 中配置 ‘library’ 项,值为‘library’(当使用script 标签引入后,会创建一个全局变量标志符为 library )。如下。
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js',
library: 'library',
libraryTarget: 'umd'
}
}
运行打包命令即可。
我们在项目的dist 目录下新建一个test.html 如下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./library.js"></script>
</head>
<body>
</body>
</html>
然后在浏览器中打开页面,在控制台,我们输出library 就会发现如下内容了!
上面,我们使用了两个配置项 output.library, output.libraryTarget 。有时,这两项是配合着使用的。output.library 是核心,意思是要打包生成一个全局变量,output.libraryTarget 是指这个全局变量挂在哪里。如果是libraryTarget 是‘umd’,那么它俩是没什么关系的。但如果output.libraryTarget 是‘this’,首先就不支持ES6, Common JS,AMD 方式的引入了,然后library 被挂载到全局的 this 上。
如下。
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js',
library: 'library',
libraryTarget: 'this'
}
}
我们打包,然后重新刷新页面,在控制台中输出this.library (这儿的this 就是window)还是可以看见上面的内容。
libraryTarget 除了‘umd’ / 'this' 外,还可以配置为 ‘window’ / ‘global’(node中)
一般来说,我们做一个一般的库,只需配置为‘umd’, 然后library 取一个想叫的名字就可以了。
下面,我们再看一种情况。在src/string.js 中,我们想使用lodash 的join 来改写之前的join。那么应该怎样更好地打包呢?
先我们在项目中下载lodash 库。(npm install lodash --save)
我们把string.js 改写为如下。
import _ from 'lodash'
export function join(a, b) {
return _.join([a,b], ' ')
}
运行打包命令,发现打包生成的文件,有71 KB。
而且,如果当外部需要引用我们的库,同时也要引入lodash 库在业务代码中,那么最终用户的代码里面,就很可能存在两份lodash 代码,为了解决这个问题,我们需要在我们的库里面做另外一个配置:externals 。它的值可以是数组或者对象。
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
externals: ['lodash'],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js',
library: 'library',
libraryTarget: 'umd'
}
}
运行打包命令,我们会发现,这时候打包后的代码又变为了1.6KB 了!
这是因为externals:['lodash'] 意味着,打包过程中如果遇到 lodash 库就直接忽略,不要将它打包到代码里。这也意味着,当在外部引入library 时,要使用join 方法就必须在外部引入lodash 库。
externals 还可以配置为对象。参考 webpack 官网 documentatone > configuration > externals
https://webpack.js.org/configuration/externals/
一般来说,设置成如下这种即可。(在外部引用的时候,把lodash 引入 并指定引用名为lodash)
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
externals: {
lodash: 'lodash'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js',
library: 'library',
libraryTarget: 'umd'
}
}
当然,做一个大型的库的打包配置,这些肯定是不够的,还需要配置 按需加载,tree-shaking ...
占坑,以后再来填。
先把流程走下去先。
下面,我们要将package.json 中的配置改一改了。我们把入口“main”改为‘./dist/library.js’ 如下。
{
"name": "myLibrary",
"version": "1.0.0",
"description": "",
"main": "./dist/library.js",
"scripts": {
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.15",
"webpack": "^4.39.3",
"webpack-cli": "^3.3.7"
}
}
接下来,我们需要一个npm 账号,可以在npm 官网注册。
然后在命令行输入
npm adduser
然后,输入,它要求输入的信息(用户名与密码)
然后,成功后,进入库项目的目录,运行命令
npm publish
就可以直接把项目发布到npm 仓库中去。
其他人要使用就可以直接npm install 项目的名字 ,就可以啦!