当前位置: 首页 > news >正文

webpack高级配置

一、了解webpack高级配置:

1、什么是webpack高级配置:

进行 Webpack 优化,让代码在编译或者运行时性能更好

2、webpack优化从哪些方面入手:

① 提升开发体验,增强开发和生产环境的代码调试:

如果代码编写出错了,在浏览器查看错误并且需要定位的时候,查看的是编译后的代码,难以定位具体的错误位置

② 提升打包构建速度:

(1) 模块更新:

开发时我们修改了其中一个模块代码,Webpack默认会将所有模块全部重新打包编译,速度很慢。

(2) 打包优化:

打包时每个文件都会匹配所有loader,速度比较慢。

(3) 第三方插件编译:

使用第三方的库或插件时,所有资源都会下载到 node_modules 中,这些资源是不需要编译可以直接使用的。

(4) eslintbabel缓存:

每次打包时js 文件都要经过 Eslint 检査 和 Babel 编译,速度比较慢。

(5) 多进程js文件打包:

当项目越来越庞大时,打包速度就会越来越慢。对js文件处理主要就是 eslintbabelTerser 三个工具,所以我们要提升它们的运行速度,。我们可以开启多进程同时处理js 文件,这样速度就比之前的单进程打包更快了。

③ 减少代码体积:

(1)第三方工具库引用:

对于自定义的工具函数库,或者引用第三方工具函数库、组件库。实际上可能只用上极小部分的功能,如果没有特殊处理,打包时会引入整个库,体积太大

(2)Babel编译时代码重复插入:

Babel 为编译的每个文件都插入了辅助代码,使代码体积过大

④ 优化代码运行性能:

二、提升开发体验:SourceMap

中文文档:https://webpack.docschina.org/configuration/devtool/#root

1、SourceMap 的定义:

SourceMap(源代码映射)是一个用来生成源代码与构建后代码一一映射的文件的方案。

2、为什么能优化调试:

① 使用SourceMap后,会生成一个 xxx.map 文件,里面包含源代码和构建后的代码每一行、每一列的映射关系。

② 浏览器会自动查找xxx.map 文件

③ 当代码出错时,浏览器会提示源代码文件出错位置(通过 xxx.map 文件,从构建后代码出错位置找到映射后源代码出错位置)

3、SourceMap的使用:

① 开发模式:devtool: 'cheap-module-source-map'

  • 优点:打包编译速度快,只包含行映射
  • 缺点:没有列映射
mode: 'development',
devtool: 'cheap-module-source-map'

② 生产模式:devtool: 'source-map'

  • 优点:包含行&列映射
  • 缺点:打包编译速度更慢
mode: 'production',
devtool: 'cheap-module-source-map'

在这里插入图片描述

三、提升打包构建速度:

1、模块热替换:HMR

中文文档:https://webpack.docschina.org/guides/hot-module-replacement

① 定义:

在程序运行中,替换、添加或删除模块,而无需重新加载整个页面(修改某个模块代码,就只有这个模块代码需要重新打包编译,其他模块不变)

② 使用:webpack5中是默认开启的

// 开发服务器:不会输出资源,在内存中编译打包
devServer: {host: 'localhost', // 启动服务器的域名port: '3001', // 启动服务器的端口号open: true, // 是否自动打开浏览器hot: true, // 开启 HMR(默认值)
}
(1)CSS模块热更新:

css 样式经过 style-loader 处理,已经具备 HMR 功能了

(2)JS模块热更新:
a、常规写法:
语法:
// 1. 监听特定模块
module.hot.accept('字符串或数组(模块路径)', [,'模块更新后的回调函数'])
// 2. 监听当前模块自身
module.hot.accept()
项目中使用:
// 配置js模块热更新
if(module.hot) {// 如果支持模块热更新module.hot.accept('./js/sum.js')module.hot.accept('./js/util.js')
}
b、vue或者React项目写法:

vue-loader:https://vue-loader.vuejs.org/
React Fast Refresh:https://reactnative.dev/docs/fast-refresh

2、模块热替换:oneOf

中文文档:https://webpack.docschina.org/configuration/module/#ruleoneof

① 定义:

只要匹配到一个 loader,剩下的就不匹配了

② 使用:

    // 加载器module: {rules: [{   // 当规则匹配时,只使用第一个匹配规则oneOf: [{test: /\.css$/i, // 匹配以.css结尾的文件use: ['style-loader', // 将js中的css通过style标签的形式添加到html中'css-loader' // 将css资源编译成commonjs的模块化js], // loader的执行顺序是从后往前的},{test: /\.less$/i,use: ['style-loader','css-loader','less-loader', // 将less文件编译为css文件],},{test: /\.s[ac]ss$/i,use: [// 将 JS 字符串生成为 style 节点'style-loader',// 将 CSS 转化成 CommonJS 模块'css-loader',// 将 Sass 编译成 CSS'sass-loader',],},{test: /\.styl$/i,use: ['style-loader','css-loader','stylus-loader', // 将stylus文件编译为css文件],},{   // webpack4处理图片资源的方式:使用file-loader、url-loader。// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// url-loader将图片资源进行优化// webpack5处理图片资源的方式(file-loader、url-loader已经内置):test: /\.(png|jpe?g|svg|webp|gif)$/,type: 'asset',parser: {dataUrlCondition: {maxSize: 30 * 1024 // 小于30kb的图片会转为base64 - 减少请求数量,但是体积会变大}},generator: { // 打包的图片输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/images/[hash:10][ext][query]'}},{   // webpack4处理图片资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理图片资源的方式(file-loader已经内置):test: /\.(ttf|woff2?)$/,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/fonts/[hash:10][ext][query]'}},{   // webpack4处理其它资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理其它资源的方式(file-loader已经内置):test: /\.(mp3|MP4|avi|.doc)$/i,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [name]表示保留原始文件名filename: 'static/media/[hash:10][ext][query]'}},{test: /\.js$/,exclude: /(node_modules)/, // 排除哪些文件不需要编译loader: 'babel-loader', // 只需要一个loader,不需要use// use: {//     loader: 'babel-loader',//     options: { // 智能预设,这个对象可以不写,那么就需要在项目的根目录下新建babel.config.js,添加智能预设//         presets: ['@babel/preset-env'],//     },// },}]}]},

3、第三方插件编译优化:exclude或者include

中文文档:https://webpack.docschina.org/configuration/module#ruleexclude

exclude 定义:

要排除符合条件的资源(对 js 文件处理时,排除 node modules 下面的文件)

include 定义:

只对当前包含的资源进行处理

③ 使用:

 //加载器module: {rules: [{   // 当规则匹配时,只使用第一个匹配规则oneOf: [{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译loader: 'babel-loader', // 只需要一个loader,不需要use}]}]},// 插件plugins: [new ESLintPlugin({ // eslint检测的文件都有哪些exclude: "node_modules", // 默认值,排除哪些文件不需要编译context: path.resolve(__dirname, '../src')}),new HtmlWebpackPlugin({ // 使用 html资源引入 插件,并且保留原模版template: path.resolve(__dirname, '../index.html')})]

4、 eslintbabel缓存:Cache

中文文档:https://webpack.docschina.org/configuration/cache/#root

① 定义:

缓存之前的 Eslint 检查 和 Babel 编译结果,加快后续打包速度

② 使用:

打包完成后的缓存js文件,默认路径在node_modules/.cache/babel-loader中

module.exports = {// 加载器module: {rules: [{oneOf: [{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译loader: 'babel-loader', // 只需要一个loader,不需要useoptions: {cacheDirectory: true, // 开启babel缓存cacheCompression: false, // 不压缩缓存文件}},]}]},// 插件plugins: [new ESLintPlugin({ // eslint检测的文件都有哪些exclude: "node_modules", // 默认值,排除哪些文件不需要编译context: path.resolve(__dirname, '../src'),cache: true, // 开启缓存cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), // 缓存文件存储的路径}),new HtmlWebpackPlugin({ // 使用 html资源引入 插件,并且保留原模版template: path.resolve(__dirname, '../index.html')}),new MiniCssExtractPlugin({ // 将所有的css提取到一个单独的文件中filename: 'static/css/main.css'}),new CssMinimizerPlugin()],
}

在这里插入图片描述

5、 多进程打包:Thead

中文文档:https://webpack.docschina.org/loaders/thread-loader/#root

① 定义:

开启电脑的多个进程同时干一件事,速度更快。

需要注意:请仅在特别耗时的操作中使用,因为每个进程启动就有大约为600ms 左右开销

② 使用:

(1)获取 cpu的核数:

启动的进程最大数量就是cpu的核数

// 引入os模块
const os = require('os')
// 获取cpu的核数
const threads = os.cpus().length;
(2)下载包:

npm install --save-dev thread-loader

(3)使用:
a、js 编译多核处理:
{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译use: [{loader: 'thread-loader', // 开启多进程options: {// 产生的 worker 的数量,默认是 (cpu 核心数 - 1)workers: threads,}},{loader: 'babel-loader', // 只需要一个loader,不需要useoptions: {cacheDirectory: true, // 开启babel缓存cacheCompression: false, // 不压缩缓存文件}}]
}
b、eslint 多核处理:
 plugins: [new ESLintPlugin({ // eslint检测的文件都有哪些exclude: "node_modules", // 默认值,排除哪些文件不需要编译context: path.resolve(__dirname, '../src'),cache: true, // 开启缓存cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), // 缓存文件存储的路径threads // 开启多进程})
],
c、压缩js 多核处理:
// 引入 js压缩 插件 -- 内置
const terserWebpackPlugin = require('terser-webpack-plugin')
module.exports = {plugins: [// new CssMinimizerPlugin(),// new terserWebpackPlugin({//     parallel: threads, // 开启多进程// })],optimization: { // 不在这里写的话,可以在 plugins 中写minimizer: [new CssMinimizerPlugin(),new terserWebpackPlugin({parallel: threads, // 开启多进程})],},
}

③ 完整代码:

webpack.prod.js
// 引入os模块
const os = require('os')
// 引入path模块
const path = require('path')
// 引入 eslint 插件
const ESLintPlugin = require('eslint-webpack-plugin');
// 引入 html资源引入 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 引入 提取css 的插件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 引入 css压缩 插件
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// 引入 js压缩 插件 -- 内置
const terserWebpackPlugin = require('terser-webpack-plugin')// 获取cpu的核数
const threads = os.cpus().length;// 封装样式打包代码
function getStyleLoader (otherPre) {return [MiniCssExtractPlugin.loader, // 将 css 文件打包为一个单独的文件'css-loader', // 将css资源编译成commonjs的模块化js{ // 需要配置就写成对象的形式,不需要配置就写成字符串的形式loader: 'postcss-loader',options: { // css 的兼容性处理配置postcssOptions: {plugins: [['postcss-preset-env',{// 其他选项},],],},},},otherPre].filter(Boolean)
}module.exports = {// 入口 - 相对路径(因为编译的时候,命令是从根目录下执行的,所以不用修改)entry: './src/main.js',// 输出output: {// 所有打包的资源输出的目录 - 绝对路径(打包的时候,是根据该文件进行定位的)path: path.resolve(__dirname,'../dist'), // 入口文件打包输出的名称filename: 'static/js/main.js',// 在打包前,会清空path目录中的所有内容,然后再进行打包 -- webpack5中使用// 如果是webpack4,则需要使用clean-webpack-plugin插件进行清空clean: true // 开发时不需要},// 加载器module: {rules: [{oneOf: [{test: /\.css$/i, // 匹配以.css结尾的文件use: getStyleLoader(), // loader的执行顺序是从后往前的},{test: /\.less$/i,use: getStyleLoader('less-loader')},{test: /\.s[ac]ss$/i,use: getStyleLoader('sass-loader')},{test: /\.styl$/i,use: getStyleLoader('stylus-loader')},{   // webpack4处理图片资源的方式:使用file-loader、url-loader。// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// url-loader将图片资源进行优化// webpack5处理图片资源的方式(file-loader、url-loader已经内置):test: /\.(png|jpe?g|svg|webp|gif)$/,type: 'asset',parser: {dataUrlCondition: {maxSize: 30 * 1024 // 小于30kb的图片会转为base64 - 减少请求数量,但是体积会变大}},generator: { // 打包的图片输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/images/[hash:10][ext][query]'}},{   // webpack4处理图片资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理图片资源的方式(file-loader已经内置):test: /\.(ttf|woff2?)$/,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/fonts/[hash:10][ext][query]'}},{   // webpack4处理其它资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理其它资源的方式(file-loader已经内置):test: /\.(mp3|MP4|avi|.doc)$/i,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [name]表示保留原始文件名filename: 'static/media/[hash:10][ext][query]'}},{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译// loader: 'babel-loader', // 只需要一个loader,不需要use// options: {//     cacheDirectory: true, // 开启babel缓存//     cacheCompression: false, // 不压缩缓存文件// }// use: {//     loader: 'babel-loader',//     options: { // 智能预设,这个对象可以不写,那么就需要在项目的根目录下新建babel.config.js,添加智能预设//         presets: ['@babel/preset-env'],//     },// },use: [{loader: 'thread-loader', // 开启多进程options: {// 产生的 worker 的数量,默认是 (cpu 核心数 - 1)workers: threads,}},{loader: 'babel-loader', // 只需要一个loader,不需要useoptions: {cacheDirectory: true, // 开启babel缓存cacheCompression: false, // 不压缩缓存文件}}]},]}]},optimization: { // 不在这里写的话,可以在 plugins 中写minimizer: [new CssMinimizerPlugin(),new terserWebpackPlugin({parallel: threads, // 开启多进程})],},// 插件plugins: [new ESLintPlugin({ // eslint检测的文件都有哪些exclude: "node_modules", // 默认值,排除哪些文件不需要编译context: path.resolve(__dirname, '../src'),cache: true, // 开启缓存cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), // 缓存文件存储的路径threads // 开启多进程}),new HtmlWebpackPlugin({ // 使用 html资源引入 插件,并且保留原模版template: path.resolve(__dirname, '../index.html')}),new MiniCssExtractPlugin({ // 将所有的css提取到一个单独的文件中filename: 'static/css/main.css'}),// new CssMinimizerPlugin(),// new terserWebpackPlugin({//     parallel: threads, // 开启多进程// })],// 模式mode: 'production',devtool: 'source-map'
}
webpack.dev.js
// 引入os模块
const os = require('os')
// 引入path模块
const path = require('path')
// 引入 eslint 插件
const ESLintPlugin = require('eslint-webpack-plugin');
// 引入 html资源引入 插件
const HtmlWebpackPlugin = require('html-webpack-plugin');// 获取cpu的核数
const threads = os.cpus().length;module.exports = {// 入口 - 相对路径(因为编译的时候,命令是从根目录下执行的,所以不用修改)entry: './src/main.js',// 输出output: {// 所有打包的资源输出的目录 - 绝对路径(打包的时候,是根据该文件进行定位的)// path: path.resolve(__dirname, '../dist'), path: undefined, // 开发模式不会输出文件// 入口文件打包输出的名称filename: 'static/js/main.js',// 在打包前,会清空path目录中的所有内容,然后再进行打包 -- webpack5中使用// 如果是webpack4,则需要使用clean-webpack-plugin插件进行清空// clean: true // 开发时不需要},// 加载器module: {rules: [{   // 当规则匹配时,只使用第一个匹配规则oneOf: [{test: /\.css$/i, // 匹配以.css结尾的文件use: ['style-loader', // 将js中的css通过style标签的形式添加到html中'css-loader' // 将css资源编译成commonjs的模块化js], // loader的执行顺序是从后往前的},{test: /\.less$/i,use: ['style-loader','css-loader','less-loader', // 将less文件编译为css文件],},{test: /\.s[ac]ss$/i,use: [// 将 JS 字符串生成为 style 节点'style-loader',// 将 CSS 转化成 CommonJS 模块'css-loader',// 将 Sass 编译成 CSS'sass-loader',],},{test: /\.styl$/i,use: ['style-loader','css-loader','stylus-loader', // 将stylus文件编译为css文件],},{   // webpack4处理图片资源的方式:使用file-loader、url-loader。// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// url-loader将图片资源进行优化// webpack5处理图片资源的方式(file-loader、url-loader已经内置):test: /\.(png|jpe?g|svg|webp|gif)$/,type: 'asset',parser: {dataUrlCondition: {maxSize: 30 * 1024 // 小于30kb的图片会转为base64 - 减少请求数量,但是体积会变大}},generator: { // 打包的图片输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/images/[hash:10][ext][query]'}},{   // webpack4处理图片资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理图片资源的方式(file-loader已经内置):test: /\.(ttf|woff2?)$/,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [hash:10]表示只保留名称的前10位filename: 'static/fonts/[hash:10][ext][query]'}},{   // webpack4处理其它资源的方式:使用file-loader// file-loader将文件资源编译为webpack识别的资源原封不动的进行输出。// webpack5处理其它资源的方式(file-loader已经内置):test: /\.(mp3|MP4|avi|.doc)$/i,type: 'asset/resource', // 只会对文件原封不动的输出,不会转为base64generator: { // 打包的字体输出的目录// [name]表示保留原始文件名filename: 'static/media/[hash:10][ext][query]'}},{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译// loader: 'babel-loader', // 只需要一个loader,不需要use// // use: {// //     loader: 'babel-loader',// //     options: { // 智能预设,这个对象可以不写,那么就需要在项目的根目录下新建babel.config.js,添加智能预设// //         presets: ['@babel/preset-env'],// //     },// // },use: [{loader: 'thread-loader', // 开启多进程options: {// 产生的 worker 的数量,默认是 (cpu 核心数 - 1)workers: threads,}},{loader: 'babel-loader', // 只需要一个loader,不需要useoptions: {cacheDirectory: true, // 开启babel缓存cacheCompression: false, // 不压缩缓存文件}}]}]}]},// 插件plugins: [new ESLintPlugin({ // eslint检测的文件都有哪些exclude: "node_modules", // 默认值,排除哪些文件不需要编译context: path.resolve(__dirname, '../src'),cache: true, // 开启缓存cacheLocation: path.resolve(__dirname, '../node_modules/.cache/eslintcache'), // 缓存文件存储的路径threads // 开启多进程}),new HtmlWebpackPlugin({ // 使用 html资源引入 插件,并且保留原模版template: path.resolve(__dirname, '../index.html')})],// 开发服务器:不会输出资源,在内存中编译打包devServer: {host: 'localhost', // 启动服务器的域名port: '3001', // 启动服务器的端口号open: true, // 是否自动打开浏览器hot: true, // 开启 HMR(默认值)},// 模式mode: 'development',devtool: 'cheap-module-source-map'
}

四、减少代码体积:

1、第三方工具库引用:Tree shaking

① 定义:

用于移除 JavaScript 中的没有使用的代码。

注意:它依赖 ES Module

② 使用:

Webpack 已经默认开启了这个功能,无需其他配置,

2、Babel编译时代码重复插入:@babel/plugin-transform-runtime

中文文档:https://webpack.docschina.org/loaders/babel-loader/#babel-is-injecting-helpers-into-each-file-and-bloating-my-code

① 定义:

禁用了 Babel 自动对每个文件的 runtime 注入。将辅助代码作为一个独立模块,保存在@babel/plugin-transform-runtime中,需要的时候从@babel/plugin-transform-runtime 进行引入。

② 下载包:

npm install -D @babel/plugin-transform-runtime

③ 使用:

module.exports = {// 加载器module: {rules: [{oneOf: [{test: /\.js$/,// exclude: /(node_modules)/, // 排除哪些文件不需要编译include: path.resolve(__dirname, '../src'), // 哪些文件需要编译use: [{loader: 'thread-loader', // 开启多进程options: {// 产生的 worker 的数量,默认是 (cpu 核心数 - 1)workers: threads,}},{loader: 'babel-loader', // 只需要一个loader,不需要useoptions: {cacheDirectory: true, // 开启babel缓存cacheCompression: false, // 不压缩缓存文件plugins: ['@babel/plugin-transform-runtime'], // 减少代码体积}}]},]}]}
}

五、优化代码运行性能:

http://www.dtcms.com/a/274385.html

相关文章:

  • OpenAvatarChat数字人项目结构分析
  • 星云穿越与超光速飞行特效的前端实现原理与实践
  • 第三章 隧道与轨道交通工程 3.8 安全质量控制
  • 排序算法(一):冒泡排序
  • UniApp 生命周期详解:从启动到销毁的完整指南
  • 如何快速掌握WeNet:从零到一的端到端语音识别学习指南
  • SSRF11 各种限制绕过之DNS rebinding 绕过内网 ip 限制
  • FREERTOS根本不能使用连续接收串口思想
  • C语言的程序控制语句
  • 多态 使用场景
  • 【构建Tomcat版本检查工具:自动检测并提醒版本更新】
  • 云、实时、时序数据库混合应用:医疗数据管理的革新与展望(中)
  • 解决Linux绑定失败地址已使用(端口被占用)的问题
  • day050-ansible剧本与变量
  • 云暴露面分析完整指南
  • 2025年7月11日—基础算法—高精度
  • 删除mysql文件夹时显示在另一程序中打开
  • 期权交易完整版教程简介
  • 工具分享--IP与域名提取工具
  • YOLOv13来了!基于超图增强的自适应视觉感知实时目标检测
  • 数据结构第一章复杂度的认识
  • WebSocket 重连与心跳机制:打造坚如磐石的实时连接
  • 005---Xilinx Viivado FIFO (二)---fifo IP核使用总结
  • python之set详谈
  • 大数据驱动的酒店用品需求预测模型研究 开发——毕业论文,毕业设计——仙盟创梦IDE
  • Linux驱动基本概念(内核态、用户态、模块、加载、卸载、设备注册、字符设备)
  • linux文件系统目录结构以及交互界面
  • 稳定币将成为新时代的重要金融工具
  • Pandas:数据类型转换
  • c99-柔性数组