WEBPACK
原文連結及程式碼檢視請進入github 如果喜歡,請動動您可愛的小手點亮star--- ^.^
一、從0搭建自己的webpack開發環境
1.什麼是Webpack
- 靜態模組打包器
- 功能:
- 程式碼轉換;
- 檔案優化;在生產環境不會壓縮JS、CSS....
- 程式碼分割;提取多個頁面的公共程式碼,提取首屏不需要執行部分讓其非同步載入
- 模組合併;模組化的專案裡會有多個模組和檔案,需要構建功能把模組分類合併成一個檔案
- 自動重新整理;監聽本地更改並重新整理頁面
- 程式碼校驗;提交到git倉庫前校驗程式碼
- 自動釋出;自動構建線上釋出程式碼並傳輸給釋出系統
- webpack命令:
- 檢視版本號:npx webpack -v
- 安裝指定版本:webpack@3.12.0 webpack-cli
- 開啟檔案監聽模式:webpack --watch (消耗效能,如果想提升開發速度,完全可以使用webpack-dev-server)
2.初始化專案
- npm init -y // 生成package.json檔案
- npm install webpack webpack-cli --save-dev // 生成node_modules資料夾
- webpack-cli --mode 可以解析傳遞引數
3.Webpack快速上手
- 打包:
- webpack webpack-cli // 預設讀取根目錄下的src資料夾
- npx webpack
- 開發環境development && 生產環境 production;可以在package.json中進行指令碼配置
- 打包入口和出口的個性化配置,webpack.config.js
- 配置拆分:通過引數判斷當前環境,載入指定配置檔案;
- 合併配置檔案:npm install webpack-merge
- 生產環境預設打包配置
小記
- hash命名檔案在webpack中的幾個區別:
- hash:每次打包都會更改檔名,
- chunkhash:每個入口對應chunk,會根據入口檔案中的更改內容決定獨立打包某個入口所對應的檔案;
- contenthash:根據檔案內容是否變化來決定是否打包該檔案;
- mode取值,會將process.evn.NODE_ENV的值設定為production || development [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-r3w4L8pB-1582959864761)(./static/process.env.png)]
4.Webpack-dev-server
啟動本地服務,使用webpack-dev-server,npm install webpack-dev-server在記憶體中打包,不會產生實體檔案; devServer配置;
5.打包html外掛
使用html-webpack-plugin自動生成html檔案並且引入打包後的js內容;
6.清空打包結果
使用clean-webpack-plugin ,在每次打包之前都清除dist檔案下的目錄;
二、 Webpack中必須要掌握的配置
- 前言:webpack預設配置(零配置),非常弱,靈活性差,所以需要掌握一些配置;
- 開發相關:
-
sourceMap:原始碼與打包後的程式碼的對映關係,通過sourceMap定位到原始碼;在dev模式中,預設開啟,[devtool](https://webpack.js.org/configuration/devtool/),線上不推薦開啟; 複製程式碼
- WebpackDevServer:
- 作用:提升開發效率的利器,每次改完程式碼都需要重新打包一次,開啟瀏覽器,重新整理一次,很麻煩。我們可以安裝webpack-dev-server;
- 原理:啟動服務後,會發現dist目錄沒有了,這是因為devServer把打包後的模組不會放在dist目錄下,而是放在記憶體中;
- 配置:通過devServer選項指定埠號(port)、內容存放目錄(contentBase)、本地代理配置(proxy)等等...
-
- 解析CSS :需要強調一下loader的執行順序,預設是從下往上執行,從右邊向左邊
- css-loader:解析css語法
- style-loader:將解析的css變成style標籤,插入到頁面中
- css前處理器 .scss node-sass sass-loader .less less-loader ...
- 安裝:npm install node-sass sass-loader;
- 配置:rules
// 注意在a.css檔案中再通過@import引入a.sass檔案的配置方式
use: ['style-loader', {
loader: 'css-loader',
options: { // 給loader傳遞引數
importLoader: 1 // 代表後面引數: sass-loader
}
}, 'sass-loader']
複製程式碼
-
css樣式相容自動填充字首 附:檢視css樣式相容性的網址
- postcss-loader ,查詢有相容性要求的css屬性
- autoprefixer,自動填充ms-|| webpack-...字首
- 配置:
{ test: /\.css$/, use: [ 'style-loader'', 'css-loader', 'sass-loader', { loader: 'postcss-loader', options: { // 給loader傳遞引數 plugins: () => [ require('autoprefixer')({ overrideBrowserslist: ["last 2 versions", ">1%"] }) ] } } ] } 複製程式碼
- mini-css-extract-plugin, 抽離css樣式檔案,抽離的好處是 css檔案可以和js並行載入
-
解析圖片+icon
- file-loader,配置圖片格式匹配
{ test: /\.(jpe?g|png|gif)$/, use:'file-loader' } 複製程式碼
-
js相關
-
@babel/core @babel/preset-env babel-loader,
- 用法:babel-loader是webpack與babel通訊的橋樑(不會把es6轉es5) @bebel-preset-env負責es6->es5,
test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ["@babel/preset-env"] } } 複製程式碼
- @babel/polyfill的使用: 在入口檔案index.js中import
import "@babel/polyfill" 複製程式碼
但是會導致bundle.js非常龐大,所以我們希望按需引入,useBuiltIns選項是babel7的新功能,告訴babel如何配置@babel/polyfill,具體配置見/root/.babelrc 小記 當我們開發元件庫時、工具庫時,polyfill就不適合了,因為polyfill是注入到全域性變數window下,會汙染全域性環境;開發元件庫時,推薦閉包方式:@babel/plugin-transform-runtime
- 避免js程式碼 重用:@babel/plugin-transform-runtime
- ts配置:@babel-preset-typescript
type State = Readonly<typeof initState> // 把initState中的屬性拿出來變成只讀的 複製程式碼
-
terser-webpack-plugin,壓縮js檔案
-
-
react+vue...
-
多入口配置 實踐:入口配置為物件,出口配置多個HTMLWebpackPlugin,通過 chunks 屬性定義好對應的入口檔案
三、 Webpack打包優化(打包大小、打包速度、模組拆分)
1、壓縮+刪除無用程式碼;
- 壓縮css mini-css-extract-plugin
- 刪除無用css樣式 purgecss-webpack-plugin
- 查詢匹配檔案 glob
- 圖片壓縮外掛(降低解析度 ) image-webpack-loader
2、Tree-shaking(webpack自帶) && Scope-hoistiong
- Tree-shaking
- 作用:去除掉js無用程式碼;
- 適用範圍:預設只支援 es6語法,靜態匯入,只在生產環境使用;
- 配置:
optimization: { usedExports: true } 複製程式碼
- 需要注意的是:通過import引入的可執行檔案程式碼,但是並未真實使用,需要在package.json中配置:"sideEffects": true, l(注意該種辦法的副作用:如果引入css檔案:import 'a.css',也會被去除),可以根據需要指定檔案型別:
"sideEffects": [ "**/*.css" // glob語法 ] 複製程式碼
- Scope-hoistiong(自帶)
- 作用:由於webpack打包的每個模組都會生成一個函式,會導致記憶體過大,所以,引入scope-hoistiong,作用域提升,減少作用域
3、DllPlugin && DllReferencePlugin
- DllPlugin 動態連結庫 某種方法實現了拆分 bundles,同時還大大提升了構建的速度(對專案執行優化沒有幫助)
- 打包第三方庫
- 配置:/root/build/webpack.dll.js 注:可以通過指定libraryTarget 來決定匯出方式(匯出方式即圖中所示) [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-YHjWWGjk-1582959864764)(./static/library_result.png)]
- DllReferencePlugin 在專案中可以找到 上一步打包好的dll中的指定檔案;
new DllReferencePlugin({ manifest: path.resolve(__dirname, '../dll/mainfest.json') }) 複製程式碼
4、程式碼分割
- 程式碼分割:即第三方庫抽離,不同於dll這個是做快取:生產環境下,自動將第三方庫進行抽離:optimization.splitchunks
- 配置:/root/util/webpack.base.js -> optimization.splitChunks,可以通過引數指定什麼情況下自動分割程式碼,
DllPlugin與Optimization.splitChunks的區別
區別比較 | 是否優化頁面載入速度? | 執行時機 | 建議使用場景 |
---|---|---|---|
DllPlugin | 否 | 構建之前抽離 | 開發環境提升打包速度 |
Optimization.splitChunks | 是 | 編譯過程中抽離 | 生產環境分割第三方程式碼 |
5、動態載入;
- 草案語法:import()
- 使用:動態匯入,可以實現程式碼分割,應用在類比、路由懶載入...;
- 原理:JSONP;
- 語法:返回值為Promise物件;
- 為動態載入的檔案更改檔名的配置:chunkFilename + 魔術字串
6、熱更新(模組熱替換Hot Module Replacement);
- 定義:模組熱替換是Webpack提供的最有用的功能之一,它允許在執行時替換、新增、刪除各種模組,而無需進行完全重新整理重新載入整個頁面;瞭解更多點選進入官網
- 實現:
- 保留在完全重新載入頁面時丟失的應用程式的狀態;
- 只更新改變內容,節省開發時間;
- 調整樣式更加快速,幾乎等同於在瀏覽器偵錯程式中更改樣式;
- 配置:
devServer: { hot: true } new webpack.NamedModulesPlugin() 複製程式碼
- 讓js支援熱更新:
如果在專案中使用,不用單獨配置,配置框架loader即可,import sum from './sum' console.log(sum(1, 2)) if (module.hot) { // 判斷是否支援熱更新 module.hot.accept() // 當入口檔案變化後重新執行當前入口檔案,原理是監聽到變化後,刪除dom再重新將新的新增到文件中; } 複製程式碼
7、happypack;
happypack多執行緒打包,將不同的邏輯交給不同的執行緒來處理
8、CDN載入檔案;
- 意義:webpack打包出來的都會放到bundle.js(出口檔案)中,bundle.js會非常龐大,所以我們引入CDN,拆分bundle.js
- 使用:bootcnd,找到外掛,複製script標籤,貼上進模板檔案中,但是當檔案較多時,不能都在index.html中引入,所以可以使用 add-asset-html-cdn-webpack-plugin 外掛
plugins: [ new AddCdnPlugin(true, { 'jquery': 'https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js' }) ] 複製程式碼
- 配置:宣告外部檔案
externals: { 'jquery': '$' // 引入外部變數,在使用$時,是從外部引入的jq,不去打包程式碼中的jquery } 複製程式碼
9、IgnorePlugin;
忽略import和require語法
10、noParse;
module.noParse,對類似jq這類依賴庫,內部不會引用其他庫,我們在打包的時候沒有必要去解析,這樣能夠增加打包速率
noParse: /jquery/
複製程式碼
11、resolve;
resolve: {
extensions: [".js", ".jsx", ".json", ".css"],
alias: {},
modules: ['node_modules']
}
複製程式碼
12、include/exclude;
在使用loader 時,可以指定哪些檔案不通過loader,或者指定哪些檔案通過loader
13、打包檔案分析工具
-
打包分析工具:webpack-bundle-analyzer 可以分析打包依賴關係,以及包的大小
-
費時分析:speed-measure-webpack-plugin 可以計算每一步執行的執行速度
四、原理
- 簡單實現一個檔案匯入,程式碼轉換:見/root/util/bundle.js
- 簡單實現一個loader 官網描述
- 簡單編寫一個plugins 官網描述 外掛是可以作用在webpack打包的整個生命週期中,所以需要了解compiler鉤子 、compilation鉤子