歡迎關注富途web開發團隊,缺人從眾
其實,說實話這篇文章的由來也是有很多的原因在裡面的。在這之前,我也做過不少的專案。有新的專案,也有舊的專案。通過對舊專案的不斷研究,改進。再結合自己的理解,將新的構建應用到新的專案中。經過時間的積累,慢慢的就有了一套感覺上還比較適合的webpack前端構建規範。
那這裡來說說,webpack4+構建上的一些事吧。
多入口的意思大概就是,訪問不同頁面的時候,主要的前端JS功能檔案是不同的。最好的對比和區別就是SPA單頁面應用,每個頁面引入的檔案都是同一份JS檔案。
我期望的構建是:
- 一氣呵成(編碼過程爽不爽)
- 極大程度脫離後端語言限制(解耦)
- 多入口(多入口,多頁面)
一氣呵成,意味著專案從你執行git clone
,拉取程式碼開始,直到你git push
推送程式碼。這之間,所有與編碼無關的,是一氣呵成的,並不需要你過多的配置。希望做到的就是編碼的極致體驗。整個過程,期望開發人員關心的只有一件事,就是自己編寫的程式碼是否OK。
那也意味著webpack構建需要做更多的事。
說起脫離後端語言,這並不是什麼好事,只不過要看專案合不合適。在最近寫的專案裡面,使用的是vue + Node.js
。使用vue ,一般意味著模版檔案裡面其他很少有Node.js模版(例如:jade,swig)程式碼,也很少有前端程式碼。也就是一個空殼頁面,做過SPA單頁面應用的應該比較熟悉。
那也就是這個空殼頁面,其實和後端語言沒有太大的耦合關係。那也意味著,我可以極大程度的做到前後端程式碼解耦。這是什麼意思?
試想一下,自己在開發過程中,需要關注的無非就2個東西:頁面,靜態資源。編碼上與後端有耦合的就是隻有頁面,就像上面說的,使用vue做SPA,其實頁面裡面其實並沒有和後端有耦合。
也就說,這為前後端結構上解耦,提供了便利。前端所有資源可以獨立出來,只要保證,通過構建之後,能將頁面,靜態資源生成到指定專案目錄即可。
那構建這裡就是由webpack來做。
上圖中已經標明:
- client:是放前端資源目錄
- server:是放後端資源的目錄。這裡假如後端為Node.js
- static:是靜態資源目錄。也就是js/css檔案放置的地方
那這裡就引出了一個值得先思考的問題,webapck構建的目的是什麼?落實到工程專案裡面,構建的目的又是什麼?
結合上面的目錄結構圖,如果說webpack的目的是將靜態資源打包編譯;那麼在工程上,就是將前端資源client
目錄資源通過webpack構建到指定的static
和server/views
目錄。
那這樣是不是就做到了極大程度的解耦呢。
那如何在單入口的webpak構建工程上進行修改變為多入口構建工程?這就是今天這篇文章需要解決的問題,也是我一直以來需要解決的問題,也是寫這篇文章的初衷。
面對這個多入口程式構建問題,這裡先從當前現狀說起吧。
注意:以下的所有內容都是在單入口的基礎上進行講述的,相關demo在這裡:webpack案例
webpack構建現狀
一直以來,webpack構建我只做了單入口構建。也就是大家熟悉的SPA。這也並沒有影響到專案的執行,因為專案功能單一,目標明確,資原始檔不會太大,所以打包壓縮之後,出來的檔案也不會很大,適當的進行拆分就可以。
如圖,構建很簡單,單入口,單頁面。所有的檔案都是通過main.js
和其引入的子模組引入,形成單入口。作為經典的SPA專案,就一個入口頁面index.html
,前端跳轉由前端路由和後端路由協作完成。
那麼需要webpack做的事情其實就很好理解了:
- 引入對應檔案的模組解析。例如:
vue-loader
,babel-loader
,css-loader
等 - 提取css為外部引入,通過
link
標籤引入 - 檔案壓縮
- 大檔案拆分
- 公共檔案提取為獨立檔案
- 通過
html-webpack-plugin
將所有依賴的js/css等靜態資源注入模版檔案,生成目標檔案儲存到指定伺服器模版檔案目錄
都說了,其實前端最後需要處理的檔案大概率就3個html
,js
,css
。
demo詳情地址-->> 單入口案例
webpack4+ 多入口構建思路
既然都已經知道單入口構建怎麼玩的了。那麼就來思考一下webpack多入口構建怎麼玩唄。
先不說,webpack怎麼配置。從需求上來說,不就是期望:
- 有很多的入口檔案
- 有很多的html模版檔案生成。這裡會生成到
server/views
目錄 - html模版檔案引入自己模組需要的js/css等靜態資源即可,其他模組的不引入,以免產生冗餘程式碼
上圖的靜態資源js/css會生成並儲存到static
目錄。
也就是說上圖的pagea.js
入口檔案,通過webpack構建之後,只會注入pagea.html
。而不會注入pageb.html
。
這裡其實難點,就一個:如何讓對應的入口檔案的html模版檔案,引入只與本模組有關的js/css。
webpack4+ 多入口構建配置實戰
那不廢話,實戰中要如何配置呢?這恐怕並不是只有我一個人想知道。其實上面的每個問題在這裡都有解決的方案。
如圖,可以看到多入口配置,超級簡單在entry
新增對應模組入口即可。
entry:{//入口檔案
pagea:'./client/pagea/index.js',
pageb:'./client/pageb/index.js'
}
複製程式碼
這裡demo裡面有2個入口檔案pagea.js
和pageb.js
。
針對這個如何讓對應的入口檔案的html模版檔案,引入只與本模組有關的js/css問題。
可以通過html-webpack-plugin
解決。首先配置多個html-webpack-plugin
例項物件,然後指定每個例項物件需要引入的chunks
檔案即可。
new HtmlWebpackPlugin({
filename: './../../server/views/pagea.html',
chunks:['pagea'],
template: path.resolve(__dirname , './client/template.html')
}),
new HtmlWebpackPlugin({
filename: './../../server/views/pageb.html',
chunks:['pageb'],
template: path.resolve(__dirname , './client/template.html')
})
複製程式碼
這裡配置很簡單。pagea.html
配置只引入pagea.js
。當需要引入多個的時候只需要在陣列裡面新增對應的模組名稱即可。
配置完了,來看看結果如何吧。
執行npm install
先下載完所需要的模組,再通過執行webpack
命令進行構建。
webpack請全域性安裝,需要 v4.5+。
可以看到,通過webpack打包編譯,生成了我們想要的pagea.html
和pageb.html
。並且js檔案注入正常。
那現在可執行npm run develop
命令啟動node.js服務。在瀏覽器開啟127.0.0.1:4000
就看到了頁面了。
pagea.html
和pageb.html
,引入正常,並正常執行。大功告成!!!!
demo詳情地址-->> 多入口案例
webpack4+ 優化
當你以為一切迴歸平靜時,其實才是挑戰的開始。要做到多入口,其實感覺還是挺簡單的。要做的好,其實距離還是很遠的。再往下的篇幅其實已經和多口構建沒有多少關係了。主要是一些基於webpack4+ 優化的點,也就是遇到相關問題的解決方案。
Split Chunks模組拆分
專案小的時候,感覺什麼都是那麼爽。啥事也沒有。可是專案一旦變得複雜,那麼其實很多之前沒有遇到的問題就會暴露無遺。
當我在pagea.js
嘗試引入vue
,tui-chart
圖表模組的時候,發現了打包出來的檔案過於龐大,達到了2.2MB
,即使壓縮之後一樣。
那麼是時候引入檔案拆分了,因為webpack4+之後,並不建議再使用CommonChunks
模組,所以使用新的官方推薦的SplitChunks
模組。
通過在webpack的plugin
裡面新增:
new webpack.optimize.SplitChunksPlugin({
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '-',
name: true,
cacheGroups: {
vue: {
test: /[\\/]node_modules[\\/]vue[\\/]/,
priority: -10,
name: 'vue'
},
'tui-chart': {
test: /[\\/]node_modules[\\/]tui-chart[\\/]/,
priority: -20,
name: 'tui-chart'
}
}
})
複製程式碼
新增splitChunks方式有多種,上面只是其中一種。
通過在cacheGroups
裡面設定公共模組,達到模組複用。需要注意的就是,在html-webpack-plugin
例項中引入chunks
時,需要加入對應的模組。
new HtmlWebpackPlugin({
filename: './../../server/views/pagea.html',
chunks:['vue','tui-chart','pagea'],
template: path.resolve(__dirname , './client/template.html')
})
複製程式碼
上面的pagea.html
不僅需要引入pagea
,還需要而為引入vue
和tui-chart
。
通過上圖,最後看到打包拆分出來的js檔案體積還是很可觀的。
MiniCssExtract提取為外部CSS
說完了JavaScript的體積拆分,其實CSS上面也有一個問題。就是,我並沒有在上面的demo中做到通過link
標籤引入。這裡將解決這個問題。
webpack4+ 提供了一個新的模組叫做MiniCssExtract。這個模組就可以處理.css
外鏈引入的問題。
首先在rules
裡面配置:
{
test: /\.s?[ac]ss$/,//postcss-loader 依賴 postcss-config.js
use: [MiniCssExtractPlugin.loader,'css-loader','postcss-loader','sass-loader']
}
複製程式碼
主要是將原來的style-loader
替換成MiniCssExtractPlugin.loader
。如果需要區分環境,進行不同引入也是可以的。
然後需要在下面進行plugins
引入:
new MiniCssExtractPlugin({ //提取為外部css程式碼
filename:'[name].css?v=[contenthash]'
})
複製程式碼
當一切完成之後。執行相關命令。
可以看到,生成的html檔案成功的引入了自己需要的檔案。
是不是成功了呢? 哈哈。。。。。
趕緊去驗證吧!!!!!!一定要驗證哦。。。。。。。。。。
demo詳情地址-->> 多入口優化案例
總結
大體上,webpack4+構建和其他版本的沒有多大區別,最多就是模組的使用有點不同。不過對於我來說,解決了我原來糾結的多入口構建問題。但同時這也是一個demo,算不上是一個完整的構建。還缺很多的東西,但是基礎已經在這裡了,所以可以在此基礎上優化,最終達到自己想要的構建配置。
最後有一個問題,那就是所有打包後生成的檔案入不入版本庫呢?
這裡我給出所謂答案在這篇文章:小馬的大前端之路--Node.js初探