
寫(xiě)在前面
之前寫(xiě)下了《webpack4入門(mén)講解》文集,里面從webapck最基礎(chǔ)概念,到一些高級(jí)的配置,處理分包等問(wèn)題,讀完后你會(huì)對(duì)webpack有一個(gè)比較清晰的認(rèn)識(shí),從這一節(jié)開(kāi)始,我們要去學(xué)習(xí)一些webpack的高級(jí)使用實(shí)際,在實(shí)際開(kāi)發(fā)中,你可能會(huì)遇到一些比如打包優(yōu)化等等方面的內(nèi)容,這個(gè)文集中將詳細(xì)介紹,同時(shí),為了保證知識(shí)涵蓋面的廣泛,還會(huì)將到一些你開(kāi)發(fā)中可能用不到的內(nèi)容,大家各取所需即可。當(dāng)然,基礎(chǔ)還不扎實(shí)的同學(xué),要去學(xué)習(xí)前面的文集哦,前面的文集可不是各取所需,如果可以,我希望你將它徹底搞懂。
下面進(jìn)入本文集的第一篇文章
Library打包
什么是“Library”?
所謂Library即“庫(kù)”,比如我們使用的lodash就是一個(gè)“函數(shù)庫(kù)”,比如我們的常用的'antd'、'elementUI'這些就屬于“組件庫(kù)”,在實(shí)際的工作中,我們很有可能去封裝自己的函數(shù)庫(kù)或者是UI組件庫(kù)或者是基于某個(gè)開(kāi)源庫(kù)做二次封裝的業(yè)務(wù)組件庫(kù),那么我們是入庫(kù)針對(duì)“庫(kù)”進(jìn)行打包的呢?
環(huán)境準(zhǔn)備
- 創(chuàng)建一個(gè)名為'library'的文件夾,執(zhí)行
npm init -y,初始化一個(gè)npm環(huán)境。
生成的package.json如下
{
"name": "library", // 庫(kù)的名字
"version": "1.0.0", // 庫(kù)的版本
"description": "", // 庫(kù)的描述
"main": "index.js", // 入口
"scripts": { // npm指令
"test": "echo \"Error: no test specified\" && exit 1" // 可以刪掉,創(chuàng)建我們自己的指令
},
"keywords": [],
"author": "yourname", // 庫(kù)的作者
"license": "ISC" // 協(xié)議,可以改成‘MIT’開(kāi)源協(xié)議
}
- 寫(xiě)一個(gè)自己的庫(kù)
在根目錄下創(chuàng)建如下文件目錄
|--src
|--math.js
|--string.js
|--index.js
其中內(nèi)容如下
// 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 }
上面的代碼中,我們就簡(jiǎn)單的實(shí)現(xiàn)了一個(gè)自己的庫(kù),其中包括加減乘除的數(shù)字運(yùn)算和字符串的拼接,實(shí)際上,一個(gè)庫(kù)的開(kāi)發(fā),就類似于一個(gè)業(yè)務(wù)系統(tǒng),他也是需要被打包才能被使用,所以我們還需要webpack對(duì)其進(jìn)行打包
- 安裝webpack并創(chuàng)建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"
}
- 執(zhí)行打包
我們看到在根目錄'dist'文件夾下生成了一個(gè)'library.js'的文件,如果是對(duì)于我們平常的業(yè)務(wù)代碼,到這一步,我們已經(jīng)完成了,但是我們是開(kāi)發(fā)一個(gè)庫(kù)的代碼,是要給別人用的,別人用的形式可能是下面這樣的
import library from 'library' // ESM
const library = require('library') // commonJs
于是我們?cè)谂渲梦募屑尤胍粋€(gè)配置項(xiàng)如下
module.exports = {
output: {
libraryTarget: 'umd'
}
}
意思是,無(wú)論你使用什么樣的引入方式,我們打包出來(lái)的庫(kù)都支持。有時(shí)候我們還有可能是通過(guò)script標(biāo)簽進(jìn)行引入的
<script src='library.js'></script>
// 在使用的時(shí)候,通過(guò)library這樣的全局變量來(lái)使用,就像jquery那樣
那么我們還需要在配置項(xiàng)中加入下面的配置
module.exports = {
output: {
library: 'library' // 名字隨便取,代表我們?nèi)直┞兜淖兞? }
}
- 執(zhí)行打包,打包依然是生成了一個(gè)'library.js'的文件,下面我們通過(guò)一個(gè)簡(jiǎn)單的html文件來(lái)驗(yàn)證一下我們的打包結(jié)果,這里就是個(gè)html通過(guò)
script標(biāo)簽引入,然后測(cè)試全局變量,自行測(cè)試。
關(guān)于libraryTarget和library的配置關(guān)系
實(shí)際上,在做library打包的時(shí)候是,libraryTarget和library是有一定的關(guān)系的,需要配合使用
-
library作為核心,代表要生成一個(gè)全局變量 -
libraryTarget意思是這個(gè)全局變量掛在哪里,如果是umd,那么二者是沒(méi)有關(guān)系的,如果是this,就代表我們的庫(kù)不再支持AMD,commonJS,esm等模塊形式,而是將全局變量注入到全局的this上面。其中libraryTarget可以取值umd、this、window、global(nodeJs下)等值,一般我們?cè)诜庋b一個(gè)庫(kù)的時(shí)候,會(huì)選擇umd
關(guān)于libraryTarget和library,其實(shí)其內(nèi)容也是比較多的,這里我們只做簡(jiǎn)單的介紹,如果你的真的需要去打包這樣的庫(kù)的話,再去翻閱相關(guān)資料
在Library中使用第三方庫(kù)
有時(shí)候,我們?cè)诜庋b自己的庫(kù)的時(shí)候,不是所有的方法都自己寫(xiě)的,我們也會(huì)去引用一些第三方的組件庫(kù)或者函數(shù)庫(kù),比如在上面的例子中,我們做下面的代碼變更
// string.js
import _ from 'lodash'
export function join(a, b) {
return _.join([a,b], ' ')
}
這時(shí)候打包,也是能正常打包的,但是,library文件卻比之前大了很多,這是因?yàn)槲覀兇虬M(jìn)了lodash這個(gè)庫(kù),但是用戶在使用我們的庫(kù)的時(shí)候,可能在業(yè)務(wù)代碼中也會(huì)引入lodash這個(gè)庫(kù),這個(gè)時(shí)候,打包的代碼,很可能就會(huì)打包出兩份lodash,從而中造成一些問(wèn)題,為了解決這個(gè)問(wèn)題,我們需要這樣去配置
externals
module.exports = {
externals: ['lodash']
}
做了上面配置后,我們發(fā)現(xiàn),我的庫(kù)打包后又變小了,那么externals的意思是啥呢?就是我們?cè)诖虬臅r(shí)候,遇到這個(gè)庫(kù)就忽略他,不要把他打包到代碼中,具體的配置,大家可以看一下官網(wǎng)的API,其中,externals可以配置為對(duì)象,并且有幾個(gè)參數(shù),這里我們只講解commonjs和root,大家就知道怎么回事了
commonjs
我們將配置改成這樣
module.exports = {
externals: {
lodash: {
commonjs: 'lodash'
}
}
}
上面配置的意思是,當(dāng)我使用commonjs規(guī)范做打包的時(shí)候,遇到lodash這個(gè)庫(kù),我們必須使用'lodash'這個(gè)名字,就像這樣
const lodash = require('lodash')
const _ = require('lodash') // 這是錯(cuò)誤的!!
root
module.exports = {
externals: {
lodash: {
root: '_',
commonjs: 'lodash'
}
}
}
這代表,我們不使用模塊化,而是用script標(biāo)簽做引入的話,這時(shí)候,我們必須全局注入一個(gè)'_'的變量
當(dāng)然了一般情況下,我們都是直接
module.exports = {
externals: {
lodash: 'lodash'
}
}
意思是,不管是怎么引入,我們都使用'lodash'這個(gè)名字。
這里我們只是對(duì)library的打包,做了一個(gè)相對(duì)簡(jiǎn)單的介紹,實(shí)際上,當(dāng)你要去真正開(kāi)發(fā)一個(gè)組件庫(kù)的時(shí)候,其打包文件也是比較復(fù)雜的,到時(shí)候大家再去學(xué)習(xí),這里通過(guò)library的打包,讓大家知道幾個(gè)概念和配置項(xiàng)
將包發(fā)布到npm
我們將庫(kù)封裝好了以后,一般會(huì)將庫(kù)發(fā)布到npm上去,這里就再代價(jià)感受一下,將自定義的庫(kù)發(fā)布到npm上
- 修改配置文件中的main
"main": "./dist/library.js"
將main改成我們將來(lái)要給用戶去用的文件
- 到npm官網(wǎng)去注冊(cè)一個(gè)npm賬號(hào)
- 根目錄下執(zhí)行
npm adduers,添加用戶名密碼 - 運(yùn)行
npm publish,將包發(fā)布到npm倉(cāng)庫(kù)中,但是,我們的倉(cāng)庫(kù)名很容易和線上已有包重名,造成發(fā)布失敗,這就需要我們把名字起的獨(dú)特一點(diǎn),如果你的在cnpm私庫(kù)下面,還需要有作用域來(lái)解決這一問(wèn)題。 - npm install 試試使用的庫(kù)吧!
寫(xiě)在后面
本文介紹了關(guān)于庫(kù)即Library的打包方式,和一些webpack中比較高級(jí)的概念,大家可以試著去寫(xiě)一個(gè)自己的庫(kù)試試哦!