不折騰的前端,和鹹魚有什麼區別css
返回目錄
都 2020 了,不會點 Webpack 好像有點說不過去。html
可是事實上若是不是分配到【架構組】之類的團體中,感受接觸 Webpack 的機率會少點吧。前端
就比如 jsliang 在上家公司,就沒機會接觸 Webpack,都是用這別人已經配置好的方案,純粹作一個業務仔~vue
返回目錄
Webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler
)。node
當 Webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph
),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle
。react
因此,它的本質是一個模塊打包器,其工做是將每一個模塊打包成相應的 bundle
。webpack
返回目錄
mode
:模式。對應有開發模式、生產模式等entry
:入口output
:出口loader
:模塊轉換器,用於把模塊原內容按照需求轉換成新內容。Webpack 對於 .jpg
、.txt
等內容沒法處理,就須要 file-loader
、url-loader
等進行協助處理。plugins
:擴展插件,在 Webpack 構建流程中的特定時機注入拓展邏輯來改變構建結果或者作其餘你想作的事情。返回目錄
Webpack 就像一條生產線,要通過一系列處理流程後才能將源文件轉換成輸出結果。nginx
這條生產線上的每一個處理流程的職責都是單一的,多個流程之間有存在依賴關係,只有完成當前處理後才能交給下一個流程去處理。 git
Webpack
的運行流程是一個串行的過程,從啓動到結束會依次執行如下流程:github
Shell
語句中讀取與合併參數,得出最終的參數Compiler
對象,加載全部配置的插件,執行對象的 run
方法開始執行編譯entry
找出全部的入口文件Loader
對模塊進行翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到全部入口依賴的文件都通過了本步驟的處理Loader
翻譯完全部模塊後,獲得了每一個模塊被翻譯後的最終內容以及它們之間的依賴關係Chunk
,再把每一個 Chunk
轉換成一個單獨的文件加入到輸出列表,這步是能夠修改輸出內容的最後機會簡單來講:
Plugin
,實例化 Compiler
(鉤子)Entry
出發,針對每一個 Module
(模塊)串行調用對應的 Loader
去翻譯文件的內容,再找到該 Module
依賴的 Module
,遞歸地進行編譯處理Module
組合成 Chunk
,將 Chunk
轉換成文件,輸出到文件系統中(Chunk
就是打包過程當中,入口模塊引用其餘模塊,模塊再引用模塊,這個關係鏈鏈接的 Module
就造成了 Chunk
)在這個過程當中,Webpack
會在特定的時間點廣播出特定的事件,插件在監聽到感興趣的事件後會執行特定的邏輯,而且插件能夠調用 Webpack
提供的 API
改變 Webpack
的運行結果。
返回目錄
指定打包⼊口文件,有三種不一樣的形式:string | object | array
。
一對一:一個入口、一個打包文件
module.exports = { entry: './src/index.js' }
多對一:多個入口、一個打包文件
module.exports = { entry: [ './src/index1.js', './src/index2.js', ] }
多對多:多個入口、多打包文件
module.exports = { entry: { 'index1': "./src/index1.js", 'index2': "./src/index2.js" } }
返回目錄
打包後的文件位置。
module.exports = { ..., output: { path: path.resolve(__dirname, "dist"), filename: "bundle.js", filename: "[name].js" } }
entry
爲對象),則不能使用單文件出口,須要使用下面的方式Webpack
內置的變量佔位符:[name]
返回目錄
loader
的執行順序是從右向左執行的,也就是後面的 loader
先執行。
假若有配置:
// webpack.config.js module.exports = { //... module: { rules: [ { test: /\.(le|c)ss$/, use: ['style-loader', 'css-loader', 'less-loader'], exclude: /node_modules/, }, ], }, };
那就是先處理 less-loader
,再處理 css-loader
,最後處理 style-loader
。
返回目錄
file-loader
:當引入的文件是 .png
、.txt
等時,能夠經過 file-loader
解析項目中的 url
引入。根據配置將文件拷貝到相應的路徑,並修改打包後文件的引入路徑,讓它指向正確的文件。url-loader
:url-loader
封裝了 file-loader
且能夠不依賴於 file-loader
單獨使用,而且能夠配置 limit
。對小於 limit
大小的圖片轉換成 Base64
,大於 limit
的時候使用 file-loader
裏的方法。返回目錄
tslint-loader
:經過 TSLint 檢查 TypeScript 代碼eslint-loader
:經過 ESLint 檢查 JavaScript 代碼返回目錄
html-withimg-loader
:處理 HTML 中的圖片返回目錄
style-loader
:動態建立 style
標籤,將 CSS 代碼插入到 head
中。css-loader
:負責處理 @import
、url
等語句。例如 import css from 'file.css'
、url(image.png)
。postcss-loader
:負責進一步處理 CSS 文件,好比添加瀏覽器前綴,壓縮 CSS 等。less-loader
:將 .less
文件內容轉換成 CSS。sass-loader
:將 .sass
文件內容轉換成 CSS。返回目錄
babel-loader
:將 JS 代碼向低版本轉換,咱們須要使用 babel-loader
。ts-loader
:將 TypeScript 轉換成 JavaScript返回目錄
返回目錄
clean-webpack-plugin
:打包前自動清理 dist
目錄,防止文件殘留。copy-webpack-plugin
:將單個文件或者整個目錄複製到構建目錄mini-css-extract-plugin
:將 CSS 抽離出來單獨打包而且經過配置能夠設置是否壓縮。html-webpack-plugin
:這個插件能夠配置生成一個 HTML5 文件,其中 script
標籤包含全部 Webpack 包。若是你設置多個入口點,你能夠據此實現多頁面應用打包。返回目錄
webpack-dashboard
:能夠更友好的展現相關打包信息。webpack-merge
:提取公共配置,減小重複配置代碼speed-measure-webpack-plugin
:簡稱 SMP,分析出 Webpack 打包過程當中 Loader 和 Plugin 的耗時,有助於找到構建過程當中的性能瓶頸。size-plugin
:監控資源體積變化,儘早發現問題HotModuleReplacementPlugin
:模塊熱替換返回目錄
Loader
Loader
本質上就是一個函數,對接收到的內容進行轉換,返回轉換後的結果。
由於 Webpack
只認識 JavaScript,因此 Loader
就成了翻譯官,對不一樣類型的資源進行處理。
就比如 file-loader
或者 url-loader
,配置以後就能夠正確引用 png
等格式的圖片、txt
等格式文件。
又比如 style-loader
以及 css-loader
,引用後就能夠對 CSS 內容進行預編譯處理。
Plugin
Plugin
就是插件,就比如 jsliang 編寫的 VS Code 插件同樣,Plugin
拓展了 Webpack
的功能。
Plugin
就是在 Webpack
的生命週期中進行各類操做,從而達到使用者目的插件。
就比如 html-webpack-plugin
,配合多入口形式使用以後,就能夠實現多頁面應用的功能。
又比如 clean-webpack-plugin
實現打包以前清空 dist
目錄,copy-webpack-plugin
能夠將單個文件或者整個目錄複製到構建目錄。
返回目錄
resolve
配置 Webpack 如何尋找模塊所對應的文件。
Webpack 內置 JavaScript 模塊化語法解析功能,默認會採用模塊化標準里約定好的規則去尋找,但你能夠根據本身的須要修改默認的規則。
// webpack.config.js module.exports = { //.... resolve: { modules: ['./src/components', 'node_modules'] // 從左到右依次查找 } }
resolve.modules
:配置 Webpack 去哪些目錄下尋找第三方模塊,默認狀況下,只會去 node_modules
下尋找,若是你在項目中某個文件夾下的模塊常常被導入,不但願寫很長的路徑,那麼就能夠經過配置 resolve.modules
來簡化。resolve.alias
:配置項經過別名把原導入路徑映射成一個新的導入路徑。resolve.extensions
:適配多端的項目中,可能會出現 .web.js
, .wx.js
,例如在轉 Web 的項目中,咱們但願首先找 .web.js
,若是沒有,再找 .js
。extensions: ['web.js', '.js']
。返回目錄
如何從 0 開始配置一個屬於本身的 Webpack 腳手架呢?那就涉及到選型問題。
返回目錄
返回目錄
['style-loader', 'css-loader', 'postcss-loader', 'less-loader']
less less-loader
:解析 .less
文件postcss-loader autoprefixer
:對 flex
佈局等進行前綴補充返回目錄
file-loader
:解析 .txt
、.png
、.md
等格式文件url-loader
:limit: 1024
,判斷大小是否處理成 base64
格式返回目錄
url-loader
返回目錄
glob
entry
和 htmlwebpackplugin
動態生成返回目錄
devtool: "cheap-module-eval-source-map
devtool: "cheap-module-source-map"
返回目錄
devServer
HMR
(熱模塊替換,Hot Module Replacement)HMR
,須要 Webpack
配合返回目錄
安裝:npm i babel-loader @babel/core @babel-preset-env -D
@babel/core
:babel
核心babel-loader
:babel
和 Webpack
的鏈接橋樑babel-preset-env
:輸出什麼樣的代碼,用它來解決babel-loader
:解析 ES6+@babel/polyfill
:墊片。包含全部 ES6+ 新特性代碼.babelrc
返回目錄
react react-dom
@babel/preset-react
返回目錄
loader
的文件範圍:loader
的 include
配置,能夠指定 src
目錄,減小檢查範圍。resolve.modules
配置:配置 Webpack
去哪些目錄下尋找第三方模塊,默認 node_modules
。MiniCssExtractPlugin
hash
、chunkhash
、contenthash
區別
hash
做用域 JS、CSS,圖片的 hash
有區別,每次打包構建都會變化一次。chunkhash
以 chunk
爲單位,修改了那部分就改動哪部分的 hash
。(同時依賴的模塊也會改變 hash
)contenthash
只有本身內容發生改變,才發生改變(區別於 chunkhash
。chunkhash
;CSS 適用於 contenthash
;Image 適用於 hash
optimize-css-assets-webpack-plugin
和 cssnano
html-webpack-plugin
img-webpack-loader
Webpack
配置:分離 base.config
、dev.config
、mpa.config
和 pro.config
4 個,經過 merge
進行 config
配置的合併更多看這裏:
返回目錄
Webpack
解析器Webpack loader
Webpack plugin
返回目錄
懶加載或者按需加載,是一種很好的優化網頁或應用的方式。
這種方式其實是先把你的代碼在一些邏輯斷點處分離開,而後在一些代碼塊中完成某些操做後,當即引用或即將引用另一些新的代碼塊。
這樣加快了應用的初始加載速度,減輕了它的整體體積,由於某些代碼塊可能永遠不會被加載。
返回目錄
代碼分割(code splitting
)是指:將腳本中無需當即調用的代碼在代碼構建時轉變爲異步加載的過程。
在 Webpack 構建時,會避免加載已聲明要異步加載的代碼,異步代碼會被單獨分離出一個文件,當代碼實際調用時被加載至頁面。
代碼分割技術的核心是 異步加載資源。
可喜的是,瀏覽器容許咱們這麼作,W3C stage 3
規範: whatwg/loader 對其進行了定義:你能夠經過 import()
關鍵字讓瀏覽器在程序執行時異步加載相關資源。
在 Vue 中,能夠直接使用 import()
關鍵字作到這一點,而在 React 中,你須要使用 react-loadable
去完成一樣的事。
返回目錄
children chunk
)import
)print.js
console.log('輸出 1'); export default () => { console.log('輸出 2'); };
index.js
const btn = document.querySelector('.btn'); btn.onclick = import('./print.js').then((module) => { const print = module.default; print(); });
返回目錄
Vue 的特色就是 SPA - Single Page Application(單頁應用程序)。
只有第一次加載頁面,之後的每次頁面切換,只須要進行組件替換。
它減小了請求次數,加快頁面響應速度,下降對服務器壓力等等。
可是,由於 Vue 是 SPA,因此首頁第一次加載時會把全部組件以及組件相關資源所有加載,從而致使網站首頁打開速度變慢,下降用戶體驗。
Vue 項目中,能夠結合 Webpack,在 vue-router
經過 import
進行動態加載:
const routes = [{ path: '/', name: 'Home', component: () => import('../views/Home.vue') }];
返回目錄
刷新咱們通常分爲兩種:
window.location.reload()
。WDS
(Webpack-dev-server
)的模塊熱替換,只須要局部刷新頁面上發生變化的模塊,同時能夠保留當前的頁面狀態,好比複選框的選中狀態、輸入框的輸入等。Webpack
的熱更新又稱熱替換(Hot Module Replacement
),縮寫爲 HMR
。
這個機制能夠作到不用刷新瀏覽器而將新變動的模塊替換掉舊的模塊。
返回目錄
在 Webpack 的 webpack.config.js
中:
devServer
的 hot
爲 true
plugins
中增長 new webpack.HotModuleReplacementPlugin()
// webpack.config.js const webpack = require('webpack'); module.exports = { //.... devServer: { hot: true }, plugins: [ new webpack.HotModuleReplacementPlugin() // 熱更新插件 ] }
而且在入口文件配置:
if(module && module.hot) { module.hot.accept() }
此時修改代碼的時候,只有對應部分的內容纔會相應更新。
返回目錄
HMR
的核心就是客戶端從服務端拉去更新後的文件,準確的說是 chunk diff
(chunk
須要更新的部分)。
實際上 webpack-dev-server
(WDS
)與瀏覽器之間維護了一個 Websocket
,當本地資源發生變化時,WDS
會向瀏覽器推送更新,並帶上構建時的 hash
,讓客戶端與上一次資源進行對比。
客戶端對比出差別後會向 WDS
發起 Ajax
請求來獲取更改內容(文件列表、hash
),這樣客戶端就能夠再借助這些信息繼續向 WDS
發起 jsonp
請求獲取該 chunk
的增量更新。
後續的部分(拿到增量更新以後如何處理?哪些狀態該保留?哪些又須要更新?)由 HotModulePlugin
來完成,提供了相關 API
以供開發者針對自身場景進行處理,像 react-hot-loader
和 vue-loader
都是藉助這些 API
實現 HMR
。
返回目錄
文件指紋是打包後輸出的文件名的後綴,對應着 3 種 hash
。
hash
是跟整個項目的構建相關,只要項目裏有文件更改,整個項目構建的 hash
值都會更改,而且所有文件都共用相同的 hash
值。(粒度整個項目)chunkhash
是根據不一樣的入口進行依賴文件解析,構建對應的 chunk
(模塊),生成對應的 hash
值。只有被修改的 chunk
(模塊)在從新構建以後纔會生成新的 hash
值,不會影響其它的 chunk
。(粒度 entry
的每一個入口文件)contenthash
是跟每一個生成的文件有關,每一個文件都有一個惟一的 hash
值。當要構建的文件內容發生改變時,就會生成新的 hash
值,且該文件的改變並不會影響和它同一個模塊下的其它文件。(粒度每一個文件的內容)返回目錄
source map
是將編譯、打包、壓縮後的代碼映射回源代碼的過程。打包壓縮後的代碼不具有良好的可讀性,想要調試源碼就須要 soucre map
。
map
文件只要不打開開發者工具,瀏覽器是不會加載的。
線上環境通常有三種處理方案:
hidden-source-map
:藉助第三方錯誤監控平臺 Sentry
使用nosources-source-map
:只會顯示具體行數以及查看源代碼的錯誤棧。安全性比 source map
高source map
:經過 nginx
設置將 .map
文件只對白名單開放(公司內網)注意:避免在生產中使用 inline-
和 eval-
,由於它們會增長 bundle
體積大小,並下降總體性能。
返回目錄
在 Webpack 簡單實現中,簡單的作了下如何將一份代碼進行打包:
babel
完成代碼轉換,並生成單個文件的依賴返回目錄
本系列參考文獻有 51 篇文章。
返回目錄
其餘:
2020 年文章:
2019 年文章:
2018 年文章:
2017 文章:
返回目錄
2019 年文章:
2018 年文章:
2017 年文章:
返回目錄
返回目錄
返回目錄
jsliang 的文檔庫由 梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。<br/>基於 https://github.com/LiangJunrong/document-library 上的做品創做。<br/>本許可協議受權以外的使用權限能夠從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處得到。