日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
我曾為配置Webpack感到痛不欲生,直到我遇到了這個(gè)流式配置方案

今天給大家介紹社區(qū)當(dāng)中一個(gè) webpack 的流式配置方案——webpack-chain,這個(gè)方案現(xiàn)在已經(jīng)在我目前所在的團(tuán)隊(duì)落地,且?guī)?lái)了一些正向的收益,現(xiàn)在就這個(gè)方案出現(xiàn)的背景、核心概念及日常使用姿勢(shì)給大家展開(kāi)介紹。

海倫網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)建站!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)建站從2013年成立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)建站

為什么出現(xiàn) webpack-chain ?

相信大家都對(duì)業(yè)界鼎鼎有名的構(gòu)建工具Webpack并不陌生了,作為目前為止最穩(wěn)定、生產(chǎn)環(huán)境應(yīng)用最多的構(gòu)建打包工具,它固然有著很多優(yōu)勢(shì),比如:

  • 生態(tài)豐富。在社區(qū)有大量的 loader 和 plugin,想要的基本都能找到。
  • 可插拔的插件機(jī)制?;?Tapable 實(shí)現(xiàn)的可擴(kuò)展架構(gòu)。
  • 文檔成熟。有中文版,且一直在更新和維護(hù)。
  • 穩(wěn)定性高?,F(xiàn)在正式的前端項(xiàng)目生產(chǎn)環(huán)境下基本用 Webpack 來(lái)構(gòu)建,經(jīng)過(guò)這么多年業(yè)界的驗(yàn)證,該踩的坑也都踩的差不多了。

但其實(shí)說(shuō)了這么多優(yōu)勢(shì),大家估計(jì)還是對(duì)這個(gè)東西沒(méi)什么好感,因?yàn)檫€有最重要的一點(diǎn)不容忽視,那就是開(kāi)發(fā)體驗(yàn)。對(duì)于構(gòu)建打包這個(gè)事情來(lái)說(shuō),本來(lái)就是工程化當(dāng)中的一個(gè)細(xì)節(jié)極其復(fù)雜的環(huán)節(jié),需要輸入大量的配置信息來(lái)保證打包結(jié)果符合預(yù)期。在Webpack當(dāng)中,我們?nèi)绻挥闷渌姆桨?,就只有手?dòng)地配置一個(gè)巨大的 JavaScript 對(duì)象,所有的配置信息都在這個(gè)對(duì)象當(dāng)中,這樣原始的方式的確給人體驗(yàn)很不好,歸納為以下幾個(gè)原因:

  1. 對(duì)象過(guò)于龐大,直觀上讓人看的眼花繚亂,盡管可以封裝一些邏輯,但還是避免不了深層的嵌套配置;
  2. 難以動(dòng)態(tài)修改。舉個(gè)例子,如果通過(guò)腳本動(dòng)態(tài)修改一些配置信息,比如刪除 babel-loader 的一個(gè) plugin,那么需要從最頂層的配置對(duì)象,一步步找到到 babel-loader 的位置,然后遍歷插件列表,這個(gè)手動(dòng)尋找和遍歷的過(guò)程比較繁瑣。
  3. 難以共享配置。如果你嘗試跨項(xiàng)目共享 webpack 配置對(duì)象,那后續(xù)的修改就會(huì)變的混亂不堪,因?yàn)槟阈枰獎(jiǎng)討B(tài)地修改原來(lái)的配置。

社區(qū)當(dāng)中也有人發(fā)現(xiàn)了這些痛點(diǎn),于是出現(xiàn)了針對(duì)Webpack的流式配置方案——webpack-chain。

webpack-chain 核心概念

其實(shí)真正學(xué)會(huì) webpack-chain,我覺(jué)得首先不是去學(xué)習(xí)具體每個(gè)屬性的配置方法,而是理解webpack-chain核心的兩個(gè)對(duì)象——ChainedMap和ChainedSet。

什么是 ChainMap ?

比如我現(xiàn)在配置路徑別名:

 
 
 
  1. config.resolve.alias 
  2.   .set(key, value) 
  3.   .set(key, value) 
  4.   .delete(key) 
  5.   .clear() 

那么,現(xiàn)在的 alis 對(duì)象就是一個(gè)ChainMap。如果一個(gè)屬性在webpack-chain當(dāng)中標(biāo)記為ChainMap之后,它會(huì)有一些額外的方法,并且允許這些鏈?zhǔn)秸{(diào)用(如上面的示例)。

接下來(lái)就來(lái)一個(gè)個(gè)認(rèn)識(shí)這些方法:

 
 
 
  1. // 清空當(dāng)前 Map 的所有屬性 
  2. clear() 
  3. // 通過(guò)鍵值從 Map 移除單個(gè)配置. 
  4. delete(key) 
  5. // Map中是否存在一個(gè)配置值的特定鍵,返回真或假 
  6. has(key) 
  7. // 返回 Map中已存儲(chǔ)的所有值的數(shù)組 
  8. values() 
  9. //  提供一個(gè)對(duì)象,這個(gè)對(duì)象的屬性和值將映射進(jìn) Map。第二個(gè)參數(shù)為一個(gè)數(shù)組,表示忽略哪些屬性 
  10. merge(obj, omit) 
  11. // handler: ChainedMap => ChainedMap 
  12. // 一個(gè)把ChainedMap實(shí)例作為單個(gè)參數(shù)的函數(shù) 
  13. batch(handler) 
  14. // condition: Boolean 
  15. // whenTruthy: ChainMap -> any, 條件為真時(shí)執(zhí)行 
  16. // whenFalsy: ChainSet -> any, 條件為假時(shí)執(zhí)行 
  17. when(condition, whenTruthy, whenFalsy) 
  18. // 獲取 Map 中相應(yīng)鍵的值 
  19. get(key) 
  20. // 先調(diào)用 get,如果找不到對(duì)應(yīng)的值, 就返回 fn 函數(shù)返回的結(jié)果 
  21. getOrCompute(key, fn) 
  22. // 配置鍵值對(duì) 
  23. set(key, value) 

這些方法的返回對(duì)象也都是 ChainMap,這樣可以實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用,簡(jiǎn)化操作。在 Webpack中,大部分的對(duì)象都是 ChainMap,具體大家可以去源碼當(dāng)中看看,實(shí)現(xiàn)并不復(fù)雜。

ChainMap 是webpack-chain當(dāng)中非常重要的一個(gè)數(shù)據(jù)結(jié)構(gòu),封裝了鏈?zhǔn)秸{(diào)用的方法,以至于后面所有 ChainMap 類型的配置都可以直接復(fù)用ChainMap本身的這些方法,非常方便。

什么是 ChainSet ?

跟 ChainMap 類似,封裝了自己的一套 API:

 
 
 
  1. // 末尾增加一個(gè)值 
  2. add(value) 
  3. // 在開(kāi)始位置增加一個(gè)值 
  4. prepend(value) 
  5. // 清空 set 內(nèi)容 
  6. clear() 
  7. // 刪除某個(gè)值 
  8. delete(value) 
  9. // 判斷是否有某個(gè)值 
  10. has(value) 
  11. // 返回值列表 
  12. values() 
  13. // 合并給定的數(shù)組到 Set 尾部。 
  14. merge(arr) 
  15. // handler: ChainSet => ChainSet 
  16. // 一個(gè)把 ChainSet 實(shí)例作為單個(gè)參數(shù)的函數(shù) 
  17. batch(handler) 
  18. // condition: Boolean 
  19. // whenTruthy: ChainSet -> any, 條件為真時(shí)執(zhí)行 
  20. // whenFalsy: ChainSet -> any, 條件為假時(shí)執(zhí)行 
  21. when(condition, whenTruthy, whenFalsy) 

ChainSet 的作用和ChainMap類似,也是封裝了底層鏈?zhǔn)秸{(diào)用的 API,在需要操作Webpack配置當(dāng)中的數(shù)組類型的屬性時(shí),通過(guò)調(diào)用ChainSet的方法即可完成。

速記方法

對(duì)于 ChainMap,有這樣一種簡(jiǎn)化的寫(xiě)法,官網(wǎng)稱之為速記寫(xiě)法:

 
 
 
  1. devServer.hot(true); 
  2.  
  3. // 上述方法等效于: 
  4. devServer.set('hot', true); 

因此,在實(shí)際的webpack-chain配置中,可以經(jīng)常看到直接 .屬性()這樣調(diào)用方式,是不是感覺(jué)很巧妙?源碼當(dāng)中的實(shí)現(xiàn)非常簡(jiǎn)單:

 
 
 
  1. extend(methods) { 
  2.   this.shorthands = methods; 
  3.   methods.forEach(method => { 
  4.     this[method] = value => this.set(method, value); 
  5.   }); 
  6.   return this; 

在ChainMap初始化的時(shí)候,會(huì)調(diào)用 extend 方法,然后把屬性列表作為 methods參數(shù)直接傳入,然后通過(guò)下面一行代碼間接調(diào)用 set 方法:

 
 
 
  1. this[method] = value => this.set(method, value); 

這樣的設(shè)計(jì)也是值得學(xué)習(xí)的。

配置 Webpack

首先,需要?jiǎng)?chuàng)建一個(gè)新的配置對(duì)象:

 
 
 
  1. const Config = require('webpack-chain'); 
  2.  
  3. const config = new Config(); 
  4.  
  5. // 一系列鏈?zhǔn)讲僮髦?nbsp;
  6. // 得到最后的 webpack 對(duì)象 
  7. console.log(config.toConfig()) 

然后依次配置 resolve、entry、output、module、plugins、optimization 對(duì)象,本文關(guān)鍵還是帶大家能夠落地 webpack-chain,因此詳細(xì)介紹一下各個(gè)配置的使用方法。

entry 和 output

這里列舉一個(gè)常用的配置,由于 Webpack 在 entry 和 output 掛了太多屬性,大家參考 Webpack 官方文檔照著如下的方式去配就好了。

 
 
 
  1. config.entryPoints.clear() // 會(huì)把默認(rèn)的入口清空 
  2. config.entry('entry1').add('./src/index1.tsx')//新增入口 
  3. config.entry('entry2').add('./src/index2.tsx')//新增入口 
  4.  
  5. config.output 
  6.       .path("dist") 
  7.       .filename("[name].[chunkhash].js") 
  8.       .chunkFilename("chunks/[name].[chunkhash].js") 
  9.       .libraryTarget("umd") 

alias

對(duì)于路徑別名的配置,也是幾乎所有項(xiàng)目必不可少的部分,配置方式如下:

 
 
 
  1. // 可以發(fā)現(xiàn) resolve.alias 其實(shí)是一個(gè) ChainMap 對(duì)象 
  2. config.resolve.alias 
  3.   .set('assets',resolve('src/assets')) 
  4.   .set('components',resolve('src/components')) 
  5.   .set('static',resolve('src/static')) 
  6.   .delete('static') // 刪掉指定的別名 

plugins

插件的配置可以說(shuō)是相當(dāng)重要的一個(gè)環(huán)節(jié)了,webpack-chain 當(dāng)中的配置會(huì)和平時(shí)的配置有些不同,讓我們來(lái)具體看看。

1. 添加一個(gè)插件

 
 
 
  1. // 先指定名字(這個(gè)名字是自定義的),然后通過(guò) use 添加插件 
  2. config 
  3.   .plugin(name) 
  4.   .use(WebpackPlugin, args) 

舉個(gè)例子:

 
 
 
  1. const ExtractTextPlugin = require('extract-text-webpack-plugin'); 
  2.  
  3. // 先指定名字(這個(gè)名字可以自定義),然后通過(guò) use 添加插件,use 的第二個(gè)參數(shù)為插件參數(shù),必須是一個(gè)數(shù)組,也可以不傳 
  4. config.plugin('extract') 
  5.   .use(ExtractTextPlugin, [{ 
  6.     filename: 'build.min.css', 
  7.     allChunks: true, 
  8.   }]) 

2. 移除插件

移除一個(gè)插件很簡(jiǎn)單,還記得添加插件時(shí)我們指定了每個(gè)插件的 name 嗎?現(xiàn)在通過(guò)這個(gè) name 移除即可:

 
 
 
  1. config.plugins.delete('extract') 

3. 指定插件在 xx 插件之前/之后調(diào)用

比如,我現(xiàn)在需要指定 html-webpack-plugin 這個(gè)插件在剛剛寫(xiě)的 extract 插件之前執(zhí)行,那么這么寫(xiě)就行了:

 
 
 
  1. const htmlWebpackPlugin = require('html-webpack-plugin'); 
  2.  
  3. config.plugin('html') 
  4.   .use(htmlWebpackPlugin) 
  5.   .before('extract') 

通過(guò) before 方法,傳入另一個(gè)插件的 name 即可,表示在另一個(gè)插件之前執(zhí)行。

同樣,如果需要在 extract 插件之后執(zhí)行,調(diào)用 after 方法:

 
 
 
  1. config.plugin('html') 
  2.   .use(htmlWebpackPlugin) 
  3.   .after('extract') 

4. 動(dòng)態(tài)修改插件參數(shù)

我們也可以用 webpack-chain 來(lái)動(dòng)態(tài)修改插件的傳參,舉個(gè)例子:

 
 
 
  1. // 使用 tap 方法修改參數(shù) 
  2. config 
  3.   .plugin(name) 
  4.   .tap(args => newArgs) 

5. 修改插件初始化過(guò)程

我們也可以自定義插件的實(shí)例化的過(guò)程,比如下面這樣:

 
 
 
  1. // 通過(guò) init 方法,返回一個(gè)實(shí)例,這將代替原有的實(shí)例化過(guò)程 
  2. config 
  3.   .plugin(name) 
  4.   .init((Plugin, args) => new Plugin(...args)); 

loader

loader 是 Webpack 中必不可少的一個(gè)配置,下面我們來(lái)看看 loader 的相關(guān)操作。

1. 添加一個(gè) loader

 
 
 
  1. config.module 
  2.   .rule(name) 
  3.     .use(name) 
  4.       .loader(loader) 
  5.       .options(options) 

舉個(gè)例子:

 
 
 
  1. config.module 
  2.   .rule('ts') 
  3.   .test(/\.tsx?/) 
  4.   .use('ts-loader') 
  5.     .loader('ts-loader') 
  6.     .options({ 
  7.       transpileOnly: true 
  8.     }) 
  9.     .end() 

2. 修改 loader 參數(shù)

可通過(guò) tap 方法修改 loader 的參數(shù):

 
 
 
  1. config.module 
  2.   .rule('ts') 
  3.   .test(/\.tsx?/) 
  4.   .use('ts-loader') 
  5.     .loader('ts-loader') 
  6.     .tap(option => { 
  7.       // 一系列 
  8.       return options; 
  9.     }) 
  10.     .end() 

在所有的配置完成之后,可以通過(guò)調(diào)用config.toConfig()來(lái)拿到最后的配置對(duì)象,可以直接作為webpack的配置。

3. 移除一個(gè) loader

 
 
 
  1. // 通過(guò) uses 對(duì)象的 delete 方法,根據(jù) loader 的 name 刪除 
  2. config.module 
  3.   .rule('ts') 
  4.   .test(/\.tsx?/) 
  5.   .uses.delete('ts-loader') 

optimization

Webpack 中的optimization也是一個(gè)比較龐大的對(duì)象,參照官方文檔:https://webpack.js.org/configuration/optimization/。

這里以其中的 splitChunks 和 minimizer 為例來(lái)配置一下:

 
 
 
  1. config.optimization.splitChunks({ 
  2.      chunks: "async", 
  3.      minChunks: 1, // 最小 chunk ,默認(rèn)1 
  4.      maxAsyncRequests: 5, // 最大異步請(qǐng)求數(shù), 默認(rèn)5 
  5.      maxInitialRequests : 3, // 最大初始化請(qǐng)求數(shù),默認(rèn)3 
  6.      cacheGroups:{ // 這里開(kāi)始設(shè)置緩存的 chunks 
  7.          priority: 0, // 緩存組優(yōu)先級(jí) 
  8.          vendor: { // key 為entry中定義的 入口名稱 
  9.              chunks: "initial", // 必須三選一: "initial" | "all" | "async"(默認(rèn)就是async) 
  10.              test: /react|vue/, // 正則規(guī)則驗(yàn)證,如果符合就提取 chunk 
  11.              name: "vendor", // 要緩存的 分隔出來(lái)的 chunk 名稱 
  12.              minSize: 30000, 
  13.              minChunks: 1, 
  14.          } 
  15.      } 
  16. }); 
  17.  
  18. // 添加一個(gè) minimizer 
  19. config.optimization 
  20.   .minimizer('css') 
  21.   .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: {} }]) 
  22. // 移除 minimizer 
  23. config.optimization.minimizers.delete('css') 
  24. // 修改 minimizer 插件參數(shù) 
  25. config.optimization 
  26.   .minimizer('css') 
  27.   .tap(args => [...args, { cssProcessorOptions: { safe: false } }]) 

善用條件

配置之前提到過(guò),對(duì)于ChainSet和ChainMap對(duì)象都有條件配置方法when,可以在某些很多場(chǎng)景下取代 if-else,保持配置的鏈?zhǔn)秸{(diào)用,讓代碼更加優(yōu)雅。

 
 
 
  1. config.when( 
  2.   process.env.NODE === 'production', 
  3.   config.plugin('size').use(SizeLimitPlugin) 

小結(jié)

webpack-chain作為 webpack 的流式配置方案,通過(guò)鏈?zhǔn)秸{(diào)用的方式操作配置對(duì)象,從而取代了以前手動(dòng)操作 JavaScript 對(duì)象的方式,在方便復(fù)用配置的同時(shí),也使代碼更加優(yōu)雅,無(wú)論是從代碼質(zhì)量,還是開(kāi)發(fā)體驗(yàn),相對(duì)于之前來(lái)說(shuō)都是不錯(cuò)的提升,推薦大家上手使用。


本文標(biāo)題:我曾為配置Webpack感到痛不欲生,直到我遇到了這個(gè)流式配置方案
分享路徑:http://m.5511xx.com/article/ccoescc.html