什么是webpack?
官網給出的概念是:本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle。
為什么要用webpack?
為什么使用webpack,這應該和前端的發展是有關系的,因為計算機網絡的飛速發展,導致前端也在迅猛發展,最初的實踐方案已經不能滿足我們的需求,加上新的技術和新思想框架的產生,為了節省開發的成本和效率,所以webpack的產生是一個必然的結果
相比gulp、grunt、Rollup,為什么要使用webpack?
gulp和grunt的操作都是流式的,但是gulp是基於內存流,grunt是基於文件流,所以相對來說,gulp的性能要高於grunt,而且他們都是需要定義一個個任務,然后自動將一個個任務執行。,而webpack是模塊化的組織,模塊化的依賴,然后模塊化的打包,相對來說,webpack更強調模塊化開發,而那些文件合並壓縮、預處理等功能,不過是他的附帶功能。而且現在相對於前兩者,webpack的插件也更為豐富
Rollup是在webpack流行后出現的替代品,Rollup和webpack類似,但是專注於ES6模塊打包,相比webpack,Rollup功能和插件都不如webpack完善,不過Rollup在用於打包JavaScript庫時比webpack更加有又是,因為其打包的代碼更小更快。但也因為功能不完善,很多場景找不到現成的解決方案。
安裝與使用
因為現在webpack已經更新到到4.0+了,所以本篇就直接按4.0+的來講好了
創建package.json文件
也叫初始化,可以手動創建,也可以使用命令自動創建,建議是命令創建
npm init
然后自己配置文件名、版本號等信息
如果想要快捷安裝的話,使用下面的命令(-y 表示使用默認參數)
npm init -y
注意:1.package文件里面的name屬性的值如果用駝峰式命名的話,會報警告
2. 通過文件名我們就知道package.json文件是json的對象,所以語法肯定是嚴格按照json的格式,不能添加注釋,屬性和值只能用雙引號不能用單引號,不能多添加逗號
package.json文件說明:

安裝
webpack可以直接使用npm安裝,因為我們需要使用webpack這個命令,所以必須要全局安裝
npm i webpack -g
然后在項目中安裝
npm i webpack -S
注意點:webpack 4+以上的,都需要安裝webpack-cli,所以還需要安裝webpack-cli
npm i webpack-cli -S
按着上面的步驟安裝好之后,等你配置好webpack.config.js文件在終端輸入webpack時你可能會遇到下面這個問題

解決辦法:全局安裝一下webpack-cli即可
npm i webpack -g
到此安裝步驟就已經搞定了,下面教大家如何使用
使用
創建src文件夾、public文件夾和webpack.config.js文件

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>Document</title> </head> <body> <div id="app"></div> <script src="bundle.js"></script> </body> </html>
配置webpack.config.js
module.exports = { mode:'development', // 當前的開發模式 entry: __dirname + "/src/main.js",// 入口文件 output: { path: __dirname + "/dist",// 打包后的文件存放的地方 filename: "bundle.js" // 打包后輸出文件的文件名 } }
這些基礎配置完之后,我們在項目的終端輸入
webpack
就會輸出一下信息

看到這樣的信息的話,那么恭喜你,你的第一個webpack項目完成了
此時你會看到文件夾目錄下會多了一個dist文件夾
OK,上面的文件寫法我們還可以做一下改進,例如文件的文件路徑問題,我們需要寫成的是絕對路徑,node里面有自帶一個path模塊,我們可以換成下面的寫法
const path=require('path');
module.exports={
mode:'development',
// 入口文件
entry:'./src/main.js',
// 出口文件
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'public')
}
}
上面這個是單個入口文件的寫法,有單個入口的話,那肯定是有多個入口的啊,下面這段就是多個入口文件的寫法:
const path=require('path');
module.exports={
mode:'development',
// 多個入口的話,在這邊配置
entry:{
index:'./src/js/1.js',
admin:'./src/js/index.js',
},
output:{
// 出口的名字就是上面entry定義的名字,上面定義的是index和admin,打包后在dist文件夾里面的js就是index.min.js和admin.min.js
filename:'[name].js',
path:path.resolve(__dirname,'dist')
}
}
在出口文件處的filename中,就不需要寫死bundle.js這些了,直接用name變量來接收,打包出來后的文件名字來源於entry中入口文件中的定義的鍵,如上面的就是index和admin
資源管理
webpack本身只能處理javascript,如果要處理其他類型的文件的話,就需要使用loader來進行轉換。下面我就列舉了我們經常用的幾個
css-loader---->引入css文件
我們可以在src文件夾里面新建一個css文件夾,然后在里面新建一個main.css文件。在webpack中,所有的文件都是一個模塊,所以要使用這個css文件,就必須要先引入
在main.js文件中引入css文件
import './css/main.css'
然后在終端輸入webpack后發現報錯啦

這個時候呢,安裝一下css需要使用到的loader,然后在配置一下在試試
安裝
處理css需要使用到兩個loader,css-loader和style-loader
npm install --save-dev style-loader css-loader
在webpack.config.js中配置loader
module.exports={ // 當前的開發模式 // 開發模式:development,會保留我們開發時的一些必要信息 // 生產模式:production會盡力壓縮,能壓多大就壓多大 // none:什么也不干,就只是打包 mode:'development', entry:'./src/js/main.js', output:{ filename:'bundle.js', path:path.resolve(__dirname,'dist') }, // 添加的module里面的rules module:{ rules:[ { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader后執行style-loader use:[ 'style-loader', 'css-loader' ] } ] } }
說明: loader都是在module里面的rules中配置的,rules是一個數組配置規則,該規則告訴webpack符合test的文件,使用use后面的loader處理,所以該規則就是對所有的.css文件使用css-loader、style-loader
注意點:loader的執行順序是由右向左執行的,先執行css-loader后在執行style-loader
在終端輸入webpack后,提示下面的信息就是成功啦

常用的loader
| 資源 | loader名 |
| 圖片 | file-loader |
| sass | saa-loader |
| less | less-loader |
| babel | babel-loader |
| 字體 | file-loader和url-loader |
加載圖片
安裝
npm install --save-dev file-loader
配置loader
rules:[ { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader后執行style-loader use:[ 'style-loader', 'css-loader' ] }, + { + test: /\.(png|svg|jpg|gif)$/, + use: [ + 'file-loader' + ] + } + ]
加載字體
webpack.config.js中配置
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }
加載less
安裝
npm install --save-dev less-loader less
配置
{ test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }
加載sass
安裝
npm install sass-loader node-sass --save-dev
配置:
{ test: /\.scss$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }] }
加載ES6及以上版本及jsx文件
安裝:
npm install -D babel-loader @babel/core @babel/preset-env
配置:
{ test: /\.(js|jsx)$/i, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } }
總的配置集合
module:{ rules:[ // 加載css { test:/\.css$/, // webpack的loader執行順序是反的,先執行css-loader后執行style-loader use:[ 'style-loader', 'css-loader' ] }, // 加載圖片 { test: /\.(png|svg|jpg|gif)$/, use: [ 'file-loader' ] }, // 加載字體 { test: /\.(woff|woff2|eot|ttf|otf)$/, use: [ 'file-loader' ] }, // 加載less { test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] }, // 加載sass { test: /\.scss$/, use: [ "style-loader", // creates style nodes from JS strings "css-loader", // translates CSS into CommonJS "sass-loader" // compiles Sass to CSS, using Node Sass by default ] }, // 加載base64 { test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { limit: 8192 // 當圖片小於8192K之后轉為base64 } } ] }, // 加載數據 { test: /\.(csv|tsv)$/, use: [ 'csv-loader' ] }, { test: /\.xml$/, use: [ 'xml-loader' ] },
// 加載ES6以上版本 { test: /\.(js|jsx)$/i, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] }
Plugin
插件(Plugin)是用來擴展webpack功能的,webpack可以實現loader所不能實現完成的復雜功能,使用plugin豐富的自定義API以及生命周期事件,可以控制webpack打包流程的每個環節,實現webpack的自定義功能擴展
html-webpack-plugin:生成html文件
html-webpack-plugin 可以根據你設置的模板,在每次運行后生成對應的模板文件,同時所依賴的 CSS/JS 也都會被引入,如果 CSS/JS 中含有 hash 值,則
html-webpack-plugin 生成的模板文件也會引入正確版本的 CSS/JS 文件。
安裝
npm i html-webpack-plugin -D
修改配置文件
const path=require('path');
const HtmlPlugin=require('html-webpack-plugin');
module.exports = {
entry: __dirname + "/src/main.js",//已多次提及的唯一入口文件
output: {
path:path.resolve(__dirname, './dist'),//打包后的文件存放的地方
filename: "bundle.js"//打包后輸出文件的文件名
},
module:{
rules:[
// 加載css
{
test:/\.css$/,
// webpack的loader執行順序是反的,先執行css-loader后執行style-loader
use:[
'style-loader',
'css-loader'
]
},
// 加載圖片
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
// 加載字體
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
// 加載less
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
// 加載sass
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
},
// 加載base64
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
outputPath: 'images/',
limit: 8*1024 // 當圖片小於8192K之后轉為base64
}
}
]
},
// 加載數據
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
},
{
test: /\.(js|jsx)$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
plugins: [
new HtmlPlugin(),
]
}
配置完之后,你會看到在dist文件夾下面會多了一個index.html文件
如果你想打包一個固定的模板的話,你可以在實例化插件的時候添加參數配置
plugins: [ new HtmlPlugin({ template: './public/index.html' // 模板的地址 }), ]
分離css文件--MiniCssExtractPlugin
在webpack中,默認css文件是一起打包進js文件里面去的,如果你希望打包后css在單獨的文件中的話,name你就需要MiniCssExtractPlugin(ExtractTextPlugin在webpack4+版本中已經廢棄掉了,如果使用4以下的版本的話,可以自行官網查api,也是類似的寫法的)這個plugin了
安裝
npm i mini-css-extract-plugin -D
在webpack.config.js中的配置
const path=require('path');
const HtmlPlugin=require('html-webpack-plugin');
const MiniCssExtractPlugin=require('mini-css-extract-plugin');
module.exports = {
entry: __dirname + "/src/main.js",//已多次提及的唯一入口文件
output: {
path:path.resolve(__dirname, './dist'),//打包后的文件存放的地方
filename: "bundle.js"//打包后輸出文件的文件名
},
module:{
rules:[
// 加載css
{
test:/\.css$/,
// webpack的loader執行順序是反的,先執行css-loader后執行style-loader
use:[ {
loader: MiniCssExtractPlugin.loader,
},
'css-loader'
]
},
]
},
plugins: [
new HtmlPlugin({
title:'webpack test',
template:path.join(__dirname, './public/index.html')
}),
new MiniCssExtractPlugin({
filename:'[name].css',
chunkFilename:'[id].css'
})
]
}
配置完成后在終端輸入webpack,你會發現dist文件夾里面會多了一個main.css文件(前面已經在src目錄下的css文件夾中新建了main.css,並導入到了main.js中),到這,css就已經抽離出來啦
構建運行環境
我們平時開發的時候,例如gulp都會區分開發環境還是生產環境,這兩個環境下所要配置的一些參數肯定是要不一樣的,而且我們在開發環境下,並不需要打包。在這種情況下,我們要這么去區分運行環境呢?webpack提供了一個webpack-dev-server工具給我們搭建本地運行環境。有了這個插件之后,我們可以配置命令腳本快捷運行
安裝webpack-dev-server
npm i webpack-dev-server -D
然后在package.json配置中的script里面腳本命令
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server ", "dev": "webpack-dev-server ", "build": "webpack" }
通過上面的代碼,我們可以知道,在看法環境下才要運行項目環境,如果打包的時候就用build的那個命令來充當生產環境
開發環境命令使用
npm run start // 或 npm run dev
生產環境命令使用
生產環境下的話,我們需要做的是打包的工作
npm run build
了解npm 命令的話,我們應該知道,在npm的命令腳本中,我們是可以添加參數的,我們可以通過添加參數來設置一下在開發環境下自動在默認瀏覽器中打開項目

默認的端口是8080端口
修改默認端口
嗯,有些時候我們的端口可能被其他項目占用着,所以為了項目得以運行,肯定是要改一下端口的啊。我們可以在配置命令腳本的時候添加參數--port 端口號
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000", "dev": "webpack-dev-server ", "build": "webpack" },

此時的端口就已經改為了3000端口了
自動熱更新
我們每次修改完都要重啟一下運行環境,這樣的操作效率太低了,而且很浪費時間,我們要怎么做到每次修改完他都會自動更新呢,當然是有解決方法的啊,添加--hot參數即可
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000 --hot", "dev": "webpack-dev-server ", "build": "webpack" }
開發的時候區分環境更項目配置的,可以查看我的上一篇的使用webpack構建簡易的vue-cli框架的筆記(https://www.cnblogs.com/cythia/p/10672042.html)
統計編譯的時間
有時候我們在開發的時候需要做性能優化的時候,就肯定想要知道在編譯過程中哪些步驟耗時最長。這個時候我們可以使用--profile
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack-dev-server --open --port 3000 --hot --profile", "dev": "webpack-dev-server ", "build": "webpack" }

