Webpack學習筆記
第1章 Webpack簡介
學習視頻:https://www.bilibili.com/video/BV1e7411j7T5?p=1&spm_id_from=pageDriver
1.1Webpack是什么
Webpack 是一種前端資源構建工具,一個靜態模塊打包器(module bundler).
在Webpack看來,前端的所有資源文件(js/json/css/img/less/...)都會作為模塊處理.
它根據模塊的依賴關系進行靜態分析,打包生成對應的靜態資源(bundle).
1.2Webpack五個核心概念
-
1.2.1 Entry

-
1.2.2 Output

-
1.2.3 Loader

-
1.2.4 Plugins

-
1.2.5 Mode

第2章webpack初體驗



2.1 webpack打包樣式資源(css,less)
/*
webpack.config.js webpack的配置文件
作用指示:webpack 干哪些活 (當你運行webpack 指令時,會加載里面的配置)
所有構建工具都是基于nodejs平臺運行的~ 模塊化默認采用commonjs.
*/
// resolve 用來拼接絕對路徑的方法
const { resolve } = require('path');
module.exports = {
// webpack配置
// 入口起點
entry: './src/index.js',
output: {
// 輸出文件名
filename: 'built.js',
// 輸出路徑
// __dirname nodejs的變量,代表當前文件的目錄絕對路徑
path: resolve(__dirname, 'build'),
},
// loader的配置
module: {
rules: [
// 詳細loader配置
{
test: /\.css$/,
use: [
// use數組中loader執行順序:從右到左,從下到上依次執行
// 創建style標簽,將js中的樣式資源插入進去,添加到head中生效
'style-loader',
// 將css文件變成commonjs模塊加載js中,里面內容是樣式字符串
'css-loader',
],
},
{
test:/.\less$/,
use:[
'style-loader',
'css-loader',
// 將less文件編譯成css文件
// 需要下載less-loader和 less
'less-loader'
]
}
],
},
// plugins 的配置
plugins: [],
// 模式
mode: 'development',
// mode:'production'
};
2.2 webpack打包html資源
/*
loader: 1.下載 2.使用(配置loader)
plugins:1.下載 2.引用 3.使用
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
module:{
rules:[
// loader配置
]
},
plugins:[
// plugins的配置
// html-webpack-plugin
// 功能:默認會創建一個空的html,自動引入打包輸出的所有資源(JS/CSS)
new HtmlWebpackPlugin({
// 復制'./src/index.html' ,并自動引入打包輸出的所有資源(JS/CSS)
template:'./src/index.html'
})
],
mode:'development'
};
2.3 打包圖片資源
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.less$/,
use: [
// 要使用多個loader處理用use
'style-loader',
'css-loader',
'less-loader',
],
},
{
// 問題:默認處理不了html中的img圖片 (webpack5時省略該圖片loader配置,能默認處理而不需要該處配置)
// 處理圖片資源
test:/\.(jpg|png|gif)$/,
// webpack5已經棄用url-loader
// 使用一個loader
// 下載url-loader file-loader
loader:'url-loader',
options:{
// 圖片大小小于8kb,就會被base64處理
// 優點:減輕請求數量(減輕服務器壓力)
// 缺點:圖片體積會更大(文件請求速度更慢)
limit:8*1024,
// 問題:因為url-loader默認使用es6模塊化解析,而htm-loader引入圖片是commonjs
// 解析時會出問題:[object Module]
// 解決:關閉url-loader的es6模塊化,使用commonjs解析
esModule:false,
// 給圖片重命名,[hash:10]:取圖片的hash的前10位,[ext]:取文件原來擴展名
name: '[hash:10].[ext]'
}
},
{
test:/\.html$/,
// 處理html文件的img圖片(如則引入img,從而能被url-loader處理)
loader:'html-loader'
}
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
// mode:'production'
};
2.4 打包其他資源(字體)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口
entry: './src/index.js',
// 出口
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
// loader配置
module: {
rules: [
// 打包css
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
// 打包其他資源(除了html/css/js以外的資源)
{
// 排除css/js/html
// exclude: /\.(css|js|html)$/,
// webpack file-loader棄用
//loader:'file-loader'
test:/\.ttf|eot|woff2?$/, // webpack5打包字體資源
type: 'asset/resource',
generator: {
filename: 'font/[name].[hash:6][ext]',
},
},
],
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 開發環境/生產環境
mode: 'development',
// mode:'production'
};
2.5 使用devServer
/*
開發環境配置:能讓代碼運行
運行項目指令:
webpack 會將打包結果輸出出去
npx webpack serve 只會在內存中打包編譯,沒有輸出
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 入口
entry: './src/index.js',
// 出口
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
// loader配置
module: {
rules: [
// 打包css
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
// 打包其他資源(除了html/css/js以外的資源)
{
// 排除css/js/html
// exclude: /\.(css|js|html)$/,
// webpack file-loader棄用
//loader:'file-loader'
test: /\.ttf|eot|woff2?$/, // webpack5打包字體資源
type: 'asset/resource',
generator: {
filename: 'font/[name].[hash:6][ext]',
},
},
],
},
// 插件
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 開發環境/生產環境
mode: 'development',
// mode:'production'
// 開發服務器 devServer: 用來自動化(自動編譯,自動打開瀏覽器,自動刷新瀏覽器)
// 特點:只會在內存中編譯打包,不會有任何輸出
// 啟動devServer指令為:npx webpack serve
// 下載:webpack-dev-server
devServer: {
// 項目構建夠路徑
static: {
directory: resolve(__dirname, 'build'),
},
// 啟動gzip壓縮
compress: true,
// 所啟動服務器的端口號
port: 3003,
// 自動打開瀏覽器
open: true,
},
};
第3章webpack開發環境的基本配置
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用資源模塊處理字體
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用資源模塊處理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用資源模塊處理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用資源模塊處理圖片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 轉base64條件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 處理html中的圖片
test: /\.html$/,
loader: 'html-loader',
options:{
esModule:false
}
},
],
},
plugins: [
// 處理html資源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 項目構建目錄
static:{
directory:resolve(__dirname,'build'),
},
compress:true, // gzip壓縮
open:true, // 自動打開瀏覽器
port:3003, // 端口
},
};
第4章 webpack生產環境基本介紹
4.1 將CSS提取成單獨文件
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 創建style標簽,將樣式放入
// 'style-loader',
// 這個loader取代style-loader.作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
// 將css文件整合到js文件中
'css-loader',
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
// 提取CSS成單獨文件
new MiniCssExtractPlugin({
// 對輸出的CSS文件進行重命名
filename: 'css/built.css',
}),
],
mode: 'development',
};
4.2 CSS兼容性處理
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 設置nodejs環境變量
process.env.NODE_ENV = 'development';
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
/*
兼容性處理
postcss:postcss-loader和postcss-preset-env
識別對應的環境加載對應的配置
該插件幫postcss找到package.json中的browserslist里面的配置,通過配置加載指定的css兼容性樣式
"browserslist":{
* 開發環境 :設置node環境變量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一個chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生產環境: 默認是看生產環境
"production":[
">0.2%",
"not dead", // 不要已經丟棄的瀏覽器
"not op_mini all" 不要所有的歐朋瀏覽器
]
}
*/
{
loader: 'postcss-loader',
options: {
postcssOptions:{
plugins: [require('postcss-preset-env')()],
}
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/built.css',
}),
],
mode: 'development',
};
4.3 CSS壓縮
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
// 設置nodejs環境變量
// process.env.NODE_ENV = 'development';
// optimize-css-assets-webpack-plugin
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
// 將CSS提取成單獨文件
MiniCssExtractPlugin.loader,
'css-loader',
// 兼容性處理
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [require('postcss-preset-env')()],
},
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new MiniCssExtractPlugin({
filename: 'css/built.css',
}),
// 壓縮文件(webpack5采用該插件:CssMinimizerWebpackPlugin)
new OptimizeCssAssetsWebpackPlugin(),
],
mode: 'development',
};
4.4 Eslint語法檢查
// webpack.config.js
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
mode: "development",
entry: './src/index.js',
// devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
compress: true,
open: false
},
output: {
publicPath: '/',
// 指定打包后輸出的文件名
filename: 'js/app.[contenthash:10].js',
// 指定打包后輸出的目錄
path: path.resolve(__dirname, 'dist')
},
resolve: {
alias: {
# !!!!!!注意如果配置了此處 要安裝步驟5的插件!!!!!!!! #
"@": path.resolve(__dirname, 'src')
}
},
module: {
rules: [
]
},
plugins: [
#使用 配置項都可以在eslint-webpack-plugin的github上找到
new ESLintPlugin({
// 啟用 ESLint 自動修復特性
fix: true,
// 指定需要檢查的擴展名。
extensions: ['js', 'json', 'coffee'],
// 指定需要排除的文件及目錄。必須是相對于 options.context 的相對路徑
exclude: '/node_modules/'
}),
]
};
// package.json
"eslintConfig": {
"extends": "airbnb-base",
#!!!!如果沒使用alias下面的不用配置!!!!!
"settings": {
"import/resolver": {
"webpack": {
"config": "webpack.config.js"
}
}
}
}
4.5 js兼容性處理
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
/*
js兼容性處理:babel-loader @babel/core @babel/preset-env
1. 基本js兼容性處理 --> @babel/preset-env
問題: 只能轉換基本語法,如promise不能轉換
2. 全部js兼容性處理 -->@babel/polyfill不用寫配置,引入即可(下載了,只需要引入即可:import '@babel/polyfill'; )
問題:我只要解決部分的兼容性問題,但是將所有的兼容性代碼引入,體積太大了
3.需要做兼容性處理的就做:按需加載 --> core-js
*/
{
test: /\.js$/,
// 排除第三方庫
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 預設:指示babel做怎么樣的兼容性處理
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
module: 'development',
};
4.6 壓縮html和js
js壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
// 生產環境下會自動壓縮js代碼
module: 'production',
};
html壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 壓縮html
minify: {
// 移出空格
collapseWhitespace: true,
// 移出注釋
removeComments: true,
},
}),
],
// 生產環境下會自動壓縮js代碼
module: 'production',
};
第5章webpack生產環境的基本配置
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //處理css文件并提取成單獨文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 定義nodejs環境變量:決定使用browserslist的哪個環境變量
process.env.NODE_ENV = 'production';
// 復用loader
const commonCssLoader = [
// 這個loader取代style-loader.作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
// 將css文件整合(加載)到js文件中
'css-loader',
// 兼容性處理
{
// 還需要在package.json中定義browserslist
/*"browserslist":{
* 開發環境 :設置node環境變量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一個chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生產環境: 默認是看生產環境
"production":[
">0.2%",
"not dead", // 不要已經丟棄的瀏覽器
"not op_mini all" 不要所有的歐朋瀏覽器
]
}
*/
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
/*
正常來講,一個文件只能被一個loader處理,
當一個文件要被多個loader處理,name一定要指定loader執行的順序
先執行eslint 在執行babel
*/
{
// js語法檢查 在package.json中添加eslintConfig -->airbnb
/*
在package.json中添加eslintConfig -->airbnb
"eslintConfig": {
"extends": "airbnb-base"
}
*/
test: /\.js$/,
exclude: /node_modules/,
// 優先執行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
{
// 處理圖片資源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 處理HTML資源中的圖片
test: /\.html/,
loader: 'html-loader',
},
{
// 處理其他資源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
plugins: [
// 提取CSS成單獨文件
new MiniCssExtractPlugin({
// 對輸出的CSS文件進行重命名
filename: 'css/built.css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html壓縮 移出空格,注釋
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
};
第5章webpack優化配置
5.1 開發環境性能優化
- 優化打包構建速度
- 優化代碼調試
5.2 生產環境性能優化
- 優化打包構建速度
- 優化代碼運行的性能
5.3 HMR: hot module replacement 熱模塊替換 / 模塊熱替換
/*
HMR: hot module replacement 熱模塊替換 / 模塊熱替換
作用:一個模塊發生變化,只會重新打包這一個模塊(而不是打包所有模塊)
極大提升構建速度
樣式文件:可以使用HMR功能,因為style-loader內部實現了~
js文件:默認不能使用HMR功能 -->需要修改js代碼,添加支持HMR功能的代碼
注意:HMR功能對js的處理,只能處理非入口js文件的其他文件.
html文件:默認不能使用HMT功能,同時會導致問題:html文件不能熱更新了
解決:修改entry入口,將html文件引入
*/
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['./src/index.js','./src/index.html']
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用資源模塊處理字體(其他資源)
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用資源模塊處理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用資源模塊處理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用資源模塊處理圖片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 轉base64條件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 處理html中的圖片
test: /\.html$/,
loader: 'html-loader',
options: {
esModule: false,
},
},
],
},
plugins: [
// 處理html資源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 項目構建目錄
static: {
directory: resolve(__dirname, 'build'),
},
compress: true, // gzip壓縮
open: true, // 自動打開瀏覽器
port: 3003, // 端口
hot: true, //開啟HMR功能 (當修改了webpack配置,新配置要想生效,必須重啟webpack服務)
},
};
5.4 source-map: 一種提供源代碼到構建后代碼映射技術(如果構建后代碼出錯,通過映射關系可以追蹤到源代碼錯誤)
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: ['./src/index.js', './src/index.html'],
output: {
filename: 'built.js',
path: resolve(__dirname, 'build'),
},
module: {
rules: [
{
// 使用資源模塊處理字體(其他資源)
test: /\.(eot|svg|ttf|woff|woff2)$/i,
type: 'asset/resource',
generator: {
filename: 'fonts/[name].[hash:5][ext]',
},
},
{
// 使用資源模塊處理CSS
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
// 使用資源模塊處理less
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader'],
},
{
// 使用資源模塊處理圖片
test: /\.(jpg|png|gif)$/i,
type: 'asset',
parser: {
// 轉base64條件
dataUrlCondition: {
maxSize: 8 * 1024, //8kb
},
generator: {
filename: 'images/[name][ext]',
},
},
},
{
// 處理html中的圖片
test: /\.html$/,
loader: 'html-loader',
options: {
esModule: false,
},
},
],
},
plugins: [
// 處理html資源
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
mode: 'development',
devServer: {
// 項目構建目錄
static: {
directory: resolve(__dirname, 'build'),
},
compress: true, // gzip壓縮
open: true,
port: 3003,
hot: true,
},
devtool: 'source-map',
};
/*
source-map: 一種提供源代碼到構建后代碼映射技術(如果構建后代碼出錯,通過映射關系可以追蹤到源代碼錯誤)
參數:
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
source-map:外部
錯誤代碼準確信息 和 源代碼的錯誤位置
inline-source-map:內聯
只生成一個內聯source-map
錯誤代碼準確信息 和 源代碼的錯誤位置
hidden-source-map:外部
錯誤代碼錯誤原因,但是沒有錯誤位置
不能追蹤源代碼錯誤,只能提示到構建后代碼的錯誤位置
eval-source-map:內聯
每一個文件都生成對應的source-map,都在eval函數中
錯誤代碼準確信息 和 源代碼的錯誤位置
nosources-source-map:外部
錯誤代碼準確信息,但是沒有任何源代碼信息
cheap-source-map:外部
錯誤代碼準確信息 和源代碼錯誤位置
只能精確到行
cheap-module-source-map:外部
錯誤代碼準確信息 和源代碼錯誤位置
只能精確到行
module會將loader的source map加入
內聯和外部的區別: 1.外部生成了文件,內聯沒有 2.內聯構建速度更快
開發環境:速度快,調試更友好
速度快(eval>inline>cheap>...)
eval-cheap-source-map
eval-source-map
調試更友好
source-map
cheap-module-source-map
cheap-source-map
-->eval-source-map / eval-cheap-module-source-map
生產環境:源代碼要不要隱藏?調試要不要更友好
內聯會讓代碼體積變大,所以生產環境不用內聯
nosources-source-map 全部隱藏
hidden-source-map 只隱藏源代碼,會提示構建后代碼錯誤信息
-->source-map/cheap-module-source-map
*/
5.5 oneOf:生產環境提升打包構建速度
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //處理css文件并提取成單獨文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 定義nodejs環境變量:決定使用browserslist的哪個環境變量
process.env.NODE_ENV = 'production';
// 復用loader
const commonCssLoader = [
// 這個loader取代style-loader.作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
// 將css文件整合(加載)到js文件中
'css-loader',
// 兼容性處理
{
// 還需要在package.json中定義browserslist
/*"browserslist":{
* 開發環境 :設置node環境變量 process.env.NODE_ENV = development
"development": [
"last 1 chrome version", // 兼容最近的一個chrome版本
"last 1 firefox version",
"last 1 safari version"
],
* 生產環境: 默認是看生產環境
"production":[
">0.2%",
"not dead", // 不要已經丟棄的瀏覽器
"not op_mini all" 不要所有的歐朋瀏覽器
]
}
*/
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js語法檢查 在package.json中添加eslintConfig -->airbnb
/*
在package.json中添加eslintConfig -->airbnb
"eslintConfig": {
"extends": "airbnb-base"
}
*/
test: /\.js$/,
exclude: /node_modules/,
// 優先執行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只會匹配一個
// 注意:不能有兩個配置處理同一種類型文件
oneOf:[
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
/*
正常來講,一個文件只能被一個loader處理,
當一個文件要被多個loader處理,name一定要指定loader執行的順序
先執行eslint 在執行babel
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
},
},
{
// 處理圖片資源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 處理HTML資源中的圖片
test: /\.html/,
loader: 'html-loader',
},
{
// 處理其他資源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
]
}
],
},
plugins: [
// 提取CSS成單獨文件
new MiniCssExtractPlugin({
// 對輸出的CSS文件進行重命名
filename: 'css/built.css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html壓縮 移出空格,注釋
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
};
5.6 緩存:生產環境緩存的配置
視屏教程地址:https://www.bilibili.com/video/BV1e7411j7T5?p=23&spm_id_from=pageDriver
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //處理css文件并提取成單獨文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
緩存:
babel緩存
cacheDirectory:true
-->讓第二次打包構建速度更快
文件資源緩存
hash: 每次webpack構建時會生成一個唯一的哈希值
問題: 因為js和css同時使用一個hash值.
如果重新打包,會導致所有緩存失效.
chunkhash: 根據chunk生成的hash值.如果打包來源于同一個chunk,那么hash值就一樣
問題: js和css的hash值還是一樣的.
因為css是在js中被引入的,所以屬于同一個chunk
contenthash: 根據文件的內容生成hash值.不同文件hash值一定不一樣.
-->讓代碼上線運行緩存更好使用
*/
// 定義nodejs環境變量:決定使用browserslist的哪個環境變量
process.env.NODE_ENV = 'production';
// 復用loader
const commonCssLoader = [
// 這個loader取代style-loader.作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
// 將css文件整合(加載)到js文件中
'css-loader',
// 兼容性處理
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js語法檢查 在package.json中添加eslintConfig -->airbnb
test: /\.js$/,
exclude: /node_modules/,
// 優先執行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只會匹配一個
// 注意:不能有兩個配置處理同一種類型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
// 開啟babel緩存 第二次構建時,會讀取之前的緩存
cacheDirectory: true,
},
},
{
// 處理圖片資源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 處理HTML資源中的圖片
test: /\.html/,
loader: 'html-loader',
},
{
// 處理其他資源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
],
},
plugins: [
// 提取CSS成單獨文件
new MiniCssExtractPlugin({
// 對輸出的CSS文件進行重命名
filename: 'css/built.[contenthash:10].css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html壓縮 移出空格,注釋
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
// 映射
devtool: 'source-map',
};
5.7 tree shaking(樹搖/樹震):
const { resolve } = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); //處理css文件并提取成單獨文件
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // css壓縮
const HtmlWebpackPlugin = require('html-webpack-plugin');
/*
tree shaking: 去除無用代碼
前提: 1. 必須使用ES6模塊化 2.開啟production環境 -->同時滿足,自動開啟tree shaking
作用: 減少代碼體積
在package.json中配置
"sideEffects": false 所有代碼都沒有副作用(都可以進行tree shaking)
問題: 可能會把css/@babel/polyfill(副作用)文件干掉
"sideEffects": ["*.css","*.less"]
*/
// 定義nodejs環境變量:決定使用browserslist的哪個環境變量
process.env.NODE_ENV = 'production';
// 復用loader
const commonCssLoader = [
// 這個loader取代style-loader.作用:提取js中的css成單獨文件
MiniCssExtractPlugin.loader,
// 將css文件整合(加載)到js文件中
'css-loader',
// 兼容性處理
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [require('postcss-preset-env')()],
},
},
];
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/built.[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
modules: {
rules: [
{
// js語法檢查 在package.json中添加eslintConfig -->airbnb
test: /\.js$/,
exclude: /node_modules/,
// 優先執行
enforce: 'pre',
loader: 'eslint-loader',
options: {
fix: true,
},
},
{
// 以下loader只會匹配一個
// 注意:不能有兩個配置處理同一種類型文件
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader],
},
{
test: /\.less$/,
use: [...commonCssLoader, 'less-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加載
useBuiltIns: 'usage',
// 指定core-js版本
corejs: {
version: 3,
},
// 指定兼容性做到哪個版本瀏覽器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
edge: '17',
safari: '10',
},
},
],
],
// 開啟babel緩存 第二次構建時,會讀取之前的緩存
cacheDirectory: true,
},
},
{
// 處理圖片資源
test: /\.(jpg|png|gif)/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[hash:10].[ext]',
outputPath: 'imgs',
esModule: false,
},
},
{
// 處理HTML資源中的圖片
test: /\.html/,
loader: 'html-loader',
},
{
// 處理其他資源
exclude: /\.(js|css|less|html|jpg|png|gif)/,
loader: 'file-loader',
options: {
output: 'media',
},
},
],
},
],
},
plugins: [
// 提取CSS成單獨文件
new MiniCssExtractPlugin({
// 對輸出的CSS文件進行重命名
filename: 'css/built.[contenthash:10].css',
}),
new OptimizeCssAssetsWebpackPlugin(),
new HtmlWebpackPlugin({
template: './src/index.html',
// html壓縮 移出空格,注釋
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
mode: 'production',
// 映射
devtool: 'source-map',
};
5.8 code split:代碼分割
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// 單入口
//entry: './src/js/index.js',
entry: {
index: './src/js/index.js',
test: './src/js/test/js',
},
output: {
// name: 取文件名(取index/test)
filename: 'js/[name].[contenthash:10].js',
path: resolve(__dirname, 'build'),
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// html壓縮 移出空格,注釋
minify: {
collapseWhitespace: true,
removeComments: true,
},
}),
],
// 可以將node_modules中代碼單獨打包成一個chunk最終輸出
// 自動分析多入口chunk中,有沒有公共的文件.如果有會打包成一個單獨chunk
optimization: {
splitChunks: {
chunks: 'all',
},
},
mode: 'production',
};
代碼分割之方法3

5.9 懶加載和預加載

PWA:漸進式網絡開發應用程序
多進程打包
externals
dll (動態連接庫)
性能優化總結
### WEBPACK 性能優化
- 開發環境性能優化
- 生產環境性能優化
#### 開發環境性能優化
- 優化打包構建速度
- HMR
- 優化代碼調試
- source-map
#### 生產環境性能優化
- 優化打包構建速度
- onfOf
- babel 緩存
- 多進程打包
- externals(讓某些庫不打包,直接通過 cdn 連接引入)
- dll(讓某些庫不打包,單獨打包)
- 優化代碼運行的性能
- 緩存(hash-chunkhash-contenthash)
- tree shaking(樹搖)
- code split(代碼分割)
- 懶加載/預加載
- PWA(漸進式網絡應用開發技術/離線訪問技術)
第6章 webpack詳細配置
webpack詳細配置之entry
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
/*
entry:入口起點
1.string --> './src/index.js'
單入口(應用最多)
打包形成一個chunk.輸出一個bundle文件
此時chunk的名稱默認是 main
2.array --> ['./src/index.js','./src/add.js']
多入口
所有入口文件最終只會形成一個chunk,輸出出去只有一個bundle文件.
-->只有在HMR功能中讓html熱更新生效
3.object -->entry: { index: './src/index.js', add: './src/add.js' },
多入口
有幾個入口文件就形成幾個chunk,輸出幾個bundle文件
此時chunk的名稱就是key
-->特殊用法
{
// 所有入口文件最終只會形成一個chunk,輸出出去只有一個bundle文件.
index: ['./src/index.js', './src/count.js'],
// 形成一個chunk,輸出一個bundle文件
add: './src/add.js'
}
*/
module.exports = {
// entry: './src/index.js',
entry: { index: ['./src/index.js', './src/count.js'], add: './src/add.js' },
output: {
filename: '[name].js',
path: resolve(__dirname, 'build'),
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack詳細配置之output
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/index.js',
output: {
// 文件名稱(可以指定名稱+目錄)
filename: 'js/[name].js',
// 輸出文件目錄(將來所有資源輸出的公共目錄)
path: resolve(__dirname, 'build'),
// (一般適用于生產環境)所有資源引入公共路徑前綴-->'imgs/a.jpg'-->'/imgs/a.jpg'
publicPath: '/',
chunkFilename: '[name]_chunk.js', // 非入口chunk的名稱
// 一般結合dll一起使用
//library: '[name]', // 整個庫向外暴露的變量名
//libraryTarget:'window',// 變量名添加到哪個上 browser
//libraryTarget:'global',// 變量名添加到哪個上 node
//libraryTarget:'commonjs',
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack詳細配置之module
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/index.js',
output: {
// 文件名稱(可以指定名稱+目錄)
filename: 'js/[name].js',
// 輸出文件目錄(將來所有資源輸出的公共目錄)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多個loader 用use
use: ['style-loader', 'css-loader'],
},
{
test: /\.js$/,
// 排除node_modules下的js文件
exclude: /node_modules/,
// 只檢查src下面的js文件
include: resolve(__dirname, 'src'),
// pre 優先執行 ,post 延后執行
enforce: 'pre',
// 單個loader
loader: 'eslint-loader',
},
{
// 以下配置只會生效一個
oneOf: [],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
};
webpack詳細配置之resolve(用來解析模塊的規則)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名稱(可以指定名稱+目錄)
filename: 'js/[name].js',
// 輸出文件目錄(將來所有資源輸出的公共目錄)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多個loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
// 解析模塊的規則
resolve: {
// 配置解析模塊路徑別名: 優點可以簡寫路徑 缺點:寫路徑時沒有提示
alias: {
$css: resolve(__dirname, 'src/css'),
},
// 配置省略文件路徑的后綴名
extensions: ['.js', '.json', 'jsx', '.css'],
// 告訴 webpack 解析模塊是去找哪個目錄
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
};
webpack詳細配置之devServer
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名稱(可以指定名稱+目錄)
filename: 'js/[name].js',
// 輸出文件目錄(將來所有資源輸出的公共目錄)
path: resolve(__dirname, 'build'),
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多個loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'development',
// 解析模塊的規則
resolve: {
// 配置解析模塊路徑別名: 優點可以簡寫路徑 缺點:寫路徑時沒有提示
alias: {
$css: resolve(__dirname, 'src/css'),
},
// 配置省略文件路徑的后綴名
extensions: ['.js', '.json', 'jsx', '.css'],
// 告訴 webpack 解析模塊是去找哪個目錄
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
// 用于開發環境
devServer: {
// 運行代碼的目錄
contentBase: resolve(__dirname, 'build'),
// 監視contentBase 目錄下的所有文件,一旦文件發生變化就會 reload(重載)
watchContentBase: true,
watchOptions: {
// 忽略文件
ignored: /node_modules/,
},
// 啟動gzip壓縮
compress: true,
// 端口
port: 5000,
// 域名
host: 'localhost',
// 自動瀏覽器
open: true,
// 開啟HMR功能
hot: true,
// 不需要顯示啟動服務器日志信息
clientLogLevel: 'none',
// 除了一些基本啟動信息以外,其他內容都不要顯示
quiet: true,
// 如果出現錯誤,不要全屏提示
overlay: false,
// 服務器代理 -->解決開發環境跨域問題
proxy: {
// 一旦devServer(5000)服務器接受到 /api/xxx 的請求,就會把請求轉發到另外一個服務器 (3000)
'/api': {
target: 'http://localhost:3000',
// 發送請求時,請求路徑重寫:將 /api/xxx --> /xxx (去掉/api)
pathRewrite: {
'^/api': '',
},
},
},
},
};
webpack詳細配置之optmization
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { resolve } = require('path');
const TerserWebpackPlugin = require('terser-webpack-plugin');
module.exports = {
entry: './src/js/index.js',
output: {
// 文件名稱(可以指定名稱+目錄)
filename: 'js/[name].[contenthash:10].js',
// 輸出文件目錄(將來所有資源輸出的公共目錄)
path: resolve(__dirname, 'build'),
chunkFilename: 'js/[name].[contenthash:10]_chunk.js',
},
module: {
rules: [
// loader 配置
{
test: /\.css$/,
// 多個loader 用use
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [new HtmlWebpackPlugin()],
mode: 'production',
resolve: {
alias: {
$css: resolve(__dirname, 'src/css'),
},
extensions: ['.js', '.json', 'jsx', '.css'],
modules: [resolve(__dirname, '../../node_modules'), 'node_modules'],
},
optimization: {
splitChunks: {
chunks: 'all',
// 默認值,可以不寫
/* minSize: 30 * 1024, // 分割的chunk最小為30kb
maxSize: 0, // 最大沒有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加載時并行加載的文件的最大數量
maxInitialRequests: 3, // 入口js文件最大并行請求數量
automaticNameDelimiter: '~', // 名稱連接符
name: true, // 可以使用命名規則
cacheGroups: {
// 分割chunk的組
// node_modules文件會被打包到vendors 組的chunk中. -->vendors~XXX.js
// 滿足上面的公共規則,如:大小超過30KB,至少被引用一次.
vendors: {
test: /[\\/]node_modules[\\/]/,
// 優先級
priority: -10,
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
priority: -20,
// 如果當前要打包的模塊,和之前已經被提取的模塊是同一個,就會復用.而不是重新打包模塊
reuseExistingChunk: true,
},
}, */
},
// 將當前模塊的記錄其他模塊的hash單獨打包為一個文件 runtime
// 解決:修改a文件導致b文件的contenthash變化
runtimeChunk: {
name: (entrypoint) => `runtime-${entrypoint.name}`,
},
// 配置生產環境的壓縮方案:js和css
minimizer: {
new TerserWebpackPlugin({
// 開啟緩存
cache:true,
// 開啟多進程打包
parallel:true,
// 啟用source-map
sourceMap:true,
})
},
},
};
第7章 webpack5介紹和使用
浙公網安備 33010602011771號