大概准備春招兩個月了, 也沒找到坑位埋自己, 來看看webpack
webpack
官網: www.webpackjs.com
對於前端的大兄弟來說, 每天在前端摸爬滾打, 各方征戰, 那對於webpack肯定再熟悉不過了
所以說這篇文章適合給像我們這樣的后端的同胞看着玩,(一說前端不是想用BootStrap就想用其他前端框架的UI組件庫, 要不就是vue的腳手架) , 那對於浪跡各大vue react組件庫的你, 對於喜歡用腳手架構建項目的你, 對於喜歡一鍵打包項目的你, 真的了解webpack各種目錄和默認配置嗎?
webpack的核心概念:
- 入口: 從哪里開始打包
- 出口: 打包的結果輸出到哪里去
- loader: 我們通過npm給webpack安裝上不同的loader, webpack就能處理不同格式的文件, 用於處理圖片等靜態資源的loader, 處理css的loader, 處理less的loader, 用於適配各種瀏覽器的loader等等
- 插件: 作用於整個打包過程, 比如用於本件拷貝的插件, 用於生成html的插件, 用於處理css的插件
搭建一個空的項目
通過這個小案例你將了解:
- 局部安裝webpack-cli的命令是什么 ?
- 如何在新項目中使用局部安裝的webpack ?
- webpack的默認啟動目錄, 啟動文件在哪里 ? 叫什么 ?
- 什么是mode? (development production)
- 有哪些build mode , 這些mode有何區別 ?
繼續:
命令: npm init 創建一個空項目
執行完成后, 會為我們生成一個packetage.json文件
然后安裝webpack 包管理工具命令: npm i webpack-cli -D

注意點:上面的安裝命令是局部安裝命令, 如果我們進入這個項目中, 使用npm run build命令嘗試將這個項目打包時, 會報錯 說 missing script : build

解決方法: 在package.json的script部分中加入下面的配置 后, 再使用 npm run build 命令時, 會自動使用我們在局部安裝的這個命令

--mode 指定在什么環境下打包, 上面的 production 就是說打包后在生產環境下使用, 和development最直接的不同點就是 前者會將main.js 壓縮
繼續執行npm run build 命令: 會遇到新的錯誤, 說解析不到 src目錄, 原因是webpack找到不到入口目錄
默認的, webpack的入口會去找 src/index.js
我們在根目錄下將這個目錄創建出來, 再次執行npm run build 即可打包成功, 打包的結果: /dist/main.js , 會將項目中依賴的js文件, 打包成一個js文件
npm run xxx ,命令中的xxx就是上圖中的srcipt中定義的 比如npm run dev , npm run build , npm run start , npm run test
webpack的配置文件
看完這本小節你將了解:
- webpack默認的配置文件叫什么 ?
- webpack默認的配置文件在哪里 ?
- 如何修改webpack默認配置文件所在的路徑和名稱 ?
- webpack的入口js文件可以修改嗎? 如何修改 ?
- webpack的配置文件中output目錄及文件可以修改嗎? 如何修改 ?
- output輸出的目標文件默認叫什么名? 可以修改嗎?
- webpack有哪些hash函數可以使用 ?
ok, 繼續:
- 有哪些默認的配置?
webpack.config.js, 默認的webpack會去根目錄中尋找他, (如過我們把它放在自定義的目錄中, webpack是找不到它的)
但是可以在 package.json中去修改這個默認的配置, 如下: 添加--config 參數

- 能添加哪些自定義的配置?
webpack.config.js 配置文件的作用的對外暴露node.js的配置腳本, 看下圖, 可以知道, webpack.config.js中對應的就是webpack對應的各個模塊的

參照這個連接: https://www.webpackjs.com/concepts/configuration/
用大白話說, webpack.config.js 可以告訴webpack打包的mode, 是否需要壓縮, 入口js文件在哪里, 打包結果輸出到什么目錄, 輸出結果叫什么, 等等
var path = require('path');
module.exports = {
mode: 'development', // 指定打包后在什么環境下使用
entry: './src/index.js', // 指定入口js文件, todo 可以在這里修改入口js文件
output: {
path: path.resolve(__dirname, 'dist'), // 打包后的文件所在的目錄名
//filename: 'foo.bundle.js' // 打包后生成的文件名, 默認是main.js
// hash值是通過入口目錄中的入口js算出來的, 一旦js改變, 每次build的結果的hash值
//filename: '[name].[hash].js' // 生成的文件名: main.e9bsajdoahsds.js
//filename: '[name].[hash:6].js' // 生成的文件名: main.6位長度hash值.js
filename: '[name].[chunkHash:6].js' // 生成的文件名: main.6位長度hash值.js 且共存多個模塊時, 只有那個發生變動的入口js對應生成的 output文件名中的js哈希值才會改變
// 第三種hash contenthash ,是根據文件的內容計算出來的hash
}
};
- webpack的三種hash值
- hash: 它是工程級別的, 即修改工程中任何一個文件, 整個工程的文件緩存都會失效, 打包出來的文件的hash值都會發生改變, 缺點: 如果項目存在多個入口, 勢必針對每一個入口js文件都打包出來一個帶有hash值的結果文件, 雖然是兩個不同的入口, 但是屬於一個工程, 所有多個目標文件的hash值都會改變
- chunkHash: 它解決了hash的缺點帶來的不足條件, 還是同一個項目,多個入口js的情況, 使用chunkHash模式, 然后修改一個入口js的內容, 打包出來的結果文件中, 只有被修改了的那個js的hash改變;
- contentHash: 根據文件的內容計算hash
打包后自動生成html
學完本節你將了解
- 如何讓webpack打包出一個單頁index.html
- 如何讓webpack基於我們自己提供的html頁面生成 index.html
參考鏈接: https://www.npmjs.com/package/html-webpack-plugin
默認的, webpack會將項目中依賴的js文件打包稱一個js文件輸出到 / dist / 目錄中, 但是不會為我們生成html文件, 這時候我們需要手動的將生成的js文件引入到我們自己的index.html文件中, 這樣整挺麻煩的
所有, 一般我們會這么搞, 把自己的index.html文件放在/public/index.html中, 然后安裝webpack的插件, 讓這個插件替我們完成上面的那個復雜的過程, 如下
安裝命令:
npm i --save-dev html-webpack-plugin
參考: webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
// 着重看一下這個plugin模塊
plugins: [
new HtmlWebpackPlugin(), // Generates default index.html
new HtmlWebpackPlugin({ // Also generate a test.html
filename: 'test.html',
// 允許用戶自定義一個html模板, webpack會在這個模板上累加上自己生成的js
template: 'src/assets/test.html'
})
]
}
引入CSS
看完本節你將了解:
- 兩種方式讓webpack替我們導入css文件
參考鏈接: https://www.npmjs.com/package/css-loader
- 第一種方式:
安裝loader插件命令
npm i style-loader -D
npm install --save-dev css-loader
參考配置文件 : 通過一個rules來控制這個過程, 通過正則匹配到css, 然后對這些匹配到的文件使用 style-loader css-loader , 執行的順序的 后面的css-loader比style-loader先執行
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
通過如下方式將css引入

此時再執行 npm run build 可以完成構建工作
問題來了, 通過這種方式導入進來的css文件在哪里呢?
通過查看html源碼可見, 構建出來的源碼被放在head標簽中
- 第二種引入css文件的方式, 將css導入進來, 並提取成一個獨立的文件, 並自動插入到html中
參考鏈接: https://www.npmjs.com/package/mini-css-extract-plugin
安裝命令:
npm install --save-dev mini-css-extract-plugin
參考webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// 在plugins部分new出來
plugins: [
new MiniCssExtractPlugin(
{
filename: '[name].[chunkHash:8].css'
}
)],
module: {
rules: [
{
test: /\.css$/i,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
esModule: true,
},
},
'css-loader',
],
},
],
},
};
這種方式生成結果如下:

很明顯: css被添加在head標簽中, script添加在index.html末尾
小技巧, 如果想讓生成的文件呈現下面的樣子:

可以在webpack.config.js文件中, 使用下面的方式為文件命名
new MiniCssExtractPlugin(
{
filename: 'css/[name].[chunkHash:8].css'
}
)
CSS預處理
參考鏈接: https://www.npmjs.com/package/less-loader
目的是處理less, 將less轉換成css
安裝 less 和 less-loader
npm install less less-loader --save-dev
在webpack.config.js中添加less的解析規則

loader的第二種寫法
{
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
// 'less-loader',
{
loader: "less-loader",
options:{
}
}
],
}
自動添加CSS前綴
看完本節你將了解
- 啥是css3前綴
- 為啥要加前綴
- 怎么通過webpack添加前綴
**那為啥要添加前綴呢? **
因為在CSS標准未被確定之前, 市面上的不同瀏覽器使用自己私有的前綴卻分不同的CSS樣式, 當標准確定之后, 各大瀏覽器不再使用這些前綴, 目前很多私有的前綴都可以不再寫了, 但是為了兼容, 可以仍然使用前綴逐漸過度
常見的瀏覽器的前綴如:
- Chrome谷歌瀏覽器: -webkit-
- Safari蘋果瀏覽器: -webkit-
- FireFox 火狐: -moz-
- IE: -ms-
- Opera 歐朋瀏覽器: -O-
例:
#example{
-webkit-outline: none;
-moz-outline: none;
-ms-outline: none;
-o-outline: none;
-khtml-outline: none;
outline: none;
}
如何配置webpack, 自動添加瀏覽器css3前綴
參考鏈接: https://www.npmjs.com/package/autoprefixer
安裝命令:
npm i postcss-loader autoprefixer -D
第二步: 在項目的根目錄下創建 postcss.config.js 配置文件
postcss的npm包參考鏈接: https://www.npmjs.com/package/postcss
module.exports = {
plugins: [
// 他需要下面的插件 autoprefixer
require('autoprefixer'),
]
}
第三步: 在webpack.config.js配置文件中添加指定的postcss-loader, 注意把他的添加順序, 放在靠前的位置

第四步: 在package.json配置文件中添加 browerslist相關配置, 可以針對不同瀏覽器做出更詳細的配置
參考鏈接: https://www.npmjs.com/package/browserslist
實例:
"browserslist": [
"defaults",
"not IE 11",
"not IE_Mob 11",
"maintained node versions",
]
並不是瀏覽器包含的越多越好, 比如說想用ES5的話, IE的版本至少要大於等於8
處理資源文件
看完本節, 你將了解:
- 三種處理資源文件的方式
- 第一種處理方式 file-loader
使用file-loader處理資源文件, 參考鏈接 <https://www.npmjs.com/package/file-loader >
安裝命令:
npm install file-loader --save-dev
參照上面鏈接中的示例配置, 為webpack.config.js中添加file-loader相關的模塊
示例:
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options:{
// 指定webpack打包后, 輸出的路徑
name: 'static/images/[name].[ext]',
// 這個publicPath規定的路徑, 就是webpack運行項目后, 所有的資源文件url的最前面的公共部分
publicPath: '/',
}
},
],
}
]
注意點: 如果不添加publicPath的話, 將出現下面的問題

- 第二種處理方式
參考鏈接: https://www.npmjs.com/package/url-loader
url-loader的優點, 會針對不同圖片做不同的壓縮
安裝命令
npm install url-loader --save-dev
同樣是在webpack.config.js中添加配置
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
// url-loader和file-loader的工作原理相似, 當資源的大小小於limit指定的值時, 資源將被替換成base64編碼的數據植入html或者 css中
limit: 80,
name: 'static/images/[name].[ext]',
// 這個publicPath規定的路徑, 就是webpack運行項目后, 所有的資源文件url的最前面的公共部分
publicPath: '/',
},
},
],
}
url-loader的特點如下:
- 當資源size < limit值時, 將使用base64對資源進行加密處理
- 當資源size > limit值時, 和file-loader相似, 將圖片本身輸出到指定的目錄中
- 第三種處理方式
比如項目中引用了字體文件, 直接寫死在index.html模板中, 而不需要使用file-loader或者url-loader進行壓縮之類webpack的處理和生成的操作, 那么可以使用下面的插件, 直接進行文件的copy
參考鏈接: https://www.npmjs.com/package/copy-webpack-plugin
命令:
npm install url-loader --save-dev
參考webpack.config.js如下:
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyPlugin([
{ // 將項目根路徑下的static目錄中的內容, 拷貝到dist/static/images中
from: path.resolve(process.cwd(),'static/'),
to: path.resolve(process.cwd(),'dist/static/images中')
},
]),
],
};
添加Babel-loader
為什么要使用babel-loader?
我們都是到, 瀏覽器只認識html css 原生js , 后續js發展的很快, ES5 ES6出世了, 但是不少瀏覽器根本不支持ES6的語法, 比如 import export 對象/函數 等等
如何使用?
參考鏈接: https://www.npmjs.com/package/babel-loader
安裝命令:
npm install -D babel-loader @babel/core @babel/preset-env webpack
示例:
rules: [
// the 'transform-runtime' plugin tells Babel to
// require the runtime instead of inlining it.
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
}
}
}
]
webpack讓前端項目獨立占用一個端口運行
通過這小節你將知道:
- webpack 通過什么讓前端項目獨立運行
- 如何安裝這個插件
- 如何配置進webpack, 讓webpack使用它
- 在那個配置文件中對devs-server進行更多的配置
參考連接: https://www.npmjs.com/package/webpack-dev-server
安裝命令:
npm install webpack-dev-server --save-dev
修改npm的配置文件, 添加dev選項

這也就是為啥, 通過腳手架構建的開發環境, 能npm run dev 運行起來
並且, 項目運行起來后, 我們做出的任何修改, 都會熱加載進來, 時時更新, 無須重啟
在webpack.config.js中添加devServer模塊
如:

一般在開發時. 這個配置肯定是需要定制的, 如果在這里模擬前后端聯調, 就在這個模塊配置mock數據的地址
devServer: {
change xxx-api/login => mock/login
detail: https://cli.vuejs.org/config/#devserver-proxy
},
或者是真的在前后端聯調, 因為端口不同將出現跨域, 在這里配置代理服務器的地址
// 參考: https://www.webpackjs.com/configuration/dev-server/#devserver-proxy
devServer: {
proxy: 'http://localhost:8089'
},
比如, 自動打開啊等等, 更多的配置 參考鏈接 https://www.webpackjs.com/configuration/dev-server/
