【前端webpack5高级优化】提升打包构建速度几种优化方案

本文主要是介绍【前端webpack5高级优化】提升打包构建速度几种优化方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HotModuleReplacement(HMR/热模块替换)

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

所以我们需要做到修改某个模块代码,就只有这个模块代码需要重新打包编译,其他模块不变,这样打包速度就能很快

使用HotModuleReplacement(HMR/热模块替换):在程序运行中,替换、添加或删除模块,而无需重新加载整个页面

使用流程

1.基本配置

module.exports = {// 其他省略devServer: {host: "localhost", // 启动服务器域名port: "3000", // 启动服务器端口号open: true, // 是否自动打开浏览器hot: true, // 开启HMR功能(只能用于开发环境,生产环境不需要了)},
};

此时 css 样式经过 style-loader 处理,已经具备 HMR 功能了。 但是 js 还不行

2.js配置

// main.js
import count from "./js/count";
import sum from "./js/sum";
// 引入资源,Webpack才会对其打包
import "./css/iconfont.css";
import "./css/index.css";
import "./less/index.less";
import "./sass/index.sass";
import "./sass/index.scss";
import "./styl/index.styl";const result1 = count(2, 1);
console.log(result1);
const result2 = sum(1, 2, 3, 4);
console.log(result2);// 判断是否支持HMR功能
if (module.hot) {module.hot.accept("./js/count.js", function (count) {const result1 = count(2, 1);console.log(result1);});module.hot.accept("./js/sum.js", function (sum) {const result2 = sum(1, 2, 3, 4);console.log(result2);});
}

上面这样写会很麻烦,所以实际开发我们会使用其他loader来解决。

比如:vue-loader, react-hot-loader


OneOf

打包时每个文件都会经过所有loader处理,虽然因为 test 正则原因实际没有处理上,但是都要过一遍,比较慢

使用OneOf:顾名思义就是只能匹配上一个 loader, 剩下的就不匹配了

使用流程

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: "./src/main.js",output: {path: undefined, // 开发模式没有输出,不需要指定输出目录filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中// clean: true, // 开发模式没有输出,不需要清空输出结果},module: {rules: [{oneOf: [{// 用来匹配 .css 结尾的文件test: /\.css$/,// use 数组里面 Loader 执行顺序是从右到左use: ["style-loader", "css-loader"],},{test: /\.less$/,use: ["style-loader", "css-loader", "less-loader"],},{test: /\.s[ac]ss$/,use: ["style-loader", "css-loader", "sass-loader"],},{test: /\.styl$/,use: ["style-loader", "css-loader", "stylus-loader"],},{test: /\.(png|jpe?g|gif|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, // 小于10kb的图片会被base64处理},},generator: {// 将图片文件输出到 static/imgs 目录中// 将图片文件命名 [hash:8][ext][query]// [hash:8]: hash值取8位// [ext]: 使用之前的文件扩展名// [query]: 添加之前的query参数filename: "static/imgs/[hash:8][ext][query]",},},{test: /\.(ttf|woff2?)$/,type: "asset/resource",generator: {filename: "static/media/[hash:8][ext][query]",},},{test: /\.js$/,exclude: /node_modules/, // 排除node_modules代码不编译loader: "babel-loader",},],},],},plugins: [new ESLintWebpackPlugin({// 指定检查文件的根目录context: path.resolve(__dirname, "../src"),}),new HtmlWebpackPlugin({// 以 public/index.html 为模板创建文件// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源template: path.resolve(__dirname, "../public/index.html"),}),],// 开发服务器devServer: {host: "localhost", // 启动服务器域名port: "3000", // 启动服务器端口号open: true, // 是否自动打开浏览器hot: true, // 开启HMR功能},mode: "development",devtool: "cheap-module-source-map",
};

Include/Exclude

开发时我们需要使用第三方的库或插件,所有文件都下载到 node_modules 中了。而这些文件是不需要编译可以直接使用的。

所以我们在对js文件处理时,要排除 node_modules 下面的文件

使用Include/Exclude

include
包含,只处理 xxx 文件

exclude
排除,除了 xxx 文件以外其他文件都处理

使用流程

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: "./src/main.js",output: {path: undefined, // 开发模式没有输出,不需要指定输出目录filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中// clean: true, // 开发模式没有输出,不需要清空输出结果},module: {rules: [{oneOf: [{// 用来匹配 .css 结尾的文件test: /\.css$/,// use 数组里面 Loader 执行顺序是从右到左use: ["style-loader", "css-loader"],},{test: /\.less$/,use: ["style-loader", "css-loader", "less-loader"],},{test: /\.s[ac]ss$/,use: ["style-loader", "css-loader", "sass-loader"],},{test: /\.styl$/,use: ["style-loader", "css-loader", "stylus-loader"],},{test: /\.(png|jpe?g|gif|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, // 小于10kb的图片会被base64处理},},generator: {// 将图片文件输出到 static/imgs 目录中// 将图片文件命名 [hash:8][ext][query]// [hash:8]: hash值取8位// [ext]: 使用之前的文件扩展名// [query]: 添加之前的query参数filename: "static/imgs/[hash:8][ext][query]",},},{test: /\.(ttf|woff2?)$/,type: "asset/resource",generator: {filename: "static/media/[hash:8][ext][query]",},},{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, "../src"), // 也可以用包含loader: "babel-loader",},],},],},plugins: [new ESLintWebpackPlugin({// 指定检查文件的根目录context: path.resolve(__dirname, "../src"),exclude: "node_modules", // 默认值}),new HtmlWebpackPlugin({// 以 public/index.html 为模板创建文件// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源template: path.resolve(__dirname, "../public/index.html"),}),],// 开发服务器devServer: {host: "localhost", // 启动服务器域名port: "3000", // 启动服务器端口号open: true, // 是否自动打开浏览器hot: true, // 开启HMR功能},mode: "development",devtool: "cheap-module-source-map",
};

Cache

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

我们可以缓存之前的 Eslint 检查 和Babel编译结果,这样第二次打包时速度就会更快了

使用Cache : 对Eslint检查 和Babel编译结果进行缓存

使用流程

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: "./src/main.js",output: {path: undefined, // 开发模式没有输出,不需要指定输出目录filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中// clean: true, // 开发模式没有输出,不需要清空输出结果},module: {rules: [{oneOf: [{// 用来匹配 .css 结尾的文件test: /\.css$/,// use 数组里面 Loader 执行顺序是从右到左use: ["style-loader", "css-loader"],},{test: /\.less$/,use: ["style-loader", "css-loader", "less-loader"],},{test: /\.s[ac]ss$/,use: ["style-loader", "css-loader", "sass-loader"],},{test: /\.styl$/,use: ["style-loader", "css-loader", "stylus-loader"],},{test: /\.(png|jpe?g|gif|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, // 小于10kb的图片会被base64处理},},generator: {// 将图片文件输出到 static/imgs 目录中// 将图片文件命名 [hash:8][ext][query]// [hash:8]: hash值取8位// [ext]: 使用之前的文件扩展名// [query]: 添加之前的query参数filename: "static/imgs/[hash:8][ext][query]",},},{test: /\.(ttf|woff2?)$/,type: "asset/resource",generator: {filename: "static/media/[hash:8][ext][query]",},},{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, "../src"), // 也可以用包含loader: "babel-loader",options: {cacheDirectory: true, // 开启babel编译缓存cacheCompression: false, // 缓存文件不要压缩},},],},],},plugins: [new ESLintWebpackPlugin({// 指定检查文件的根目录context: path.resolve(__dirname, "../src"),exclude: "node_modules", // 默认值cache: true, // 开启缓存// 缓存目录cacheLocation: path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),}),new HtmlWebpackPlugin({// 以 public/index.html 为模板创建文件// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源template: path.resolve(__dirname, "../public/index.html"),}),],// 开发服务器devServer: {host: "localhost", // 启动服务器域名port: "3000", // 启动服务器端口号open: true, // 是否自动打开浏览器hot: true, // 开启HMR功能},mode: "development",devtool: "cheap-module-source-map",
};

Thead

当项目越来越庞大时,打包速度越来越慢,甚至于需要一个下午才能打包出来代码。这个速度是比较慢的。

我们想要继续提升打包速度,其实就是要提升js的打包速度,因为其他文件都比较少。

而对 js 文件处理主要就是 eslintbabelTerser 三个工具,所以我们要提升它们的运行速度。

我们可以开启多进程同时处理 js 文件,这样速度就比之前的单进程打包更快了

使用Thead 多进程打包:开启电脑的多个进程同时干一件事,速度更快。

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

使用流程

我们启动进程的数量就是我们 CPU 的核数

1.如何获取 CPU 的核数,因为每个电脑都不一样

// nodejs核心模块,直接使用
const os = require("os");
// cpu核数
const threads = os.cpus().length;

2.下载包

npm i thread-loader -D

3.使用

const os = require("os");
const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");// cpu核数
const threads = os.cpus().length;// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {return [MiniCssExtractPlugin.loader,"css-loader",{loader: "postcss-loader",options: {postcssOptions: {plugins: ["postcss-preset-env", // 能解决大多数样式兼容性问题],},},},preProcessor,].filter(Boolean);
};module.exports = {entry: "./src/main.js",output: {path: path.resolve(__dirname, "../dist"), // 生产模式需要输出filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中clean: true,},module: {rules: [{oneOf: [{// 用来匹配 .css 结尾的文件test: /\.css$/,// use 数组里面 Loader 执行顺序是从右到左use: getStyleLoaders(),},{test: /\.less$/,use: getStyleLoaders("less-loader"),},{test: /\.s[ac]ss$/,use: getStyleLoaders("sass-loader"),},{test: /\.styl$/,use: getStyleLoaders("stylus-loader"),},{test: /\.(png|jpe?g|gif|webp)$/,type: "asset",parser: {dataUrlCondition: {maxSize: 10 * 1024, // 小于10kb的图片会被base64处理},},generator: {// 将图片文件输出到 static/imgs 目录中// 将图片文件命名 [hash:8][ext][query]// [hash:8]: hash值取8位// [ext]: 使用之前的文件扩展名// [query]: 添加之前的query参数filename: "static/imgs/[hash:8][ext][query]",},},{test: /\.(ttf|woff2?)$/,type: "asset/resource",generator: {filename: "static/media/[hash:8][ext][query]",},},{test: /\.js$/,// exclude: /node_modules/, // 排除node_modules代码不编译include: path.resolve(__dirname, "../src"), // 也可以用包含use: [{loader: "thread-loader", // 开启多进程options: {workers: threads, // 数量},},{loader: "babel-loader",options: {cacheDirectory: true, // 开启babel编译缓存},},],},],},],},plugins: [new ESLintWebpackPlugin({// 指定检查文件的根目录context: path.resolve(__dirname, "../src"),exclude: "node_modules", // 默认值cache: true, // 开启缓存// 缓存目录cacheLocation: path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),threads, // 开启多进程}),new HtmlWebpackPlugin({// 以 public/index.html 为模板创建文件// 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源template: path.resolve(__dirname, "../public/index.html"),}),// 提取css成单独文件new MiniCssExtractPlugin({// 定义输出文件名和目录filename: "static/css/main.css",}),// css压缩// new CssMinimizerPlugin(),],optimization: {minimize: true,minimizer: [// css压缩也可以写到optimization.minimizer里面,效果一样的new CssMinimizerPlugin(),// 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了new TerserPlugin({parallel: threads // 开启多进程})],},// devServer: {//   host: "localhost", // 启动服务器域名//   port: "3000", // 启动服务器端口号//   open: true, // 是否自动打开浏览器// },mode: "production",devtool: "source-map",
};

这篇关于【前端webpack5高级优化】提升打包构建速度几种优化方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/875938

相关文章

电脑找不到mfc90u.dll文件怎么办? 系统报错mfc90u.dll丢失修复的5种方案

《电脑找不到mfc90u.dll文件怎么办?系统报错mfc90u.dll丢失修复的5种方案》在我们日常使用电脑的过程中,可能会遇到一些软件或系统错误,其中之一就是mfc90u.dll丢失,那么,mf... 在大部分情况下出现我们运行或安装软件,游戏出现提示丢失某些DLL文件或OCX文件的原因可能是原始安装包

电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案

《电脑显示mfc100u.dll丢失怎么办?系统报错mfc90u.dll丢失5种修复方案》最近有不少兄弟反映,电脑突然弹出“mfc100u.dll已加载,但找不到入口点”的错误提示,导致一些程序无法正... 在计算机使用过程中,我们经常会遇到一些错误提示,其中最常见的就是“找不到指定的模块”或“缺少某个DL

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

JAVA保证HashMap线程安全的几种方式

《JAVA保证HashMap线程安全的几种方式》HashMap是线程不安全的,这意味着如果多个线程并发地访问和修改同一个HashMap实例,可能会导致数据不一致和其他线程安全问题,本文主要介绍了JAV... 目录1. 使用 Collections.synchronizedMap2. 使用 Concurren

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

mysql中的group by高级用法

《mysql中的groupby高级用法》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,下面给大家介绍mysql中的groupby用法... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2

将Java程序打包成EXE文件的实现方式

《将Java程序打包成EXE文件的实现方式》:本文主要介绍将Java程序打包成EXE文件的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录如何将Java程序编程打包成EXE文件1.准备Java程序2.生成JAR包3.选择并安装打包工具4.配置Launch4

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M