程式碼:github
一、webpack4--基本配置
1.初始化配置
mkdir webpack4
cd webpack4
mkdir demo1
cd demo1
npm init -y 或 npm init
複製程式碼
目錄結構
webpack4
├── webpack4/demo1
│ └── webpack4/demo1/package.json
└── webpack4/README.md
複製程式碼
-
安裝webpack
npm install webpack --save-dev
-
安裝指定版本webapck
npm install --save-dev webpack@<version>
-
webpack 4+ 版本,還需要安裝webpack-cli
npm install webpack-cli --save-dev
-
npx webpack -v
:檢視webpack版本 -
npx webpack-cli -v
:檢視webpack-cli版本
推薦本地安裝webpack和webpack-cli 寫這篇部落格的時候webpack最新版本為:4.30.0,也是這篇學習webpack4使用的版本
在demo1目錄下新建src目錄,在src目錄下新建index.js
mkdir src
cd src
touch index.js
複製程式碼
demo1目錄結構
demo1
├── demo1/package.json
├── demo1/package-lock.json
└── demo1/src
└── demo1/src/index.js
複製程式碼
在index.js中加寫程式碼,例如:
//index.js
let demo='webpack4'
console.log(demo)
複製程式碼
webpack4可以零配置打包,webpack4會預設對src目錄下的index.js檔案打包。
現在執行npx webapck
,可以在demo1目錄下看到dist目錄,dist目錄下有一個main.js檔案,這就是打包後的檔案,開啟查詢可以看到 console.log(demo)
,說明index.js被打包到main.js中。
2.webpack4的簡單配置
在demo1
目錄下新建webpack
配置檔案webpack.config.js
配置webpack
--webpack.config.js
const path = require('path')
module.exports={
//mode development: 開發環境 production:生產環境
mode: 'development',
//entry 入口檔案配置
entry: {
index: './src/index.js'
},
//打包完成後檔案輸出位置配置
output: {
//filename 設定打包後檔案的名字
//如果不設定filename,則檔案的名字跟入口檔案路徑的屬性名一樣
filename: 'bundle.js',
//path 設定打包完成後檔案輸出路徑
path: path.resolve(__dirname,'dist')
}
}
複製程式碼
執行npx webpack
命令
npx webpack
等價於npx webpack --config webpack.config.js
當webapck
配置檔案命名為webpack.config.js
時可以省略--config *.js
,直接執行npx webpack
即可,否則執行npx webpack --config 配置檔名
。
看到dist目錄下有bundle.js
,說明webpack配置正確。
在package.json
中配置'script'
"scripts": {
"build": "webpack"
}
複製程式碼
新增"build": "webpack"
,執行npm run build
效果等價於執行npx webpack
命令。
配置webpack.config.js的modoule物件
loader的用法
file-loader
的使用
安裝
file-loader
npm i file-loader --save-dev
webpack.config.js
const path = require('path')
module.exports={
//mode development: 開發環境 production:生產環境
mode: 'development',
//entry 入口檔案配置
entry: {
index: './src/index.js'
},
//打包完成後檔案輸出位置配置
output: {
//filename 設定打包後檔案的名字
//如果不設定filename,則檔案的名字跟入口檔案路徑的屬性名一樣
filename: 'bundle.js',
//path 設定打包完成後檔案輸出路徑
path: path.resolve(__dirname,'dist')
},
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[ext]', //對打包後的圖片命名
outputPath: 'images/' //打包後圖片輸出的位置 dist\images
}
}
}
]
}
}
複製程式碼
在src目錄下新建images資料夾,存放圖片
修改index.js
//index.js
//import匯入圖片
import image from './images/11.png'
let img=new Image()
img.src=image
document.body.append(img)
複製程式碼
執行npm run build
後的目錄結構如下
demo1
├── demo1/dist
│ ├── demo1/dist/bundle.js
│ ├── demo1/dist/images
│ │ └── demo1/dist/images/11.png
│ └── demo1/dist/index.html
├── demo1/package.json
├── demo1/package-lock.json
├── demo1/src
│ ├── demo1/src/images
│ │ └── demo1/src/images/11.png
│ └── demo1/src/index.js
└── demo1/webpack.config.js
複製程式碼
在dist目錄下出現了images目錄和圖片,建立index.html,引入js檔案,在瀏覽器中開啟就可以看到圖片。
url-loader
的使用
url-loader
安裝npm i url-loader -D
url-loader
的作用跟'file-loader'的作用很類似
webpack.config.js
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]', //對打包後的圖片命名
outputPath: 'images/', //打包後圖片放的位置 dist\images
limit: 20480
//1024 == 1kb
//小於20kb時打包成base64編碼的圖片否則單獨打包成圖片
}
}
}
]
}
}
複製程式碼
limit
屬性:當圖片大小大於屬性值時打包成圖片輸出到images目錄下,否則打包成base64編碼的圖片注入bundle.js中
因為base64編碼的圖片導致打包檔案變大,所以圖片比較小時打包成base64編碼的圖片,圖片比較大時單獨打包成一張圖片。
對css
和scss
的打包
安裝相應的loader
npm i css-loader style-loader -D
npm i node-sass sass-loader -D
npm i postcss-loader -D
npm i autoprefixer -D
postcss-loader
和autoprefixer
配合使用可以在打包過程中自動新增字首
在demo1根目錄下新建postcss.config.js
,配置如下
//postcss.config.js
module.exports={
plugins: [
require('autoprefixer')
]
}
複製程式碼
在webpack.config.js檔案的`module.rules'陣列中新增配置
module:{
rules:[
{
test: /\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
//加字首 npm i autoprefixer -D
//在專案根目錄下配置postcss.config.js檔案
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
//importLoaders
//用於配置css-loader作用於@import的資源之前有多少個loader先作用於@import的資源
}
},
'postcss-loader',
'sass-loader'
]
}
]
}
複製程式碼
在demo1
的src
下新建css
資料夾,在css
資料夾下新建style.css
和index.scss
檔案。
index.scss
body{
border: 1px solid red;
width: 300px;
height: 300px;
img{
width: 100px;
height: 100px;
border-radius: 10%;
transform: translate(100px,100px);
}
}
複製程式碼
style.css
body{
border-radius: 10%;
}
複製程式碼
index.js
//index.js
import image from './images/11.png'
import './style.css'
import './index.scss'
let img=new Image()
img.src=image
document.body.append(img)
複製程式碼
執行npm run build
,在dist目錄下新建index.html,引入js檔案,在瀏覽器中開啟就可以看到效果,說明打包成功。
css模組化
css模組化,避免頁面樣式之間相互影響
在webpack.config.js
中的css-loader
新增modules: true
//webpack.config.js
module:{
rules: [
{
test: /\.css$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
modules: true
}
},
'postcss-loader'
//加字首 npm i autoprefixer -D
//在專案根目錄下配置postcss.config.js檔案
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
//importLoaders
//用於配置css-loader作用於@import的資源之前有多少個loader先作用於@import的資源
modules: true //載入css模組化打包,避免樣式檔案之間相互影響
}
},
'postcss-loader',
'sass-loader'
]
}
]
}
複製程式碼
修改index.js
.img
是類名需要在樣式檔案中提前寫好樣式
//index.js
import image from './images/11.png'
import style from './css/style.css'
// import style from './css/index.scss'
let img=new Image()
img.src=image
//style.img .img是scss檔案中寫好的類名
img.classList.add(style.img)
document.body.append(img)
複製程式碼
index.scss
body{
border: 1px solid red;
width: 300px;
height: 300px;
img{
width: 100px;
height: 100px;
border-radius: 10%;
transform: translate(100px,100px);
}
.img{
border: 10px solid royalblue;
}
}
複製程式碼
style.css
body{
border-radius: 10%;
}
body .img{
border: 10px solid yellow;
}
複製程式碼
結果
可以看到新增了一個class,類名是一串比較複雜的字串,從而避免這個樣式對別的元素產生影響。
二、進一步配置webpack4,使自己在學習webpack4的時候更方便
這一部分主要是學會使用html-webpack-plugin
和clean-webpack-plugin
外掛,主要是學會配置devServer
以及使用webpack的熱模組替換功能。
首先,在webpack4
目錄下新建demo2
資料夾將demo1
目錄下的所有東西複製到demo2
中
在上一部分我們都是手動在dist目錄下建立index.html引入js檔案檢視打包結果,這樣會很麻煩。我們可以使用html-webpack-plugin
來自動生產index.html,並且能夠自動引入打包好的檔案,直接開啟生產的html就可以看到打包結構。
1.html-webpack-plugin
的使用
安裝
npm i html-webpack-plugin -D
在webpack.config.js
中配置plugins配置項
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
module.exports={
//mode development: 開發環境 production:生產環境
mode: 'development',
//entry 入口檔案配置
entry: {
index: './src/index.js'
},
//打包完成後檔案輸出位置配置
output: {
//filename 設定打包後檔案的名字
//如果不設定filename,則檔案的名字跟入口檔案路徑的屬性名一樣
filename: 'bundle.js',
//path 設定打包完成後檔案輸出路徑
path: path.resolve(__dirname,'dist')
},
module: { },
plugins: [
new htmlWebpackPlugin({
template: './index.html'
})
]
}
複製程式碼
在demo2目錄下新建index.html作為模板
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="bundle.js"></script></body>
</html>
複製程式碼
執行npm run build
,可以看到dist目錄下自動生產index.html,並且還自動引入js檔案
2.clean-webpack-plugin
的使用
每次打包生成的dist目錄,如果改一次程式碼,都得要刪除一次dist目錄,這樣很麻煩,可以通過clean-webpack-plugin
在每次打包的前自動清空dist目錄。
安裝
npm i clean-webpack-plugin -D
在webpack.config.js
的plugins
中配置如下
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
module.exports={
//mode development: 開發環境 production:生產環境
mode: 'development',
//entry 入口檔案配置
entry: {
index: './src/index.js'
},
//打包完成後檔案輸出位置配置
output: {
//filename 設定打包後檔案的名字
//如果不設定filename,則檔案的名字跟入口檔案路徑的屬性名一樣
filename: 'bundle.js',
//path 設定打包完成後檔案輸出路徑
path: path.resolve(__dirname,'dist')
},
module: { },
plugins: [
new htmlWebpackPlugin({
template: './index.html'
}),
new cleanWebpackPlugin()
]
}
複製程式碼
執行npm run build
,可以自己測試,每次打包前都會把dist目錄下的檔案刪掉。
3.entry
和output
多入口配置
module.exports={
//mode development: 開發環境 production:生產環境
mode: 'development',
//entry 入口檔案配置
entry: {
index: './src/index.js',
main: './src/index.js'
},
//打包完成後檔案輸出位置配置
output: {
//filename 設定打包後檔案的名字
//如果不設定filename,則檔案的名字跟入口檔案路徑的屬性名一樣
// 佔位符
filename: '[name].js',
//path 設定打包完成後檔案輸出路徑
path: path.resolve(__dirname,'dist')
},
}
複製程式碼
當有多入口的時候,需要修改filename
的屬性值為'[name].js'
執行npm run build
,就會在dist目錄下生產index.js
和main.js
4.配置devtool
devtool決定原始碼與打包後的程式碼之間的對映關係,方便對程式碼進行除錯。
開發環境推薦: cheap-module-eval-source-map 生產環境推薦: cheap-module-source-map
devtool具體內容請查閱:文件:devtool
module.exports={
devtool: 'cheap-module-eval-source-map',
//開發環境推薦: cheap-module-eval-source-map
//生產環境推薦: cheap-module-source-map
}
複製程式碼
5.配置devServer
安裝
webpack-dev-server
npm i webpack-dev-server -D
在webpack.config.js中新增以下內容
module.exports={
devServer: {
contentBase: './dist',
// open: true, //自動開啟瀏覽器
// port: 8080, //預設8080
}
}
複製程式碼
修改package.json
的script
,新增 "start": "webpack-dev-server"
"scripts": {
"start": "webpack-dev-server"
},
複製程式碼
執行npm run start
後開啟瀏覽器就可以看到效果,當我們修改程式碼的時候頁面就會重新重新整理。
有時我們希望頁面只更新我們修改的那一部分就可以了,而並不是重新整理頁面,所以需要啟用webpack的熱模組替換功能。
#### 6.啟用webpack的熱模組替換功能
首先修改index.js
import './css/style.css'
var btn = document.createElement('button')
btn.innerHTML='新增'
document.body.appendChild(btn)
btn.onclick=function(){
var div=document.createElement('div')
div.innerHTML='items'
document.body.appendChild(div)
}
複製程式碼
修改style.css,刪掉index.scss
//style.css
body{
background: yellow;
}
div:nth-of-type(odd){
background: chartreuse;
font-size: 18px;
}
複製程式碼
在webpack.config.js中
引入webpack:const webpack=require('webpack')
新增內容如下:
const webpack=require('webpack')
module.exports={
plugins: [
new webpack.HotModuleReplacementPlugin() //啟用HMR
],
devServer: {
contentBase: './dist',
// open: true, //自動開啟瀏覽器
// port: 8080,
hot: true, //啟用webpack的熱模組替換功能
hotOnly: true 
//devServer.hot在沒有頁面重新整理的情況下啟用熱模組替換作為構建失敗時的後備
}
}
複製程式碼
hot:true
啟用HotModuleReplacementPlugin
(HMR)
執行npm run start
,在瀏覽器開啟以後,修改div的背景顏色,只有改變的地方才發生變化,但是頁面並沒有重新整理。
在demo2的src目錄下新建number.js
number.js
var number=function(){
var div=document.createElement('div')
div.setAttribute("id","number")
div.innerHTML=103
document.body.appendChild(div)
}
export default number
複製程式碼
修改index.js
import number from './number'
number()
複製程式碼
執行npm run start
,在瀏覽器中開啟看結果,然後在number.js中修改內容,但是頁面並沒有顯示修改後的內容
這是因為在引入js檔案的時候,熱模組替換的實現方式有點區別。
js要達到熱模組替換的效果,得要if(module.hot){}這一部分程式碼,否則就算改了程式碼,頁面不重新整理,修改的地方在頁面上頁面變化。
css樣式因為css-loader已經實現if(module.hot){}這一部分,所以不需要單獨實現這一部分。
再次修改index.js
import number from './number'
number()
if(module.hot){
module.hot.accept('./number.js',function(){
number()
document.body.removeChild(document.getElementById('number'))
})
}
複製程式碼
執行npm run start
,在瀏覽器中開啟看結果,然後在number.js中修改內容,發現頁面顯示修改後的內容
三、使用Babel處理js檔案
Babel是一個廣泛使用的轉碼器,可以將ES6程式碼轉為ES5程式碼,從而在現有環境執行。
Babel總共分為三個階段:解析(parse),轉換(transform),生成(generate)。
Babel本身不具有任何轉化功能,它把轉化的功能都分解到一個個plugin
裡面。因此當我們不配置任何外掛時,經過Babel
輸出的程式碼和輸入是相同的。
Babel外掛的使用
-
將外掛的名字增加到配置檔案中:專案根目錄下建立
.babelrc
配置檔案或是webapck.config.js
中配置,一般都是在.babelrc
中配置。 -
使用 npm install xxx 進行安裝
Babel的配置檔案是.babelrc
,存放在專案的根目錄下。使用Babel的第一步,就是配置這個檔案。
該檔案用來設定轉碼規則和外掛,基本格式如下。
{
"presets": [],
"plugins": []
}
複製程式碼
Babel簡單介紹
preset
preset(預設)就是一系列外掛的集合
@babel/preset-env
包含所有ES6轉譯為ES5的外掛集合
core-js
轉換一些內建類(Promise, Symbols等等)和靜態方法(Array.from等)。
@babel/core
是作為Babel的核心存在,Babel的核心api都在這個模組裡面。
babel-loader
babel-loader
在webpack中使用,是webpack和Babel之間的通訊橋樑
@babel/polyfill介紹
@babel/preset-env
預設只轉譯js
語法,而不轉譯新的API
,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise
等全域性物件,以及一些定義在全域性物件上的方法(比如Object.assign
)都不會轉譯。這時就必須使用@babel/polyfill
(內部整合了core-js
和regenerator
)。
使用時,在所有程式碼執行之前增加import "@babel/polyfill"
或者是在webpack.config.js
入口配置
module.exports = {
entry: ["@babel/polyfill", "./app/js"],
}
複製程式碼
因此必須把@babel/polyfill
作為dependencies
而不是devDependencies
@babel/polyfill主要有兩個缺點:
1.使用@babel/polyfill
需要做些額外配置,實現打包的時候按需引入,否則會把@babel/polyfill
全部注入程式碼中會導致打出來的包非常大。
2.@babel/polyfill
會汙染全域性變數。
Babel7
的一個重大變化就是npm package
名稱的變化,把所有babel-*
重新命名為@babel/*
,例如:
babel-polyfill
重新命名為@babel/polyfill
babel-preset-env
重新命名為@babel/preset-env
Babel在webpack中的用法
首先實現對ES6語法的轉譯
在webpack4目錄下新建demo3資料夾,將demo2目錄下的所有東西複製到demo3中
安裝babel-loader、 @babel/core、@babel/preset-env
npm i babel-loader -D
npm i @babel/core -D
npm i @babel/preset-env -D
babel-loader@8
需要安裝@babel/core7.x
版本。
在webpack.config.js配置
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
use:{
loader: 'babel-loader',
options:{
presets: [
["@babel/preset-env",{
//targets:表示編譯出的程式碼想要支援的瀏覽器版本
targets: {
chrome: "67"
}
}]
]
}
}
}
]
}
}
複製程式碼
執行npm run build
或npx webpack
就可以看到dist目錄下的打包檔案,但是隻是將ES6的語法進行轉譯,並沒有對ES6新API進行轉譯,所以我們需要配置@babel/polyfill
解決這個問題。
安裝
@babel/polyfill
npm i @babel/polyfill --save
在index.js
中引入@babel/polyfill
index.js
//index.js
import '@babel/polyfill'
let arr=[
new Promise(()=>{}),
new Promise(()=>{}),
2
]
arr.map((item)=>{
console.log(item)
})
複製程式碼
引入@babel/polyfill
前,main.js的大小為29.5KB
引入@babel/polyfill
後,main.js的大小為1MB
注意:以上對比都是在沒有targets
這個選項的情況下,因為有些瀏覽器幾乎都支援ES6,在這種情況下,@babel/preset-env
將不會對程式碼進行處理。
這是因為把@babel/polyfill
對所有API的實現都注入到打包檔案中,但是裡面很多的API我們在程式碼中並沒有用到,所以需要修改配置,按需引入對應的API。
修改webpack.config.js配置
新增"useBuiltIns": "usage"
以後,需要安裝core-js@2
,並且新增"corejs": 2
配置項,這時配置選項比較多,需要在專案根目錄下新建.babelrc
檔案,在這個檔案中配置。
.babelrc
配置如下:
-
"useBuiltIns"
屬性值為"usage"
時,會自動引入@babel/polyfill
,必須保證已經安裝了@babel/polyfill
-
"useBuiltIns"
屬性值為"usage"
時,需要新增"corejs": 2
配置項,否則報錯,需要安裝core-js
首先刪掉index.js
中的import '@babel/polyfill'
安裝
core-js
npm i --save core-js@2
或npm i --save core-js@3
{
"presets": [["@babel/preset-env",{
"useBuiltIns": "usage", //不需要把polly都打包到程式碼中,根據程式碼按需轉譯
// core-js@3和core-js@2二選一
//"corejs": 3, //npm i --save core-js@3
"corejs": 2 //npm i --save core-js@2
}]]
}
複製程式碼
修改webpack.config.js
,刪除options
物件
module.exports={
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
}
}
複製程式碼
執行npm run build
,打包後的檔案大小為165KB
但是,在開發類庫或是第三方模組時不適合使用@babel/polyfill
,所以接下來使用@babel/plugin-transform-runtime
來解決這個問題。
@babel/plugin-transform-runtime、@babel/runtime和@babel/runtime-corejs2的用法
@babel/runtime-corejs2:是一個包含Babel modular runtime helpers
和regenerator-runtime
以及core-js
的庫。
@babel/runtime:是一個包含Babel modular runtime helpers
和regenerator-runtime
的庫。
在配置項中corejs
屬性值為預設為false
,如果需要將Promise
等API
進行轉譯,則需要設定屬性值為2
時,並且安裝@babel/runtime-corejs2
安裝:
npm i @babel/plugin-transform-runtime -D
npm i --save @babel/runtime
npm i --save @babel/runtime-corejs2
修改.babelrc檔案
{
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
複製程式碼
我們把presets
配置項去掉了,然後npm run build
打包,開啟打包後的main.js
檢視,雖然把轉譯了Promise
,但是ES6新語法並沒被轉譯,例如:let
沒有被轉譯為var
。
所以還是需要配置presets
,因為"@babel/preset-env"
包含了對所有ES6語法轉譯為ES5外掛。
再次修改.babelrc檔案
{
 "presets": ["@babel/preset-env"],
"plugins": [
["@babel/plugin-transform-runtime",{
"helpers": true,
"regenerator": true,
"useESModules": false,
"corejs": 2
}]
]
}
複製程式碼
新增presets
配置項,然後npm run build
打包,開啟打包後的main.js
檢視,可以看到let
和箭頭函式都被轉譯為ES5語法了。
四、Tree Shaking
使用
首先,在webpack4目錄下新建demo4資料夾,將demo3目錄下的所有東西複製到demo4中
Tree Shaking
可以用來剔除JavaScript
中用不上的死程式碼。它依賴靜態的ES6
模組化語法,例如通過import
和export
匯入匯出。
需要注意的是要讓Tree Shaking
正常工作的前提是JavaScript
程式碼必須採用ES6
模組化語法,因為ES6
模組化語法是靜態的,這讓Webpack
可以簡單的分析出哪些export
的被import
過了。
接下來配置Webpack
讓Tree Shaking
生效
webpack4
預設保留ES6模組化語句,並沒有通過Babel將其轉換
修改.babelrc
檔案為如下:
//.babelrc
{
"presets": [["@babel/preset-env",{
"useBuiltIns": "usage",
"corejs": 2,
"modules":false //關閉 Babel 的模組轉換功能,保留原本的 ES6 模組化語法
//預設是auto,取值還可以是 amd, umd, systemjs, commonjs,auto等
}]]
}
複製程式碼
修改webapck.config.js
,新增
optimization: {
usedExports: true
}
複製程式碼
到module.exports{}
中
module.exports={
 mode: 'development',
optimization: {
//開發壞境使用tree shaking時加usedExports: true
usedExports: true 
},
}
複製程式碼
還需通過package.json
的"sideEffects"
屬性來告訴webpack哪些模組是可以忽略掉,如果沒有則設定為false
,來告知webpack,它可以安全地刪除未用到的export
。
修改package.json
{
"name": "your-project",
"sideEffects": false
}
複製程式碼
在demo4下的src新建math.js
index.js
//tree shaking import export
import {cube} from './math.js'
let component = () => {
let element = document.createElement('pre')
element.innerHTML = [
'Hello webpack!',
'2 cubed is equal to ' + cube(2)
].join('\n\n');
console.log(cube)
return element;
}
document.body.appendChild(component());
複製程式碼
math.js
export let square= (x) => {
console.log(x)
return x * x;
}
export let cube = (x) => {
console.log(x)
return x * x * x;
}
複製程式碼
執行npm run build
,然後開啟打包後的js檔案:main.js找到下面這段文字
/*!*********************!*\
!*** ./src/math.js ***!
\*********************/
/*! exports provided: square, cube */
/*! exports used: cube */
/***/
複製程式碼
從上面這段文字可以看出Tree Shaking
生效了,但是在開發環境下,並沒有把沒有用的程式碼刪掉,因為 環境下還需要對程式碼進行除錯。
我們已經找出需要刪除的“未引用程式碼(dead code)”,然而,不僅僅是要找出,還要刪除它們。為此,我們需要將mode
配置選項設定為production
,將optimization物件刪掉,修改devtool
配置選項
webpack.config.js
module.exports = {
mode: 'production',
devtool: 'cheap-module-source-map'
}
複製程式碼
執行npm run build
,檢視打包結果就可以看到沒有用的程式碼被刪掉了。
五、Develoment
和Production
不同環境的配置
在webpack4下新建demo5,將demo4下的所有檔案複製到demo5中
因為在不同的環境下,webpack的配置稍微有點區別,如果我們需要在不同的換將下切換,就得修改webpack配置,這是很麻煩而且還容易改錯,所以我們需要把配置檔案進行拆分。
在專案根目錄下新建build資料夾,然後在build資料夾中新建webpack.dev.js
、webpack.prod.js
和webpack.base.js
三個檔案
webpack.dev.js
:是開發環境
webpack.prod.js
:是生產環境
webpack.base.js
:是開發環境和生產環境都用到的配置
這幾個檔案之間的結合靠'webpack-merge'這個外掛。
安裝
npm i webpack-merge -D
webpack.dev.js
//webpack.dev.js
const webpack=require('webpack')
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const devConfig={
mode: 'development',
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin()
],
optimization: {
usedExports: true
},
devServer: {
contentBase: './dist',
// open: true, //自動開啟瀏覽器
// port: 8080,
hot: true, //啟用webpack的熱模組替換功能
//hotOnly: true 
//devServer.hot在沒有頁面重新整理的情況下啟用熱模組替換作為構建失敗時的後備
}
}
module.exports=merge(baseConfig,devConfig)
複製程式碼
webapck.prod.js
//webapck.prod.js
const merge = require('webpack-merge')
const baseConfig=require('./webpack.base')
const prodConfig={
mode: 'production',
devtool: 'cheap-module-source-map'
}
module.exports=merge(baseConfig,prodConfig)
複製程式碼
但是這兩個檔案還有大量重複的程式碼,新建webpack.base.js
//webpack.base.js
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
module.exports={
entry: {
main: './src/index.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname,'dist')
},
module: {
rules:[
{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},
{
test: /\.css$/,
use:[
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.scss$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
modules: true
}
},
'sass-loader',
'postcss-loader'
]
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
}
]
},
plugins: [
new htmlWebpackPlugin({
template: './index.html'
}),
new cleanWebpackPlugin(),
]
}
複製程式碼
修改package.json
的script
:
{
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
}
複製程式碼
開發環境:執行npm run dev
,開啟瀏覽器訪問http://localhost:8080/
就可以看到結果
生產環境:執行npm run build