習慣用腳手架的你, 瞭解Webpack這些知識點嗎?
大概準備春招兩個月了, 也沒找到坑位埋自己, 來看看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/