Webpack
- 基本使用
- 核心概念
- 處理樣式資源
- 步驟:
- 處理圖片資源
- 修改圖片輸出文件目錄
- 自動清空上次打包的內容
- Eslint
- Babel
- 處理HTML資源
- 搭建開發服務器
- 生產模式
- 提取css文件為單獨文件
- 問題:
- Css壓縮
- HTML壓縮
- 小結1
- 高級
- SourceMap
- 開發模式
- 生產模式
- HMR
- OneOf
- Include/Exclude
- Cache
- Thead
- Tree Shaking
- Babel
- 壓縮圖片
- Code Split
- 多入口
- 按需加載
- Preload / Prefetch
- Core-js
- PWA
- 總結
基本使用
- webpack是一個靜態資源打包工具
- 他會以一個或者多個文件作為打包的入口,將我們整個項目所有文件編譯組合成一個或者多個文件輸出出去
- 輸出的文件就是編譯好的文件,就可以在瀏覽器中運行了
- 我們將webpack輸出的文件叫做bundle
核心概念
- entry(入口):指示Webpack從哪個文件開始打包
- output(輸出):指示Webpack打包完的文件輸出到哪里去,如何命名等
- loader(加載器):webpack本身只能處理js、json等資源,其他資源需要借助loader、webpack才能解析
- plugins(插件):擴展webpack的功能
- mode(模式):
- 開發模式:development
- 生產模式:production
- 開發服務器:devServer
處理樣式資源
- webpack本身是不能識別樣式資源的,所以我們需要借助Loader來幫助Webpack解析樣式資源
步驟:
- 安裝相應的loader
- 在webpack.config.js中進行配置
- npx webpack進行打包即可
處理圖片資源
- 將小于10kb的圖片轉為base64編碼格式
//處理圖片資源{test: /\.(png|jpg|gif|jpeg|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, //小于10kb的圖片,會被base64處理},},},
修改圖片輸出文件目錄
- 添加generator屬性
//處理圖片資源{test: /\.(png|jpg|gif|jpeg|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, //小于10kb的圖片,會被base64處理},},generator: {//輸出圖片名稱filename: "static/images/[hash][ext][query]",},},
自動清空上次打包的內容
- 在output中的clean屬性設置為true
Eslint
- 可組裝的Javascript和JSX檢查工具
- 它是用來檢測js和jsx語法的工具,可以配置各項功能
Babel
- JavaScript編譯器
- 主要用于將ES6編寫的代碼轉換為向后兼容的JavaScript語法,以便能夠運行在當前和舊版本的瀏覽器或者其他環境中
處理HTML資源
- Defer的作用:在 HTML 中,
搭建開發服務器
- 自動化:devServer
- 在webpack.config.js中進行配置
//開發服務器devServer:{host:"localhost", //啟動服務器域名port:"3000", //啟動服務器端口open:true // 是否自動打開瀏覽器},
生產模式
- 生產模式是開發完成代碼后,我們需要得到代碼將來部署上線
- 這個模式下我們主要對代碼進行優化,讓其運行性能更好,優化主要從兩個角度出發:
- 優化代碼運行性能
- 優化代碼打包速度
提取css文件為單獨文件
- css文件目前被打包到js文件中,當js文件加載時,會創建一個style標簽來生成樣式
- 這樣對于網站來說會出現閃屏現象,用戶體驗不好
- 我們應該是單獨的css文件,通過link標簽加載性能更好
- 使用下面的插件
mini-css-extract-plugin
問題:
- 為什么通過style標簽加載css會出現閃屏現象,但是通過link標簽則不會呢
- 當您通過
Css壓縮
npm install css-minimizer-webpack-plugin --save-dev
HTML壓縮
- 默認生產模式已經開啟了:HTML壓縮和js壓縮
小結1
高級
- 所謂高級配置其實就是進行Webpack優化,讓我們代碼在編譯/運行時性能更好
SourceMap
- SourceMap(源代碼映射)是一個用來生成源代碼與構建后代碼一一映射的文件的方案。
- 作用:它會生成一個xxx.map文件,里面包含源代碼和構建后代碼每一行、每一列的映射關系。當構建后代碼出錯了,會通過xxx.map文件,從構建后代碼出錯位置找到映射后源代碼出錯位置,從而讓瀏覽器提示源代碼文件出錯位置,幫助我們更快的找到錯誤根源
開發模式
cheap-module-source-map
- 優點:打包編譯速度快,只包含行映射
- 缺點:沒有列映射
module.exports = {mode:"development",devtool:"cheap-module-source-map"
}
生產模式
source-map
- 優點:包含行/列映射
- 缺點:打包編譯速度更慢
module.exports = {mode:"production",devtool:"source-map"
HMR
- 全稱:
HotModuleReplacement(HMR/熱模塊替換)
:在程序運行中,替換、添加或者刪除模塊,而無需重新加載整個頁面
OneOf
- 為什么:打包時每個文件都會經過所有loader處理,雖然因為test正則原因實際沒有處理上,但是都要過一遍,比較慢
- 是什么:顧名思義就是只能匹配上一個loader,剩下的就不匹配了
Include/Exclude
- 為什么:開發時我們需要使用第三方庫和插件,所有文件都下載到node-modules中了,而這些文件是不需要編譯可以直接使用的,所以我們在對js文件處理時,要排除node-modules下面的文件
- 是什么:
- include:包含,只處理xxx文件
- exclude:排除,除了xxx文件以外其他文件都處理
Cache
- 為什么:每次打包時js文件都要經過Eslint檢查和Babel編譯,速度比較慢。我們可以緩存之前的Eslint檢查和Babel編譯結果,這樣第二次打包時速度就會更快了。
- 是什么:對Eslint檢查和Babel編譯結果進行緩存
Thead
- 為什么:當項目越來越大時,打包速度越來越慢。我們想要繼續提升打包速度,其實就是要提升js的打包速度,因為其他文件都比較少。而對js文件處理主要就是eslint、babel、Terser三個工具,所以我們要提升他們的運行速度,我們可以開啟多進程同時處理js文件,這樣速度就比之前的單進程打包更快了
- 是什么:多進程打包:開啟電腦的多個進程同時干一件事,速度更快。
需要注意:請僅在特別耗時的操作中使用,因為每個進程啟動就有大約為600ms左右的開銷。
Tree Shaking
- 用來減少代碼體積
- 為什么:開發時我們定義了一些工具函數庫,或者引用第三方工具函數庫或者組件庫。如果沒有特殊處理的話我們打包時會引入整個庫,但是實際上可能我們可能只用上極小部分的功能。這樣將整個庫都打包進來,體積就太大了。
- 是什么:Tree Shaking是一個術語,通常用于描述移除Javascript中的沒有使用上的代碼。
注意:它依賴ES Module
生產模式下自動開啟了這個功能
Babel
- Babel-runtime
壓縮圖片
- 開發如果項目中引用了較多圖片,那么圖片體積會比較大,將來請求速度比較慢。我們可以對圖片進行壓縮,減少圖片體積。
注意:如果項目中圖片都是在線鏈接,那么就不需要了,本地項目靜態圖片才需要進行壓縮。 - 插件:
image-minimizer-webpack-plugin
Code Split
- 作用:優化代碼運行性能
- 為什么:打包代碼時會將所有js文件打包到一個文件中,體積太大了。我們如果只要渲染首頁,就應該只加載首頁的js文件,其他文件不應該加載
- 所以我們需要將打包生成的文件進行代碼分割,生成多個js文件,渲染哪個頁面就只加載某個js文件,這樣加載的資源越少,速度就更快。
- 是什么:代碼分割,主要做了兩件事
- 分割文件:將打包生成的文件進行分割,生成多個js文件。
- 按需加載:需要哪個文件就加載哪個文件
多入口
- 有多個入口文件就是多入口
- 打包后會生成多個文件
entry: {//有多個入口文件:多入口main: "./src/main.js",app: "./src/app.js",},
按需加載
- 可以使用import的動態導入,會將動態導入的文件代碼分割(拆分成單獨模塊),在需要使用的時候自動加載。
- 返回值是一個
promise
對象
//動態import
const btn = document.getElementsByClassName("btm");
btn[0].addEventListener("click", () => {import("./count.js").then((res) => {console.log(res.default(1, 6));}).catch((err) => {console.log(err);});
});
Preload / Prefetch
- 為什么:前面已經做了代碼分割,同時會使用import動態導入語法來進行代碼按需加載(也叫懶加載,比如路由懶加載就是這樣實現的)。但是加載速度還不夠好,比如:是用戶點擊按鈕時才加載這個資源的,如果資源體積很大,那么用戶會感覺到明顯卡頓效果。我們想在瀏覽器空閑時間,加載后續需要使用的資源,我們就需要用上preload和prefetch技術。
- 是什么:
- Preload:告訴瀏覽器立即加載資源
- Prefetch:告訴瀏覽器在空閑時才開始加載資源
- 共同點:
- 都只會加載資源,并不執行。
- 都有緩存
- 區別:
- Preload加載優先級高,Prefetch加載優先級低
- Preload只能加載當前頁面需要使用的資源,Prefetch可以加載當前頁面資源,也可以加載下一個頁面需要使用的資源
- 總結:
- 當前頁面優先級高的資源用Preload加載。
- 下一個頁面需要使用的資源用Prefetch加載。
Core-js
- 為什么:babel對js代碼的兼容性處理不能做到面面俱到,一旦遇到低版本瀏覽器會直接報錯,所以我們想要將js兼容性問題徹底解決
- 是什么:
core-js
是專門用來做ES6以及以上API的polyfill
。polyfill
翻譯過來叫做墊片/補丁。就是用社區上提供的一段代碼,讓我們在不兼容某些新特性的瀏覽器上,使用該新特性。 - 完整引入:
import 'core-js'
- 按需加載:
import "core-js/es/promise"
PWA
- 為什么:開發Web App項目,項目一旦處于網絡離線情況,就沒法訪問了。
- 是什么:漸進式網絡應用程序(progressive web application),是一種可以提供類似于native app(原生應用程序)體驗的Web App的技術。其中最重要的是,在離線時應用程序能夠繼續運行功能。內部通過
Service Workers
技術實現