柚子快報(bào)邀請(qǐng)碼778899分享:前端 webpack常用配置
柚子快報(bào)邀請(qǐng)碼778899分享:前端 webpack常用配置
1.webpack概念
? 本質(zhì)上,webpack 是一個(gè)用于現(xiàn)代 JavaScript 應(yīng)用程序的 靜態(tài)模塊打包工具。當(dāng) webpack 處理應(yīng)用程序時(shí),它會(huì)在內(nèi)部從一個(gè)或多個(gè)入口點(diǎn)構(gòu)建一個(gè) 依賴圖(dependency graph),然后將你項(xiàng)目中所需的每一個(gè)模塊組合成一個(gè)或多個(gè) bundles,它們均為靜態(tài)資源,用于展示你的內(nèi)容。
2.webpack安裝
1.webpack的依賴于node環(huán)境的,所以電腦必須有Node環(huán)境。
沒(méi)有node環(huán)境,請(qǐng)參考node官網(wǎng)
node -v 查看
npm -v 查看
2.安裝webpack之前需要先安裝一個(gè)npm的包管理的配置文件
npm init -y
3.安裝webpack和webpack-cli
npm i webpack webpack-cli -d (局部)
npm i webpack webpack-cli -g (全局,不推薦)
3.webpack常用置項(xiàng)的作用
1)五個(gè)核心概念
Entry:入口起點(diǎn)(entry point)指示 webpack 應(yīng)該使用哪個(gè)模塊,來(lái)作為構(gòu)建其內(nèi)部依賴圖的開始。Output:output 屬性告訴 webpack 在哪里輸出它所創(chuàng)建的 bundles,以及如何命名這些文件,默認(rèn)值為 ./dist。Loader:loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只能解析 JavaScript)。Plugins:插件則可以用于執(zhí)行范圍更廣的任務(wù)。插件的范圍包括,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量等。Mode:模式,有生產(chǎn)模式production和開發(fā)模式development
4.webpack小demo
步驟1:
根目錄新建webpack.config.js文件
//獲取當(dāng)前的目錄
const {resolve} = require('path');//node用法
module.exports ={
//入口配置項(xiàng)
entry:'./index.js',
//出口項(xiàng)配置
output:{
filename:'built.js',
path:resolve(__dirname,'build')
},
//設(shè)置為開發(fā)環(huán)境
mode:'development',
}
根目錄新建index.js文件運(yùn)行webpack之后,根目錄出現(xiàn)build文件夾
步驟2:
安裝typescript環(huán)境npm i typescript -g,然后tsc -v查看版本號(hào),并初始化typescript環(huán)境tsc --init 將index.js文件改成index.ts并在根目錄新建src文件里components文件夾新建一個(gè)組件并在index.ts文件引入并使用。 運(yùn)行webpack之后報(bào)錯(cuò),因?yàn)槲覀儧](méi)有指定好模塊的解析方式,我們需要跟著官網(wǎng)文檔使用resolve.extensions。webpack.config.js文件追加了
extensions: [‘.ts’, ‘…’]也可以,保留的默認(rèn)的擴(kuò)展
resolve: {
extensions: ['.js', '.ts'],
},
根目錄新建public文件創(chuàng)建index.html文件npm i html-webpack-plugin并在webpack.config.js文件使用后
作用:1.自動(dòng)在內(nèi)存中根據(jù)指定頁(yè)面生成一個(gè)內(nèi)存的頁(yè)面 2.自動(dòng)把打包好的bundle.js追加到頁(yè)面中去
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
}),
],
步驟3: 配置webpack what5 + ts + react
npm i react react-dom @types/react @types/react-dom @babel/preset-react 安裝依賴
react:react核心依賴typescript:支持 tsreact-dom:負(fù)責(zé)處理web端的dom的渲染@types/react :react 類型聲明文件,用于 tsx@types/react-dom:react-dom 類型聲明文件,用于 tsx@babel/preset-react :用于讓 babel 可以轉(zhuǎn)譯 jsx 語(yǔ)法@babel/preset-typescript:處理ts文件,原理是去掉ts的類型聲明,然后再用其他 babel 插件進(jìn)行編譯@babel/plugin-proposal-decorators 和@babel/plugin-proposal-class-properties:支持并編譯decorator語(yǔ)法, 需要在tsconfig.ts中進(jìn)行如下設(shè)置"experimentalDecorators": true 入口文件改成.tsx結(jié)尾的
import React from 'react'
import ReactDom from 'react-dom'
ReactDom.render(
//這里react腳手架中引入的時(shí)app.js組件,這里直接寫死了
Hello React
,document.getElementById("root")
)
在tsconfig.json里面增加對(duì)tsx文件的支持"jsx": "react"運(yùn)行webpack之后報(bào)錯(cuò),要處理.tsx格式的執(zhí)行,因?yàn)闉g覽器只能識(shí)別js文件,需要執(zhí)行npm i ts-loader之后webpack.config.js增加module配置,修改resolve配置
module:{
rules:[
{
test: /\.(js?|ts?|tsx?|jsx?)$/,
use: [
{
loader: 'babel-loader',
options: {
// 開啟babel的緩存
cacheDirectory: true,
presets: [
[
'@babel/preset-env',
{
// useBuiltIns: usage 會(huì)根據(jù)配置的瀏覽器兼容,實(shí)現(xiàn)了按需添加
useBuiltIns: 'usage',
corejs: 3,
// 不以commonjs打包,方便tree-shaking
modules: false,
},
],
'@babel/preset-react',
'@babel/preset-typescript',
],
plugins: [
['@babel/plugin-proposal-decorators', { legacy: true }],
['@babel/plugin-proposal-class-properties'],
],
},
},
],
},
]
},
resolve:{
extensions:['.ts','.tsx','...']
},
步驟4:基本配置
根目錄新建 1).gitignore文件——總會(huì)有些文件無(wú)需納入git的管理,也不希望它們出現(xiàn)在未跟蹤文件列表,想忽略文件的作用
node_modules
**/node_modules
.DS_Store
doc/userName.md
/dist
? 2)public文件夾存放項(xiàng)目的靜態(tài)資源
? 3)build文件夾存放webpack的配置文件
? 4)src存放項(xiàng)目項(xiàng)目的代碼文件
在build文件里面新增三個(gè)文件webpack.common.js、webpack.dev.js、webpack.prod.js用于區(qū)分環(huán)境的配置,兩個(gè)環(huán)境有夠公共部分使用第三方工具webpack-merge將公共配置導(dǎo)入對(duì)應(yīng)文件中,功能類似于 JavaScript 的 Object.assign()。 // build/webpack.prod.js
const { merge } = require('webpack-merge')
const path = require('path')
const common = require('./webpack.common')
const { PROJECT_PATH } = require('../constant')
module.exports = merge(common, {
mode: 'production',
devtool: false,
output: {
filename: 'js/[name].[contenthash:8].js',
path: path.resolve(PROJECT_PATH, './dist')
},
})
// build/webpack.dev.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { merge } = require("webpack-merge");
const baseConfig = require("./webpack.common.js");
//獲取當(dāng)前的目錄
const { resolve } = require("path"); //node用法
const PROJECT_PATH = resolve(__dirname, "../"); // 項(xiàng)目根路徑
module.exports = merge(baseConfig, {
mode: "development",
output: {
filename: "js/[name].js",
path: resolve(__dirname, "dist"),
},
module: {
rules: [{ test: /\.tsx$/, use: ["ts-loader"], exclude: /node_modules/ }],
},
});
哈希值區(qū)別 hash: ? 每次修改任何一個(gè)文件,所有文件名的hash至都將改變,所以一旦修改了任何一個(gè)文件,整個(gè)項(xiàng)目的文件緩存都將失效 chunkHash: ? 根據(jù)chunk生成的hash值,如果打包來(lái)源于同一個(gè)chunk,那么hash值就一樣,chunkHash不適用于同一chunk的文件,如一個(gè)js文件導(dǎo)入了一個(gè)css文件,他們屬于同一個(gè)chunk,因此若只修改了js,最終打包出來(lái)的文件cs和js都會(huì)變成一個(gè)新的hash contenthash: ? 根據(jù)文件內(nèi)容生成hash值,不同文件的hash值一定不一樣(只要文件內(nèi)容不做修改,一定是同一個(gè)hash,有變動(dòng)則會(huì)替換成另外的),這樣就令瀏覽器只清楚掉變動(dòng)文件的緩存(只有改動(dòng)的文件重命名了) npm i cross-env配置統(tǒng)一的Node環(huán)境變量
在node中,全局變量 process 表示的是當(dāng)前的node進(jìn)程,process.env 包含著關(guān)于系統(tǒng)環(huán)境的信息。
使用 process.env.NODE_ENV獲取當(dāng)前環(huán)境
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server -- config build/webpack.dev.js",
"build": "cross-env NODE_ENV=production webpack -- config build/webpack.prod.js",
}
npm i webpack-dev-server提供本地服務(wù)參考鏈接
devServer的配置功能如下: historyApiFallback: 使用HTML5 History API時(shí),index.html可能需要提供頁(yè)面來(lái)代替任何404響應(yīng) static: 該配置項(xiàng)允許配置從目錄提供靜態(tài)文件的選項(xiàng)(默認(rèn)是 ‘public’ 文件夾) client: 允許在瀏覽器中設(shè)置日志級(jí)別, proxy: 當(dāng)擁有單獨(dú)的 API 后端開發(fā)服務(wù)器并且希望在同一域上發(fā)送 API 請(qǐng)求時(shí),代理某些 URL 可能會(huì)很有用。 host:服務(wù)ip port:服務(wù)端口 stats:設(shè)為errors-only表示終端只打印錯(cuò)誤類型的日志,不會(huì)打印warning以及其他信息影響閱讀 compress:設(shè)為true表示啟用gzip壓縮,加快網(wǎng)站打開速度 open:設(shè)為true表示第一次啟動(dòng)項(xiàng)目時(shí)自動(dòng)打開默認(rèn)瀏覽器 hot:設(shè)為true表示啟用服務(wù)熱替換配置 clientLogLevel:設(shè)為none表示去除多余網(wǎng)頁(yè)console信息 … // build/webpack.dev.js
devServer: {
historyApiFallback: true,
// noInfo: true,
static: [
{
directory: path.join(__dirname, '../public'),
// serveIndex: {} (options for the `serveIndex` option you can find https://github.com/expressjs/serve-index)
// serveIndex: true,
},
],
client: {
overlay: {
errors: true,
warnings: false,
},
logging: 'error',
progress: true,
reconnect: 3,
},
hot: true,
compress: true,
// open: true, //在mac上為true才會(huì)打開瀏覽器,故在node啟動(dòng)文件又添加了open
open: {
app: {
name: 'google-chrome',
arguments: ['--new-window'],
},
},
proxy: {
'/': {
},
},
},
為了實(shí)現(xiàn)js的熱替換,此時(shí)需要在入口文件的執(zhí)行代碼最開始處配置一下 module.hot.accept 邏輯
ts報(bào)錯(cuò)安裝第三方插件解決 npm i @types/webpack-env:包含 webpack 的 api 聲明文件 // index.tsx
if (module && module?.hot) {
module?.hot.accept();
}
進(jìn)度條npm i webpackbar展示 // build/webpack.common.js
const WebpackBar = require('webpackbar')
module.exports = {
plugins: [
new WebpackBar({
name: 'Link Startou!!!',
color: '#52c41a'
}),
]
}
分別運(yùn)行npm run dev和npm run build查看效果
步驟5:
配置css——webpack支持原生js和html打包,需要下載第三方包并配置
npm i style-loader:將 js 文件中引入的 css 代碼插入到 html 模板文件,使網(wǎng)頁(yè)可以正常展示樣式 npm i mini-css-extract-plugin:和 style-loader 功能一樣,只是打包后會(huì)單獨(dú)生成 css 文件而非直接寫在 html 文件中,用于生產(chǎn)環(huán)境,開發(fā)環(huán)境不需要另外生成文件使用 style-loader 即可 npm i css-loader:令 js 可以通過(guò) import 或者 require 等命令導(dǎo)入 css 代碼
modules:開啟 css module,看個(gè)人習(xí)慣,如果不使用可以直接置值 false,否則影響打包速度,localIdentName 表示自定義類名,為了確保類名全局統(tǒng)一加上哈希值sourceMap:為 true 時(shí)會(huì)根據(jù) devtool 映射css錯(cuò)誤,生產(chǎn)環(huán)境不需要映射所有這里給的值是開發(fā)環(huán)境 壓縮優(yōu)化css
npm i css-minimizer-webpack-plugin壓縮生產(chǎn)環(huán)境打包后的css文件
optimization:在 webpack4 之后添加了 optimization 屬性,專門用于存放優(yōu)化打包的配置,minimizer屬性存放一個(gè)數(shù)組,里可以存放用于代碼壓縮的插件,minimize 置 true 表示啟用 minimizer 配置 瀏覽器兼容問(wèn)題
npm i postcss-loader:與 sass/less 不同,不是預(yù)處理器,相當(dāng)于一個(gè)工具箱,可以使用它配合插件去轉(zhuǎn)換css npm i postcss-preset-env:將最新的 css 語(yǔ)法轉(zhuǎn)換為目標(biāo)環(huán)境的瀏覽器能夠理解的語(yǔ)法,不用考慮瀏覽器兼容問(wèn)題,以前需要配合 autoprefixer 第三方包自動(dòng)補(bǔ)全前綴,現(xiàn)在新版本已經(jīng)內(nèi)置autoprefixer功能 處理css的時(shí)候需要添加瀏覽器前綴插件的選擇結(jié)合上面代碼autoprefixer可為css添加瀏覽器前綴 1)根目錄新建.browserslistrc文件或者在package.json配置browserslist屬性 ? 2)配置 browserslist 字段會(huì)導(dǎo)致 webpack-dev-server 的熱更新功能直接失效,為了避免這種情況需要給 webpack 配上 target 屬性——webpack.dev.js中增加 target: ‘web’,webpack.prod.js中增加 target: ‘browserslist’
// package.json文件
{
"browserslist": [ //注意是一個(gè)數(shù)組
"last 1 version",
"> 1%",
"maintained node versions"
]
}
//.browserslistrc文件
last 2 versions # 所有瀏覽器兼容到最后兩個(gè)版本根據(jù)CanIUse.com追蹤的版本
> 2% # 全球超過(guò)0.5%人使用的瀏覽器,可以通過(guò) caniuse.com 查看不同瀏覽器不同版本占有率
// build/webpack.prod.js
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = merge(common, {
// ...other
optimization: {
minimize: true,
minimizer:[
new CssMinimizerPlugin()
]
}
})
// build/webpack.common.js
const getCssLoaders = () => {
const isDevelopment = process.env.NODE_ENV === 'development'
const isProduction = process.env.NODE_ENV === 'production'
const cssLoaders = [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
modules: {
localIdentName: "[local]--[hash:base64:5]"
},
sourceMap: isDevelopment,
}
}
]
// 開發(fā)環(huán)境一般用chrom不會(huì)有問(wèn)題,防止開發(fā)環(huán)境下看樣式有一堆前綴影響查看,因此只在生產(chǎn)環(huán)境使用
isProduction && cssLoaders.push({
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
isProduction && [
'postcss-preset-env',
{
//開啟自動(dòng)添加前綴功能,有些功能是默認(rèn)關(guān)閉的,如柵格樣式一些瀏覽器不支持所以默認(rèn)關(guān)閉了,這里手動(dòng)打開
autoprefixer: {
grid: true
}
}
]
]
}
}
})
return cssLoaders
}
module: {
rules: [
{
test: /\.css$/,
use: [...getCssLoaders()]
},
}
預(yù)處理器
npm i less-loader將less文件編譯成css文件,再做上述css文件的打包工作。npm i less
// build/webpack.common.js
module: {
rules: [
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
},
}
打包圖片資源及打包img標(biāo)簽中的圖片
方法1:npm i url-loader npm i file-loader 處理打包圖片資源 module: {
rules: [
{
test: /\.(png|jpe?g|gif|webp)$/,
// 要使用一個(gè)loader
// 下載 url-loader file-loader
dependency: { not: ['url'] },
use:[
{ loader: 'url-loader',
options: {
// 圖片大小小于8kb,就會(huì)被base64處理
// 優(yōu)點(diǎn):減少請(qǐng)求數(shù)量(減輕服務(wù)器壓力)
// 缺點(diǎn):圖片體積會(huì)更大(文件請(qǐng)求速度更慢)
limit: 8 * 1024,
// 問(wèn)題:因?yàn)閡rl-loader默認(rèn)使用es6模塊化解析,而html-loader引入圖片是commonjs
// 解析時(shí)會(huì)出現(xiàn)問(wèn)題:[object Module]
// 解決:關(guān)閉url-loader的es6模塊化,使用commonjs解析
esModule:false,
// 給圖片進(jìn)行重命名
// [hash:10]取圖片的hash前10位
// [ext]取文件原來(lái)拓展名
name:'[hash:10].[ext]'
},}
],
type: 'javascript/auto'
},{
test: /\.html$/,
// 處理html文件的img圖片(負(fù)責(zé)引入img,從而能被url-loader進(jìn)行處理)
loader: 'html-loader',
}
}
方法2:webpack新方法資源模塊(asset module)是一種模塊類型,它允許使用資源文件(字體,圖標(biāo)等)而無(wú)需配置額外 loader。
四種新的模塊類型
asset/resource 發(fā)送一個(gè)單獨(dú)的文件并導(dǎo)出 URL。之前通過(guò)使用 file-loader 實(shí)現(xiàn)。asset/inline 導(dǎo)出一個(gè)資源的 data URI。之前通過(guò)使用 url-loader 實(shí)現(xiàn)。asset/source 導(dǎo)出資源的源代碼。之前通過(guò)使用 raw-loader 實(shí)現(xiàn)。asset 在導(dǎo)出一個(gè) data URI 和發(fā)送一個(gè)單獨(dú)的文件之間自動(dòng)選擇。之前通過(guò)使用 url-loader,并且配置資源體積限制實(shí)現(xiàn)。 // build/webpack.prod.js
//在output中統(tǒng)一Asset Module 輸出路徑
output: {
publicPath: '/',
filename: 'js/[name].[contenthash:8].js',
path: pathResolve('../dist'),
assetModuleFilename: 'images/[name].[contenthash:8].[ext]',
},
// build/webpack.common.js
module: {
rules: [
{
// 處理圖片資源 webpack5圖片新打包方法
test: /\.(png|jpe?g|gif|webp)$/,
// webpack5中使用assets-module(url-loader已廢棄)
type: 'asset',
parser: {
dataUrlCondition: {
maxSize: 10 * 1024,// 小于10kb的圖片會(huì)被base64處理
}
},
generator: {
// 將圖片文件輸出到 static/imgs 目錄中
// 將圖片文件命名 [hash:8][ext][query]
// [hash:8]: hash值取8位
// [ext]: 使用之前的文件擴(kuò)展名
// [query]: 添加之前的query參數(shù)
filename: "static/imgs/[hash:8][ext][query]",
publicPath: './'
}
},{
test: /\.html $/,
// 處理html文件的img圖片(負(fù)責(zé)引入img,從而能被url-loader處理)
// webpack5中使用 html-withimg-loader代替loader: 'html-loader'
loader: 'html-withimg-loader'
}
}
打包統(tǒng)一字體
資源模塊(asset module)是一種模塊類型,它允許使用資源文件(字體,圖標(biāo)等)而無(wú)需配置額外 loader。默認(rèn)情況下,asset/resource 模塊以 [hash][ext][query] 文件名發(fā)送到輸出目錄。
// build/webpack.common.js
module: {
rules: [
{
// 加載字體圖標(biāo)
test: /\.(eot|ttf|svg|woff)$/,
type: "asset/resource",
generator: {
// 輸出到 font 目錄中,占位符 [name] 保留原始文件名,
// [hash] 防止出現(xiàn)相同文件名無(wú)法區(qū)分,[ext] 拿到后綴名
filename: "font/[name].[hash:6][ext]",
},
},
],
},
步驟6
css壓縮
npm install mini-css-extract-plugin --save-dev npm install css-minimizer-webpack-plugin --save-dev
// build/webpack.common.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
optimization: {
minimizer: [
// 在 webpack@5 中,你可以使用 `...` 語(yǔ)法來(lái)擴(kuò)展現(xiàn)有的 minimizer(即 `terser-webpack-plugin`),將下一行取消注釋
// `...`,
new CssMinimizerPlugin(),
],
},
plugins: [new MiniCssExtractPlugin()],
};
js壓縮
terser-webpack-plugin:用去去除生產(chǎn)環(huán)境的無(wú)用js代碼,webpack5 之后自帶,不需要另行安裝,直接引入使用即可
extractComments:設(shè)為 false 表示去除所有注釋,除了有特殊標(biāo)志的注釋如 @preserve 標(biāo)記pure_funcs:去除函數(shù),如上述配置的意思是將所有 console.log 函數(shù)去除
// build/webpack.prod.js
const TerserPlugin = require("terser-webpack-plugin")
module.exports = merge(common, {
optimization: {
minimize: true,
minimizer:[
new TerserPlugin({
extractComments: false,
terserOptions: {
compress: { pure_funcs: ['console.log'] },
}
}),
]
}
})
清除打包數(shù)據(jù)
clean-webpack-plugin:清除上一次打包的 dist 目錄內(nèi)容,防止文件殘留
// build/webpack.common.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
...
plugins: [
...
new CleanWebpackPlugin(),
],
}
緩存機(jī)制——大大增快二次編譯速度,webpack5 已內(nèi)置該功能【cache機(jī)制及配置參考】
cache.type:緩存類型,值為 memory 或 filesystem,分別代表基于內(nèi)存的臨時(shí)緩存,以及基于文件系統(tǒng)的持久化緩存 cache.buildDependencies:全局緩存失效的一種機(jī)制,配置 {config: [__filename]},表示當(dāng)配置文件內(nèi)容或配置文件依賴的模塊文件發(fā)生變化時(shí),當(dāng)前的構(gòu)建緩存即失效
// build/webpack.common.js
module.exports = {
cache: {
type: 'filesystem',
buildDependencies: {
config: [__filename],
},
},
}
代碼分割——當(dāng)使用懶加載寫法時(shí),webpack自動(dòng)會(huì)對(duì)代碼進(jìn)行分割成不同的chunk
瀏覽器緩存可縮短網(wǎng)頁(yè)交互時(shí)間降低首屏?xí)r間
// 在react中比較常見(jiàn)的是React.lazy
const MyComponent = React.lazy(() => import('Components/MyComponent'))
將第三方依賴打包獨(dú)立chunk,需要在webpack額外進(jìn)行配置
? splitChunks:代碼分割相關(guān)配置
? splitChunks.chunks:選擇哪些內(nèi)容進(jìn)行優(yōu)化,如果為 all 時(shí)表示即使同步和異步的代碼也可以共享thunk
? minSize:生成chunk的最小大小(以字節(jié)為單位)
// build/webpack.dev.js
module.exports = merge(common, {
optimization: {
minimize: false,
minimizer: [],
splitChunks: {
chunks: 'all',
minSize: 0,
},
},
})
// build/webpack.prod.js
module.exports = merge(common, {
optimization: {
// ...other
splitChunks: {
chunks: 'all',
minSize: 0,
},
}
})
柚子快報(bào)邀請(qǐng)碼778899分享:前端 webpack常用配置
參考閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。