有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。
最近,陸陸續續搞 了一個 UniUsingComponentsWebpackPlugin 外掛(下面介紹),這是自己第三個開源專案,希望大家一起來維護,一起 star 呀,其它兩個:
vue-okr-tree
基於 Vue 2的組織架構樹元件
ztjy-cli
團隊的一個簡易模板初始化腳手架
UniUsingComponentsWebpackPlugin
地址:https://github.com/qq44924588...
配合UniApp,用於整合小程式原生元件
- 配置第三方庫後可以自動引入其下的原生元件,而無需手動配置
- 生產構建時可以自動剔除沒有使用到的原生元件
背景
第一個痛點
用 uniapp開發小程式的小夥伴應該知道,我們在 uniapp 中要使用第三方 UI 庫(vant-weapp
,iView-weapp
)的時候 ,想要在全域性中使用,需要在 src/pages.json
中的 usingComponents
新增對應的元件宣告,如:
// src/pages.json
"usingComponents": {
"van-button": "/wxcomponents/@vant/weapp/button/index",
}
但在開發過程中,我們不太清楚需要哪些元件,所以我們可能會全部宣告一遍(PS:這在做公共庫的時候更常見),所以我們得一個個的寫,做為程式設計師,我們絕不允許使用這種笨方法。這是第一個痛點。
第二個痛點
使用第三方元件,除了在 src/pages.json
還需要在對應的生產目錄下建立 wxcomponents
,並將第三方的庫拷貝至該檔案下,這個是 uniapp 自定義的,詳細就見:https://uniapp.dcloud.io/fram...。
這是第二個痛點。
第三個痛點
第二痛點,我們將整個UI庫拷貝至 wxcomponents
,但最終釋出的時候,我們不太可能全都用到了裡面的全域性元件,所以就將不必要的元件也釋出上去,增加程式碼的體積。
有的小夥伴就會想到,那你將第三方的庫拷貝至 wxcomponents
時候,可以只拷使用到的就行啦。是這理沒錯,但元件裡面可能還會使用到其它元件,我們還得一個個去看,然後一個個引入,這又回到了第一個痛點了。
有了這三個痛點,必須得有個外掛來做這些傻事,處理這三個痛點。於是就有 UniUsingComponentsWebpackPlugin 外掛,這個webpack 外掛主要解決下面幾個問題:
- 配置第三方庫後可以自動引入其下的原生元件,而無需手動配置
- 生產構建時可以自動剔除沒有使用到的原生元件
webpack 外掛
webpack 的外掛體系是一種基於 Tapable 實現的強耦合架構,它在特定時機觸發鉤子時會附帶上足夠的上下文資訊,外掛定義的鉤子回撥中,能也只能與這些上下文背後的資料結構、介面互動產生 side effect,進而影響到編譯狀態和後續流程。
從形態上看,外掛通常是一個帶有 apply
函式的類:
class SomePlugin {
apply(compiler) {
}
}
Webpack 會在啟動後按照註冊的順序逐次呼叫外掛物件的 apply
函式,同時傳入編譯器物件 compiler
,外掛開發者可以以此為起點觸達到 webpack 內部定義的任意鉤子,例如:
class SomePlugin {
apply(compiler) {
compiler.hooks.thisCompilation.tap('SomePlugin', (compilation) => {
})
}
}
注意觀察核心語句 compiler.hooks.thisCompilation.tap
,其中 thisCompilation
為 tapable 倉庫提供的鉤子物件;tap
為訂閱函式,用於註冊回撥。
Webpack 的外掛體系基於 tapable
提供的各類鉤子展開,所以有必要先熟悉一下 tapable 提供的鉤子型別及各自的特點。
到這裡,就不做繼續介紹了,關於外掛的更多 詳情可以去官網瞭解。
這裡推薦 Tecvan 大佬寫的 《Webpack 外掛架構深度講解》https://mp.weixin.qq.com/s/tX...
實現思路
UniUsingComponentsWebpackPlugin 外掛主要用到了三個 compiler
鉤子。
第一個鉤子是 environment
:
compiler.hooks.environment.tap(
'UniUsingComponentsWebpackPlugin',
async () => {
// todo someing
}
);
這個鉤子主要用來自動引入其下的原生元件,這樣就無需手動配置。解決第一個痛點。
第二個鉤子 thisCompilation
,這個鉤子可以獲得 compilation
,能對最終打包的產物進行操作:
compiler.hooks.thisCompilation.tap(
'UniUsingComponentsWebpackPlugin',
(compilation) => {
// 新增資源 hooks
compilation.hooks.additionalAssets.tapAsync(
'UniUsingComponentsWebpackPlugin',
async (cb) => {
await this.copyUsingComponents(compiler, compilation);
cb();
}
);
}
);
所以這個勾子用來將 node_modules
下的第三庫拷貝到我們生產 dist 目錄裡面的 wxcomponents
,解決第二個痛點。
ps:這裡也可直接用現有的 copy-webpack-plugin
外掛來實現。
第三個鉤子 done
,表示 compilation
執行完成:
if (process.env.NODE_ENV === 'production') {
compiler.hooks.done.tapAsync(
'UniUsingComponentsWebpackPlugin',
(stats, callback) => {
this.deleteNoUseComponents();
callback();
}
);
}
執行完成後,表示我們已經生成 dist
目錄了,可以讀取檔案內容,分析,獲取哪些元件被使用了,然後刪除沒有使用到元件對應的檔案。這樣就可以解決我們第三個痛點了。
PS:這裡我判斷只有在生產環境下才會 剔除,開發環境沒有,也沒太必要。
使用
安裝
npm install uni-using-components-webpack-plugin --save-dev
然後將外掛新增到 WebPack Config 中。例如:
const UniUsingComponentsWebpackPlugin = require("uni-using-components-webpack-plugin");
module.exports = {
plugins: [
new UniUsingComponentsWebpackPlugin({
patterns: [
{
prefix: 'van',
module: '@vant/weapp',
},
{
prefix: 'i',
module: 'iview-weapp',
},
],
})
],
};
注意:uni-using-components-webpack-plugin 只適用在 UniApp 開發的小程式。
引數
Name | Type | Description |
---|---|---|
patterns | {Array<Object>} | 為外掛指定相關 |
Patterns
module | prefix |
---|---|
模組名 | 元件字首 |
module 是指 package.json
裡面的 name
,如使用是 Vant 對應的 module
為@vant/weapp
,如果使用是 iview,剛對應的 module
為 iview-weapp
,具體可看它們各自的 package.json
。
prefix 是指元件的字首,如 Vant 使用是 van
開頭的字首,iview 使用是 i
開頭的字首,具體可看它們各自的官方文件。
PS: 這裡得吐曹一下 vant,叫別人使用 van 的字首,然後自己元件裡面宣告子元件時,卻沒有使用 van 字首,如 picker 元件,它裡面的 JSON 檔案是這麼寫的:
{
"component": true,
"usingComponents": {
"picker-column": "../picker-column/index",
"loading": "../loading/index"
}
}
picker-column
和 loading
都沒有帶 van
字首,因為這個問題,在做 自動剔除 功能中,我是根據 字首來判斷使用哪些元件的,由於這裡的 loading
,picker-column
沒有加字首,所以就被會刪除,導致最終的 picker
用不了。為了解決這個問題,增加了不少工作量。
希望 Vant 官方後面的版本能優化一下。
總結
本文通用自定義 Webpack 外掛來實現日常一些技術優化需求。主要為大家介紹了 Webpack 外掛的基本組成和簡單架構,通過三個痛點,引出了 uni-using-components-webpack-plugin
外掛,並介紹了使用方式,實現思路。
最後,關於 Webpack 外掛開發,還有更多知識可以學習,建議多看看官方文件《Writing a Plugin》進行學習。
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
交流
有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。