webpack 是代碼編譯工具,有入口、出口、loader 和插件;webpack 是一個用于 JavasScript 應用程序的靜態模塊打包工具;當 webpack 處理應用程序時會遞歸構建一個依賴關系圖(dependency graph),其中包含應用程序的每一個模塊,然后將這個模塊打包成一個或者多個 bundle。
webpack 的本質是模塊化打包工具,前端所有的資源都應當看成是一個模塊,通過 webpack 的核心機制 loader 來處理,然后借助插件機制 plugin 來形成一個繁榮的生態;
學習可參考 webpack 中文文檔;webpack 版本:5.73.0
文章目錄
一、為什么使用 webpack
二、webpack 學習起步
1、解決作用域問題
2、代碼拆分問題
3、讓瀏覽器支持模塊
4、構建工具對比
11.1、公共路徑(publicPath)
11.2、環境變量
11.3、拆分配置文件
11.4、合并配置文件
11.5、npm 腳本
10.1、配置輸出文件名
10.2、緩存第三方庫
10.3、將所有的 js 文件放到一個文件夾中
9.1、配置入口節點
9.2、防止重復
9.3、動態導入
9.3.1、懶加載
9.3.2、預加載模塊
7.1、加載 css
7.2、抽離和壓縮 css
7.3、加載 fonts 字體
7.4、加載數據
7.5、自定義 JSON 模塊 parser
6.1、resource 資源
6.2、inline 資源
6.3、source 資源
6.4、通用資源類型 asset
1、安裝
2、運行打包
3、自定義 webpack 配置
4、自動引入資源
5、mode 選項
6、資源模塊 module
7、loader
8、babel-loader
9、代碼分離
10、緩存
11、拆分開發環境和生產環境的配置
一、為什么使用 webpack
1、解決作用域問題
問題原因:
傳統的 JavaScript 文件引入方式會在 window 對象上面綁定全局的變量,這也會嚴重的污染 window 對象,使得 window 對象變的臃腫;
解決辦法:
1、我們早期使用管理項目資源的工具 Grunt 和 Gulp ,他們是將所有項目文件拼接在一起,其實是使用了 JavaScript 的立即執行函數來解決作用域的問題,立即執行函數簡稱 IIFE ;當腳本被封裝在 IIFE 內部時,我們可以安全的拼接和組合文件而不必擔心作用域問題。
;(function(){
let test = 'xxx'
})()
console.log(test) //is not defined
let res = (function(){
return 'xxx'
})()
console.log(res) //xxx
上面是一個立即執行函數,如果在立即執行函數外面調用 test,test 是 ‘is not defined’ ,說明在立即執行函數中的變量是不能夠在外部訪問的,這樣就不會污染到 window;如果想暴露一些東西給 window,則可以使用一個變量,將自執行函數賦值給這個變量,然后就可以在 window 中訪問自執行函數的返回值;
2、代碼拆分問題
問題原因:
使用立即執行函數,將所有代碼整合到同一個文件中,會造成代碼體積過大,構建和加載的適合效率很慢,所有不得不對代碼進行拆分;
解決辦法:
commonJS 運行是基于 node.js 環境的,commonJS 的問世引入了一個 require 的機制,它允許我們在當前文件中去加載和使用某個模塊,只導入需要的模塊;
const add = (a,b) => {
return a+b
}
const minus = (a,b) => {
return a-b
}
module.exports = {
add,
minus
}
//引入 serve.js
const math = require(./math.js)
console.log(math.add(1,2)) //3
上面代碼我們通過 module.exports
來暴露對象,使用頁面通過 require 來引入整個 module.exports
暴露出來的對象;需要注意的是 node 需要在 node.js 環境中運行,所以想查看這個效果需要開啟 node 服務:打開控制臺,找到需要運行的 JavaScript 文件 serve.js,執行 node serve.js
就可以在控制臺看到結果;
3、讓瀏覽器支持模塊
1、借助 require.js (不夠簡潔)
定義 add 方法,通過 define 暴露出來,define 第一個參數是一個數組,里面填寫所需要依賴的文件路徑;在 html 頁面引入 require.js 文件,通過 data-main 來綁定入口文件;在入口文件 main 中,使用require 方法,第一個參數是所需要的依賴文件,第二個參數是個方法,你可以在方法中使用add方法,并返回,這個返回值在瀏覽器中是可以查看的;
2、借助 ECMAScript 標準(瀏覽器支持不完整)
//add.jsconst add =(a,b)=> {return a+b}export default add;//html <script type="module>import add from './add.js'</script>
或者
//add.jsexport const add =(a,b)=> {return a+b}//html <script type="module">import { add } from './add.js'</script>
這里需要聲明 script 的 type = 'module'
;同時使用 export(輸出多個)和 export default (輸出單個)暴露出來的方法引入時也有一點差別;
上面這些手段雖然都能解決對應的問題,但是會比較麻煩,這里我們就引出 了更加強大的工具 webpack ;它可以打包 JavaScript 應用程序,支持 ES 模塊化標準和 commonJS,可以擴展支持圖片、字體文件、樣式文件等靜態資源打包;
4、構建工具對比
1、Webpack:適合一些復雜的應用,可以集成很多第三方庫,可以拆分代碼,使用靜態資源文件,支持 commonJS、esmodule 等模塊化模式;
2、Parcel:零配置,用戶無需做其他的配置,開箱即用;適合簡單的應用,并且可以快速的運行起來;
3、Rollup:用標準化的格式來編寫代碼(ES6)通過減少無用的代碼來縮小包的體積;一般只能用來打包 JavaScript;適合一些類庫并且只需要引入很少的第三方庫;(Vue,React 框架)
4、Vite:基于 esmodule 構建,可以按需編譯,熱模塊更新;可以和 Vue3 完美結合;
二、webpack 學習起步
1、安裝
安裝 webpack 之前需要確保已經安裝了 node.js 的最新版本(參考:node版本升級);然后使用 npm 包管理工具來安裝 webpack:
1、全局安裝
//全局安裝webpack webpack-clinpm install webpack webpack-cli --global
//查看webpack是否安裝成功webpack -v
不建議使用全局安裝 webpack,那樣不利于不同項目中使用不同版本的 webpack,也不利于項目的協調開發;
2、本地項目安裝
//安裝npm包管理配置文件package.jsonnpm init -y//局部安裝webpack webpack-clinpm install webpack webpack-cli --save-dev
本地項目安裝之前需要閑創建一個 npm 包管理配置文件;安裝好 webpack 之后本地目錄中會生成 node_modules 文件夾,里面就我們引入的依賴包;(切記,文件名不可以是webpack)
webpack-cli 不是必須的,只是用來處理命令行參數的工具;
2、運行打包
1、如果是在全局安裝的 webpack 直接在控制臺執行 webpack
就可以開始打包了;
webpack
2、如果是局部安裝的 webpack,上面的運行命令就不行了,因為局部安裝的并沒有加入到系統環境變量中,所以控制臺找不到 webpack
指令;這個時候我們需要使用下面的命令來運行;
npx webpack
npx 依托于 npm ,有了 npm 就可以直接使用 npx;npx 的作用是表示我們可以觀察當前文件夾里面是否有我們想要去運行的命令,如果沒有就會在這個目錄的上一層目錄中查找;
注意:運行打包可以在任意文件夾下面運行,運行之后生成的 dist 文件夾會在運行打包的文件夾下面;
3、自定義 webpack 配置
在根目錄下創建 webpack.config.js 文件,用來配置 webpack 的配置項;
const path = require('path')module.exports = {
entry:'./src/index.js', //入口文件路徑
output:{
filename:'bundle.js',//打包后的文件名
path: path.resolve(__dirname,'./dist'),//打包后文件放置的位置
clean:true //每次打包前清空dist文件夾}}
為了獲取絕對路徑,我們需要引入 node.js 的 path 模塊;通過 resolve 來解析路徑,_dirname (兩個下劃線)表示當前文件的物理路徑,也就是 webpack.config.js 文件的上一級文件夾;第二個參數是指定打包文件保存的文件夾;
打包之后的 bundle.js 在 html 文件中通過標簽引入就可以正常使用了;
4、自動引入資源
我們可以使用 webpack 插件 HtmlWebpackPlugin
來自動引入打包后的文件,這也就可以避免手動修改文件的路徑; HtmlWebpackPlugin
插件會為你生成一個新的 HTML 文件在 dist 文件夾下,并且自動引入打包后的入口文件(script 標簽),以及 CSS( head中的標簽內);
1、安裝插件
npm install --save-dev html-webpack-plugin
2、配置
在 webpack.config.js 文件中加新的配置:
const path = require('path')var HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {
entry:'./src/index.js',
output:{
filename:'bundle.js',//打包后的文件名
path: path.resolve(__dirname,'./dist'),//打包后文件放置的位置
clean:true //每次打包前清空dist文件夾},
plugins:[new HtmlWebpackPlugin({
tempalte:'./index.html',// 模板,根據指定模板生成新的html
filename:'app.html',//生成文件的名稱
inject:'body'//指定script標簽位置})]}
這樣 dist 文件夾中就會生成 bundle.js 的同時還會生成一個 app.html 文件,這個 app.html 文件就是根據 index.html 文件為模板生成的,并且文件自動引入 bundle.js ;
5、mode 選項
為了能在每次修改之后能夠自動編譯,并且讓瀏覽器自動刷新,我們可以搭建一個開發環境來實現;
1、source map 實現代碼調試
在 webpack.config.js 添加下面配置項,實現精準定位 bug 行數;
devtool:'inline-source-map'
2、自動編譯
在初次編譯的時候在命令行后面加一個 watch,這也內容修改后控制臺就會自動編譯了;
npx webpack --watch
3、webpack-dev-server
webpack-dev-server
提供了一個基本的 web server 并且具有實時重新加載的功能;
安裝
npm install webpack-dev-server -D
配置
devServer:{
statis:"./dist" //server根目錄}
啟動
npx webpack server//或者npx webpack-dev-server//自動打開瀏覽器npx webpack-dev-server --open
這里可以啟動一個服務,一般是 http://localhost:8080/,然后在瀏覽器訪問這個地址就可以實現自動更新瀏覽器了;
webpack-dev-server 實際上并沒有輸出任何的物理文件,它把打包后的 bundle 文件保存在內存里面,這也我們的開發效率提高了,webpack 的編譯效率也提高了;
6、資源模塊 module
在 webpack 出現之前,前端人員會使用 Grunt 、Gulp 等工具來處理資源,將 src 文件夾的文件移動到 dist 或者 build 目錄中;然而 webpack 最出色的功能除了引入 js 還可以使用內置的資源模塊;asset modules 來引入任何的其他類型資源,它允許 webpack 打包其他的文件(字體、圖標);
資源模塊有四種類型:asset modules type
asset/resource:發送一個單獨的文件并導出URL;
asset/inline:導出一個資源的 Data URL;
asset/source:導出資源的源代碼;
asset:導出一個資源的 Data URL 和發送一個單獨文件之間自動選擇;
6.1、resource 資源
在 webpack.config.js 新增 module 配置項;添加 rules 規則,通過 test 加上正則匹配指定類型的文件;
module:{
rules:[{//規則
test:/\.png$/, //正則定義加載文件的類型
type:'asset/resource'}]}//頁面使用import imgSrc from './assets/test.png'
這個時候在頁面上引用的時候就會獲取到圖片的路徑;并且在 dist 文件夾下面可以看到我們導出的圖片資源;
如果想修改圖片存放位置和文件名可以進行如下操作:
output:{
filename:'bundle.js',//打包后的文件名
path: path.resolve(__dirname,'./dist'),//打包后文件放置的位置
clean:true, //每次打包前清空dist文件夾
assetModuleFilename:'images/[contenthash][ext]' //contenthash 根據文件的內容生成一個hash字符串,ext表示擴展名},
或者在 module 中加一個 generator
module:{
rules:[{//規則
test:/\.png$/, //正則定義加載文件的類型
type:'asset/resource',
generator:{
filename:'images/[contenthash][ext]'}}]}
注意:如果兩處同時設置了,那么 generator 的優先級會更高;
6.2、inline 資源
在 dist 文件夾下面是看不到圖片資源的,因為這種模式只導出了資源的 URL;這個 URL 是 base64 格式的資源路徑;
6.3、source 資源
可以獲取文本的內容,常用來獲取 txt 文件的內容;
6.4、通用資源類型 asset
在 inline 和 resource 之間自由選擇,默認情況下小于 8kb 的文件將會視為 inline 模塊類型,否則視為 resource 模塊類型;也可以通過設置 parser.dataUrlCondition.maxSize
來修改默認文件大小;
module:{
rules:[{//規則
test:/\.png$/, //正則定義加載文件的類型
type:'asset',
parser:{//自定義解析器里面的時間
dataUrlCondition:{
maxSize:4*1024*1024}},
generator:{
filename:'images/[contenthash][ext]'}}]}
7、loader
webpack 除了可以使用資源模塊來引入外部資源,還可以使用 loader 來引入其他類型的文件;webpack 只能理解 js 和 json 類型的文件,這是 webpack 自帶的能力, loader 可以讓 webpack 去解析其他類型的文件并且將這些文件轉化為有效的模塊,供應用程序使用;
loader 的定義在 module rules 下面定義一個 test 來識別那些文件被轉換,use 屬性定義在轉化的時候使用那個 loader 來進行轉化;
module:{
rules:[{
test:/\.text/,
use:'raw-loader'}]}
上面這段配置的意思是:webpack 在通過 import、require 去解析一個 .test 文件的時候,在對文件進行打包之前先使用 row-loader 轉化一下;
7.1、加載 css
1、處理 css
安裝 css-loader style-loader
//將css識別轉化,讓webpack可識別npm i css-loader -D//把css放置到頁面 header 標簽里面npm i style-loader -D
安裝成功之后在 webpack.config.js 文件的 module 下新增 rules :
rules:[{
test:/\.css$/,
use:['style-loader','css-loader']}]
多個 loader 可以在 use 里面以數組的形成傳入,loader 執行順序從 use 數組的后面往前面執行,先執行的 loader 會將結果返回傳遞給下一個 loader;并且這個先后執行順序必須正確,否則不生效;需要先轉化 css ,然后將 css 放到頁面上面;
2、處理 less
安裝 less-loader
npm i less-loader less -D
安裝成功之后在 webpack.config.js 文件的 module 下新增 rules :
rules:[{
test:/\.(css|less)$/,
use:['style-loader','css-loader','less-loader']}]
7.2、抽離和壓縮 css
1、抽離
上面我們通過 loader 將 css 放到了 HTML 中,下面我們看一下將 css 單獨放在一個文件中,然后通過 link 標簽去加載;
安裝插件 mini-css-extract-plugin
//webpack5 下才有這個插件npm i mini-css-extract-plugin -D
在 webpack.config.js 引入插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')//插件使用plugins:{new MiniCssExtractPlugin({
filename:'styles/[contenthash].css' //制定打包后的css存放位置})},module:{
rules:[{
test:/\.(css|less)$/,
use:['MiniCssExtractPlugin.loader','css-loader','less-loader']}]}
使用插件的 loader MiniCssExtractPlugin.loader
替換掉 style-loader
,這也 dist 文件夾會新增一個 styles 文件夾 ,打包后的 css 就會放在這個文件夾內,并且在 dist/index.html
文件內自動引入;
2、壓縮
安裝插件 css-minimizer-webpack-plugin
npm i css-minimizer-webpack-plugin -D
在 webpack.config.js 引入插件:
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')//這個插件不是在plugins中,而是在優化配置中做設置mode:'production',optimization:{
minimizer:[new CssMinimizerPlugin()]}
注意:這個時候的 mode 必須是 production;
7.3、加載 fonts 字體
可以直接借助 asset module 來接收和載入任何類型的資源;
module:{
rules:[{
test:/\.(woff|woff2|eot|ttf|otf)$/i,
type:'asset/resource'}]}
7.4、加載數據
json 是默認可以正常導入的,但是要導入 CSV、TSV 和 XML 類型的文件數據則需要 loader 來幫忙;
安裝 csv-loader xml-loader
npm i csv-loader xml-loader
安裝成功之后在 webpack.config.js 文件的 module 下新增 rules :
module:{
rules:[{
test:/\.(csv|tsv)$/i,
use:['csv-loader']},{
test:/\.xml$/i,
use:['xml-loader']}]}
然后頁面引入這些類型的文件,就可以正常訪問了,XML文件會轉化成 js 對象,CSV 文件會轉化成一個數組;
7.5、自定義 JSON 模塊 parser
通過使用自定義 parser 替換特定的 webpack loader ,將 toml、yaml、json5 文件作為 json 模塊導入;
安裝 toml yaml json5
npm i toml yaml json5 -D
安裝成功之后在 webpack.config.js 文件的 module 下新增 rules :
const toml = require('toml')const yaml= require('yaml')const json5 = require('json5')module:{
rules:[{
test:/\.toml$/i,
type:'json',
parser:{
parse: toml.parse }},{
test:/\.yaml$/i,
type:'json',
parser:{
parse: yaml.parse }},{
test:/\.json5$/i,
type:'json',
parser:{
parse: json5.parse }}]}
8、babel-loader
webpack 只能做 js 打包,但是無法轉化 js 代碼; babel-loader 的主要任務是將 ES6 轉化成低版本瀏覽器可以使用的代碼;這里需要先安裝三個包:
babel-loader:在 webpack 里面使用 babel 解析 ES6 的橋梁
@babel/core:babel 的核心模塊
@babel/parset-env:babel 預設,一組 babel 插件的集合(將很多插件安裝到一個插件里)
npm i babel-loader @babel/core @babel/parset-env -D
安裝成功之后還需要安裝 regeneratorRuntime
插件,這個是 webpack 打包生成的全局輔助函數,由 babel 生成,用于兼容 async/await 語法;
//包含regeneratorRuntime 插件運行的時候需要的內容npm i @babel/runtime -D//需要regeneratorRuntime 的地方自動require導包,然后編譯的時候需要它npm i @babel/plugin-transform-runtime -D
在 webpack.config.js 文件的 module 下新增 rules :
module:{
rules:[{
test:/\.js$/i,
exclude:/node_module/,//不打包node_module里面的js
use:{
loader: 'babel-loader',
options:{//參數
presets:['@babel/preset-env'],
plugins:[['@babel/plugin-transform-runtime']]}}}]}
9、代碼分離
代碼分離是 webpack 最主要的特性之一,可以將代碼分離到不同的 bundle 中;分離后的文件我們可以按需加載、并行加載;代碼分離可以獲取最小的 bundle ,可以控制資源加載的優先級,如果使用合理可以極大的節省加載時間;常用分離方式有三種:
9.1、配置入口節點
使用 entry 配置手動的分離代碼;這種方法的問題是如果有多個入口,那么這些多個入口共享的文件會分別在每個包里重復打包;
const path = require('path')entry:{
index:'./src/index.js',
other:'./src/other.js'},output:{
filename:'[name].bundle.js', //name可以獲取到entry里面入口的key
path:path.resolve(__dirname,'./dist'),}
多個入口,對應打包就會打包出多個出口,但是如果 index 和 other 同時使用了 lodash 包,那么在打包的時候會分別將 lodash 包加到 index 和 other 文件中;
9.2、防止重復
使用 Entry dependencies 或者 SplitChunkPlugin
去重和分離代碼,配置 dependOn option 選項,這也可以在多個模塊之間直接共享模塊;
1、 Entry dependencies
const path = require('path')entry:{
index:{import:'./src/index.js',
dependOn:'shared'},
other:{import:'./src/other.js',
dependOn:'shared'},
shared:'lodash' //配置需要共享的模塊},output:{
filename:'[name].bundle.js', //name可以獲取到entry里面入口的key
path:path.resolve(__dirname,'./dist'),}
將 lodash 模塊單獨打包在 shared 包中,讓 index 和 other 共享;
2、SplitChunkPlugin
const path = require('path')entry:{
index:'./src/index.js',
other:'./src/other.js'},output:{
filename:'[name].bundle.js', //name可以獲取到entry里面入口的key
path:path.resolve(__dirname,'./dist'),},optimization:{
splitChunks:{
chunks:'all'}}
這種方法會自動幫們做代碼分割處理;
9.3、動態導入
當涉及到動態代碼拆分時,webpack 提供了兩種方法:import()
語法實現動態導入、webpack 遺留功能 require.ensure
;這里推薦使用第一種,所以也只介紹第一種方法;
1、import
function get(){return import('lodash').then((default:_)=>{return _.join(['hello','webpack'],' ')})}get.then(res=>{
console.log(res)})
import 函數調用完成之后返回的是一個 Promise,所以可以直接使用 then 來鏈式調用;靜態導入和動態導入是可以同時工作的;
下面是動態導入的兩個比較好的應用:
9.3.1、懶加載
懶加載也叫按需加載,是優化網頁的一種方式;它主要是將代碼在一些邏輯斷點處分離開,在完成某些操作之后立即引入需要的代碼模塊;這也能加快應用程序初始加載速度,也能減輕代碼的體積;
//math.jsexport add(a,b){return a+b}//頁面使用const button = document.createElement('button')button.textContent = '+'button.addEventListener('click',()=>{import(/*webpackChunkName:'math'*/'./math.js').then({add}=>{ //注釋這一段是修改打包后文件的名稱
console.log(add(1,2))})})document.body.appendChild(button)
上面這個例子,webpack 會將 math.js 打包成一個公共文件 math.bundle.js,但是在頁面初始化的時候這個文件不回被加載,當點擊按鈕的時候才會被加載出來;
注意:我們可以在 import 引入資源的時候添加注釋來為這個文件打包的時候命名:webpackChunkName:'math'
9.3.2、預加載模塊
webpack4.6.0 以上版本增加了對預獲取和預加載的支持;在聲明 import 時,使用下面指令可以讓 webpack 輸出資源提示,來告訴瀏覽器:
prefetch:預獲取,將來某些導航下可能需要的資源
preload: 預加載,當前導航下可能需要的資源
//math.jsexport add(a,b){return a+b}//頁面使用const button = document.createElement('button')button.textContent = '+'button.addEventListener('click',()=>{import(/*webpackChunkName:'math', webpackPrefetch:true*/'./math.js').then({add}=>{ //注釋這一段是修改打包后文件的名稱
console.log(add(1,2))})})document.body.appendChild(button)
在引入注釋處加上webpackPrefetch:true
,這也在打包的時候就會將 math.bundle.js 文件放到頁面的 link 標簽里面,并且標明是 prefetch 類型的引入文件;這也瀏覽器就會在首頁內容都加載完畢之后網絡空閑的時候去加載 math.bundle.js;
preload 方法加載的效果和懶加載的差不多,都是在操作之后需要的時候才會下載對應資源;
prefetch 方法是在瀏覽器空閑的時候預先加載好可能需要的資源,與操作無關;
10、緩存
由于獲取資源比較耗費時間,瀏覽器會使用一個緩存機制,通過命中緩存以降低網絡流量,是網站加載速度更快;然而在部署新版本的時候不改變資源文件名瀏覽器可能會認為你沒有更新,就會使用緩存版本;
10.1、配置輸出文件名
output:{
filename:'[name].[contenthash].js'}
在打包時輸出文件名增加一個動態 hash 字符串,這也每次打包的文件名就不回重復了;
10.2、緩存第三方庫
將第三方庫(lodash)單獨提取到一個固定名稱的文件中,因為這些庫一般不回做修改,所以可以利用緩存機制消除請求,減少向 server 獲取資源;(目標是第三方共享文件)
optimization:{
splitChunks:{
cacheGroups:{
vendor:{
test:/[\\/]node_module[\\/]/,
name:'vendors',
chunks:'all'}}}}
這樣所有第三方的包就都被放到 vindors.bundle.js 中了;
10.3、將所有的 js 文件放到一個文件夾中
output:{
filename:'scripts/[name].[contenthash].js'}
11、拆分開發環境和生產環境的配置
11.1、公共路徑(publicPath)
我們可以使用公共路徑來指定應用程序中所有資源的基礎路徑;默認值是空字符串:“” ,webpack-dev-server 也會默認從 publicPath 為基準,使用它來決定在哪個目錄下啟用服務,來訪問 webpack 輸出的文件。
output:{
publishPath:'/' //也可以是其他路徑}
11.2、環境變量
環境變量可以消除 webpack.config.js 在開發環境和生產環境之間的差異;webpack 的命令行 npx webpack --env 參數
允許你傳入任意數量的環境變量,在 webpack.config.js 文件中可以訪問到這個變量;想要訪問環境變量 env 必須將 module.exports 轉換成一個函數;
將當前打包環境變量設置為 production:
npx webpack --env production//也可以攜帶一個 key 、valuenpx webpack --env production --env global=local
在 webpack.config.js 文件中獲取環境變量:
module.exports = (env) =>{
console.log(env)return {
mode: env.production ? 'production' : 'development'}}
結果:
{ WEBPACK_BUNDLE: true, WEBPACK_BUILD: true, production: true }//攜帶參數{
WEBPACK_BUNDLE: true,
WEBPACK_BUILD: true,
production: true,
global: 'local'}
js 壓縮
webpack 本身可以對 js 文件進行壓縮,但是如果我們配置了 css 壓縮,那么原有的 js 壓縮就會失效,這里我們看一下怎么配置 js 壓縮:
安裝插件 terser-weboack-plugin
npm i terser-weboack-plugin -D
在 webpack.config.js 文件中引入使用:
//壓縮const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')const TerserPlugin = require('terser-weboack-plugin')optimization:{
minimizer:{new CssMinimizerPlugin()new TerserPlugin()}}
上面這倆壓縮插件只會在生產環境中生效,開發環境中不會壓縮;
11.3、拆分配置文件
拆分配置文件的目的就是將生產環境和開發環境的配置文件分開,單獨配置:webpack.config.dev.js、webpack.config.prod.js ;然后統一放到配置文件夾中;
1、開發環境
//webpack.config.dev.jsmodule.exports = {
ebtry:{
index:'./src/index.js'},
output:{
filename:'scripys/[name].js',
path:path.resolve(__dirname,'../dist'),
clean:true,
assetModuleFilename:'images/[contenthash][ext]'},
mode:'development',
devtool:'inline-source-map',
devServer:{static:'./dist'},
optimization:{
splitChunks:{
cacheGroups:{
vendor:{
test:/[\\/]node_module[\\/]/,
name:'vendors',
chunks:'all'}}}}}12345678910111213141516171819202122232425262728
開發環境不需要清理服務器緩存,不需要 publicPath,mode 可以直接設置為 development,需要 devtool,不需要壓縮相關配置;
我們可以在控制臺運行這個配置:
npx webpack -c ./config/webpack.config.dev.js
由于提前設置的 output.path = path.resolve(__dirname,'../dist')
這個時候打包的 dist 文件夾會替換 config 同級的 dist 文件夾;這個 dist 就可以用于開發環境代碼的部署;
2、生產環境
//webpack.config.prod.jsconst CssMinimizerPlugin = require('css-minimizer-webpack-plugin')const TerserPlugin = require('terser-weboack-plugin')module.exports = {
ebtry:{
index:'./src/index.js'},
output:{
filename:'scripys/[name].js',
path:path.resolve(__dirname,'../dist'),
clean:true,
assetModuleFilename:'images/[contenthash][ext]',
publicPath:'/'},
mode:'production',
optimization:{
minimizer:{new CssMinimizerPlugin()new TerserPlugin()},
splitChunks:{
cacheGroups:{
vendor:{
test:/[\\/]node_module[\\/]/,
name:'vendors',
chunks:'all'}}}},
performance:{//關閉提示信息
hints:false}}12345678910111213141516171819202122232425262728293031323334
11.4、合并配置文件
由于配置文件開發環境和生產環境中有很多相同的配置,我們可以把相同配置提取到 webpack.config.common.js 文件中;然后再將配置合并:
安裝包 webpack-merge
npx i webpack-merge -D
在 config 文件夾下新增 webpack.config.js 文件:
const { merge } = require('webpack-merge')const common = require('./webpack.config.common.js')const prod= require('./webpack.config.prod.js')const dev= require('./webpack.config.dev.js')module.exports = (env) => {switch(true){case env.development:return merge(common,dev);case env.production:return merge(common,prod);}}
11.5、npm 腳本
每次打包或者啟動服務時,都需要在命令行輸入一長串的命令,這里我們配置 npm 來簡化命令行;
1、在項目中的 package.json 文件中
"scripts":{"start": "npx webpack serve -c ./config/webpak.config.js --env development"}
在配置 npm 的時候,我們可以省略 npm 或者 npx
"scripts":{"start": "webpack serve -c ./config/webpak.config.js --env development"}
2、在命令行運行
npm run start
由于改寫命令行的時候在后面傳入了環境變量,所以這個時候 start 就代表執行 development 環境的打包;
入門部分就到這里了,后面會繼續深入學習 webpack!
該文章在 2024/4/3 14:25:59 編輯過