webpack打包之Library打包

panyan.jpg

寫(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í)候是,libraryTargetlibrary是有一定的關(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)于libraryTargetlibrary,其實(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ù),這里我們只講解commonjsroot,大家就知道怎么回事了

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上

  1. 修改配置文件中的main
"main": "./dist/library.js"

將main改成我們將來(lái)要給用戶去用的文件

  1. 到npm官網(wǎng)去注冊(cè)一個(gè)npm賬號(hào)
  2. 根目錄下執(zhí)行npm adduers,添加用戶名密碼
  3. 運(yùn)行npm publish,將包發(fā)布到npm倉(cāng)庫(kù)中,但是,我們的倉(cāng)庫(kù)名很容易和線上已有包重名,造成發(fā)布失敗,這就需要我們把名字起的獨(dú)特一點(diǎn),如果你的在cnpm私庫(kù)下面,還需要有作用域來(lái)解決這一問(wèn)題。
  4. npm install 試試使用的庫(kù)吧!

寫(xiě)在后面

本文介紹了關(guān)于庫(kù)即Library的打包方式,和一些webpack中比較高級(jí)的概念,大家可以試著去寫(xiě)一個(gè)自己的庫(kù)試試哦!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容