写在前面
之前写下了《webpack4入门讲解》文集,里面从webapck最基础概念,到一些高级的配置,处理分包等问题,读完后你会对webpack有一个比较清晰的认识,从这一节开始,我们要去学习一些webpack的高级使用实际,在实际开发中,你可能会遇到一些比如打包优化等等方面的内容,这个文集中将详细介绍,同时,为了保证知识涵盖面的广泛,还会将到一些你开发中可能用不到的内容,大家各取所需即可。当然,基础还不扎实的同学,要去学习前面的文集哦,前面的文集可不是各取所需,如果可以,我希望你将它彻底搞懂。
下面进入本文集的第一篇文章
Library打包
什么是“Library”?
所谓Library即“库”,比如我们使用的lodash就是一个“函数库”,比如我们的常用的'antd'、'elementUI'这些就属于“组件库”,在实际的工作中,我们很有可能去封装自己的函数库或者是UI组件库或者是基于某个开源库做二次封装的业务组件库,那么我们是入库针对“库”进行打包的呢?
环境准备
- 创建一个名为'library'的文件夹,执行
npm init -y
,初始化一个npm环境。
生成的package.json
如下
{
"name": "library", // 库的名字
"version": "1.0.0", // 库的版本
"description": "", // 库的描述
"main": "index.js", // 入口
"scripts": { // npm指令
"test": "echo \"Error: no test specified\" && exit 1" // 可以删掉,创建我们自己的指令
},
"keywords": [],
"author": "yourname", // 库的作者
"license": "ISC" // 协议,可以改成‘MIT’开源协议
}
- 写一个自己的库
在根目录下创建如下文件目录
|--src
|--math.js
|--string.js
|--index.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 division (a, b) {
return a/b
}
// string.js
export function join(a, b) {
return a + ' ' + b
}
// index.js
import * as math from './math'
import * as string from './string'
export default { math, string }
上面的代码中,我们就简单的实现了一个自己的库,其中包括加减乘除的数字运算和字符串的拼接,实际上,一个库的开发,就类似于一个业务系统,他也是需要被打包才能被使用,所以我们还需要webpack对其进行打包
- 安装webpack并创建webpack.config.js配置文件
yarn add webpack webpack-cli -S
webpack.config.js
const path = require('path')
module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'library.js'
}
}
package.json中增加打包指令
"scripts": {
"build": "webpack"
}
- 执行打包
我们看到在根目录'dist'文件夹下生成了一个'library.js'的文件,如果是对于我们平常的业务代码,到这一步,我们已经完成了,但是我们是开发一个库的代码,是要给别人用的,别人用的形式可能是下面这样的
import library from 'library' // ESM
const library = require('library') // commonJs
于是我们在配置文件中加入一个配置项如下
module.exports = {
output: {
libraryTarget: 'umd'
}
}
意思是,无论你使用什么样的引入方式,我们打包出来的库都支持。有时候我们还有可能是通过script
标签进行引入的
<script src='library.js'></script>
// 在使用的时候,通过library这样的全局变量来使用,就像jquery那样
那么我们还需要在配置项中加入下面的配置
module.exports = {
output: {
library: 'library' // 名字随便取,代表我们全局暴露的变量
}
}
- 执行打包,打包依然是生成了一个'library.js'的文件,下面我们通过一个简单的html文件来验证一下我们的打包结果,这里就是个html通过
script
标签引入,然后测试全局变量,自行测试。
关于libraryTarget和library的配置关系
实际上,在做library打包的时候是,libraryTarget
和library
是有一定的关系的,需要配合使用
-
library
作为核心,代表要生成一个全局变量 -
libraryTarget
意思是这个全局变量挂在哪里,如果是umd
,那么二者是没有关系的,如果是this
,就代表我们的库不再支持AMD,commonJS,esm等模块形式,而是将全局变量注入到全局的this上面。其中libraryTarget
可以取值umd
、this
、window
、global
(nodeJs下)等值,一般我们在封装一个库的时候,会选择umd
关于libraryTarget
和library
,其实其内容也是比较多的,这里我们只做简单的介绍,如果你的真的需要去打包这样的库的话,再去翻阅相关资料
在Library中使用第三方库
有时候,我们在封装自己的库的时候,不是所有的方法都自己写的,我们也会去引用一些第三方的组件库或者函数库,比如在上面的例子中,我们做下面的代码变更
// string.js
import _ from 'lodash'
export function join(a, b) {
return _.join([a,b], ' ')
}
这时候打包,也是能正常打包的,但是,library文件却比之前大了很多,这是因为我们打包进了lodash这个库,但是用户在使用我们的库的时候,可能在业务代码中也会引入lodash这个库,这个时候,打包的代码,很可能就会打包出两份lodash,从而中造成一些问题,为了解决这个问题,我们需要这样去配置
externals
module.exports = {
externals: ['lodash']
}
做了上面配置后,我们发现,我的库打包后又变小了,那么externals
的意思是啥呢?就是我们在打包的时候,遇到这个库就忽略他,不要把他打包到代码中,具体的配置,大家可以看一下官网的API,其中,externals可以配置为对象,并且有几个参数,这里我们只讲解commonjs
和root
,大家就知道怎么回事了
commonjs
我们将配置改成这样
module.exports = {
externals: {
lodash: {
commonjs: 'lodash'
}
}
}
上面配置的意思是,当我使用commonjs
规范做打包的时候,遇到lodash
这个库,我们必须使用'lodash'这个名字,就像这样
const lodash = require('lodash')
const _ = require('lodash') // 这是错误的!!
root
module.exports = {
externals: {
lodash: {
root: '_',
commonjs: 'lodash'
}
}
}
这代表,我们不使用模块化,而是用script
标签做引入的话,这时候,我们必须全局注入一个'_'的变量
当然了一般情况下,我们都是直接
module.exports = {
externals: {
lodash: 'lodash'
}
}
意思是,不管是怎么引入,我们都使用'lodash'这个名字。
这里我们只是对library的打包,做了一个相对简单的介绍,实际上,当你要去真正开发一个组件库的时候,其打包文件也是比较复杂的,到时候大家再去学习,这里通过library的打包,让大家知道几个概念和配置项
将包发布到npm
我们将库封装好了以后,一般会将库发布到npm上去,这里就再代价感受一下,将自定义的库发布到npm上
- 修改配置文件中的main
"main": "./dist/library.js"
将main改成我们将来要给用户去用的文件
- 到npm官网去注册一个npm账号
- 根目录下执行
npm adduers
,添加用户名密码 - 运行
npm publish
,将包发布到npm仓库中,但是,我们的仓库名很容易和线上已有包重名,造成发布失败,这就需要我们把名字起的独特一点,如果你的在cnpm私库下面,还需要有作用域来解决这一问题。 - npm install 试试使用的库吧!
写在后面
本文介绍了关于库即Library的打包方式,和一些webpack中比较高级的概念,大家可以试着去写一个自己的库试试哦!
网友评论