代碼:github
一、webpack4--基本配置
這一部分通過webpack的基本配置,使用loader對圖片和樣式進行打包,從而瞭解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