1.webpack5对比webpack4做了哪些优化
Webpack 5 对比Webpack 4 存在一些重要的优化。Webpack 5 在性能、构建速度、Tree Shaking 等方面都有所改进:
-
性能改进:
- Webpack 5 在构建速度和性能方面有所提升。这主要是通过改进缓存策略、优化构建算法以及增强的持久化缓存等方式实现的。这意味着更快的构建时间和更高的整体性能。
-
支持Tree Shaking:
- 在 Webpack 5 中,Tree Shaking(树摇)机制得到了改进,这意味着它更有效地识别和删除未使用的代码,以减小最终构建的文件大小。
-
对ES6模块和JSON模块的优化:
- Webpack 5 对于 ES6 模块和 JSON 模块的处理更加智能和优化,从而提高了构建速度。
-
默认持久化缓存:
- Webpack 5 默认启用了持久化缓存,这意味着构建过程中的中间结果会被缓存,以便在后续的构建中重复使用,进而加快构建速度。
-
改进的 Tree Shaking 算法:
- Webpack 5 中对 Tree Shaking 算法进行了改进,使其更加精确和高效,从而能够更好地识别和删除未使用的代码。
-
内置的模块类型优化:
- Webpack 5 提供了一种新的模块类型------
module.type
,可以通过配置文件进行设置,以便更好地与不同的目标环境进行兼容和优化。
- Webpack 5 提供了一种新的模块类型------
2.webpack5的核心原理
Webpack 5 的核心原理涉及了模块化、依赖分析、打包优化等多个方面。下面是Webpack 5 的核心原理的概述:
-
模块化:
- Webpack 5 将项目中的各个文件视为模块,这些模块可以是 JavaScript 文件、CSS 文件、图片、字体等各种资源。它使用模块化的思想来管理这些文件,使得项目的各个部分可以相互依赖、独立开发和测试。
-
依赖分析:
- 在构建过程中,Webpack 5 会对项目中的模块进行依赖分析,即分析模块之间的依赖关系。通过识别模块之间的 import、require 等语句,Webpack 能够确定模块之间的依赖关系,从而构建出一个依赖关系图,这也是 Webpack 5 能够正确地打包项目中所有依赖的基础。
-
打包优化:
- Webpack 5 会根据依赖关系图进行打包优化。这包括但不限于:
- Tree Shaking:删除项目中未使用的代码,以减小打包后的文件大小。
- 代码分割:将项目代码拆分为多个块,按需加载,从而提高页面加载速度。
- 持久化缓存:通过缓存构建过程中的中间结果,减少重复工作,提高构建速度。
- 多线程构建:利用多线程或者多进程来并行处理模块,加快构建速度。
- 模块类型优化:根据目标环境,优化模块类型,提高兼容性和执行效率。
- 自动刷新:在开发过程中,Webpack 5 会监视文件的变化,并实时更新构建结果,提供热更新功能。
- Webpack 5 会根据依赖关系图进行打包优化。这包括但不限于:
-
插件系统:
- Webpack 5 提供了丰富的插件系统,允许开发者通过插件来扩展和定制 Webpack 的功能。通过插件系统,开发者可以在打包过程的各个阶段介入,实现自定义的功能,比如代码压缩、资源优化、文件拷贝等。
-
编译器和解析器:
- Webpack 5 内部包含了编译器和解析器,用于将项目中的源代码转换为可执行的 JavaScript 代码。编译器负责将各种类型的模块转换为标准的 JavaScript 代码,解析器负责解析 JavaScript 代码中的语法,构建 AST(抽象语法树),以便后续的依赖分析和打包优化。
Webpack 5 的核心原理包括模块化、依赖分析、打包优化、插件系统以及编译器和解析器等多个方面,它通过这些机制来实现对项目代码的打包和优化,从而提供了高效、灵活的前端构建解决方案。
3.webpack5实践-常用API
在webpack配置文件webpack.config.js
中,下面介绍一些必需要掌握的api:
1. entry
(入口)
Webpack 5 的入口配置指定了打包的起始点。可以是一个单一的入口或多个入口。下面举例单一入口代码:
javascript
module.exports = {
entry: './src/index.js'
};
搞懂了后,后面我再继续探索多入口,由浅入深,举一反三,加油!!!
2. output
(输出)
output 配置项指定了打包后的文件输出的位置和文件名等信息。
javascript
module.exports = {
output: {
filename: 'bundle.js', //打包后生成js文件名
path: path.resolve(__dirname, 'dist')。 //js文件在dist目录里头
}
};
3. devServer
(开发服务器)
devServer 配置项用于配置开发服务器,提供了许多有用的功能,如自动刷新、热模块替换等。
javascript
module.exports = {
devServer: {
contentBase: './dist', //项目打包后生成文件的目录名
port: 8080, //本地运行的端口号
hot: true。//是否开启热更新
}
};
4. mode
(模式)
mode 配置项指定了当前构建的环境,可选值有 'development':开发模式、'production' :生产环境和 'none' 。
javascript
module.exports = {
mode: 'development' //
};
5. module
(模块)
module 配置项用于配置不同类型模块的处理规则,例如配置 loader。
javascript
module.exports = {
module: {
rules: [
{
//.js文件loader
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false
}
}
},
{
//.vue文件loader
test: /\.vue$/,
use: 'vue-loader'
},
{
//.css文件loader
test: /\.css$/,
use: [isProduction ? MiniCssExtractPlugin.loader : 'vue-style-loader', 'css-loader']
},
{ //图片
test: /\.(png|svg|jpg|jpeg|gif|bmp|ico)$/,
type: 'asset/resource',
generator:{
filename: 'image/[contenthash:10].[ext]',
},
},
{ //视频或者文件在这里配置
test: /\.(mp4|ttf)$/,
use: {
loader: 'file-loader',
options: {
name: 'video/[contenthash:10].[ext]',
},
},
},
]
}
};
6. resolve
(解析)
resolve 配置项用于配置模块解析的规则。
javascript
module.exports = {
resolve: {
extensions: ['.js', '.jsx','vue'],
alias: {
'@': path.resolve(__dirname, 'src/')
}
}
};
7. optimization
(优化)
optimization 配置项用于配置打包优化相关的选项,可以用第三方插件对js文件进行分包和压缩,减少包的体积。
javascript
const ESBuildPlugin = require('esbuild-webpack-plugin').default;
module.exports = {
optimization: {
minimizer: [new ESBuildPlugin()],
splitChunks: {
cacheGroups: {
defaultVendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
}
},
};
8. plugins
(插件)
plugins 配置项用于配置各种 webpack 插件。
javascript
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const {VueLoaderPlugin} = require('vue-loader');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require('path');
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
plugins: [
new VueLoaderPlugin(), //在 webpack 中,需要使用 vue-loader 来处理 Vue.js 单文件组件。VueLoaderPlugin 插件的作用是向 webpack 中添加必要的 loader 配置,以确保 vue-loader 能够正确地解析和加载 Vue.js 单文件组件。同理,用react框架的也可以用同样的方式配置react的loader
new HtmlWebpackPlugin({ // webpack 中生成 HTML 文件的插件
template: 'index.html',//自动创建一个 HTML 文件
minify: {
collapseWhitespace: true, //去掉空格
removeComments: true, //删除注释
removeAttributeQuotes: true, //删除双引号
removeEmptyAttributes: true, //删除声明了但是没赋值的属性 let a;
minifyCSS: true, //压缩css
minifyJS: true, //压缩js
minifyURLs: true,//是否对 HTML 文件中的 URL 进行最小化处理
removeTagWhitespace: true,//是否移除 HTML 标签之间的空白字符
},
favicon: path.resolve('favicon.ico') //配置icon图标
}),
isProduction ?new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css', //生成css文件路径和名字
chunkFilename: 'css/[name].[contenthash:8].chunk.css', //生成css的chunkFilename 文件路径和名
}): null,//将 CSS 提取为独立文件的插件
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: false,
__VUE_PROD_DEVTOOLS__: false,
}),//定义全局常量的插件。它允许你在编译时创建全局常量,这些常量在编译过程中会被替换为实际的值。这在配置 webpack 打包过程中经常用于传递环境变量或者其他常量。
new CleanWebpackPlugin(), //每次打包前清理旧的编译文件
].filter(Boolean)
};
以上是 Webpack 5 中一些常用配置项的用法,它们可以组合使用项目的需求,搞懂以后,基本上一些中小型项目的框架搭建和打包可以轻松玩转。
4.高级自定义玩转webpack5
如果,简单的webpack5框架无法满足你项目的业务需求,下面我们可以配置一些高级玩法,比如, 配置多入口文件,搭载多页面应用,多页面应用利于SEO,在上述代码文件webpack.config.js
的基础上,新增文件webpack.util.js
配置自定义入口,
javascript
const glob = require('glob');
const HtmlWebpackPlugin = require('html-webpack-plugin');
function setEntry() {
const files = glob.sync('./src/pages/**/index.js') //多文件入口的路径
const entry = {}
files.forEach(file => {
const ret = file.match(/^\.\/src\/pages\/(\S*)\/index\.js$/)
if (ret) {
entry[ret[1]] = {
import: file,
dependOn: 'vue_vendors',
}
}
})
// 拆分vue依赖
entry['vue_vendors'] = {
import: ['vue'],
filename: 'commom/[name].js'
}
return entry
}
function getTemplate() {
const files = glob.sync(`./src/index.html`)
return files[0]
}
function setHtmlPlugin() {
const files = glob.sync('./src/pages/**/index.js')
const options = []
files.forEach(file => {
const ret = file.match(/^\.\/src\/pages\/(\S*)\/index\.js$/)
if (ret) {
const name = ret[1]
if(name === 'home'){
options.push(new HtmlWebpackPlugin({
filename: 'index.html',
template: getTemplate(),
title: name,
minify: {
collapseWhitespace: false,
removeComments: true,
},
chunks: ['vue_vendors',name]
}))
}
options.push(new HtmlWebpackPlugin({
filename: `${name}.html`,
template: getTemplate(),
title: name,
minify: {
collapseWhitespace: false,
removeComments: true,
},
chunks: ['vue_vendors',name]
}))
}
})
return options
}
module.exports = {
setEntry,
setHtmlPlugin
}
然后再webpack.config.js
文件中引入webpack.util.js
文件的方法
javascript
const { setEntry,setHtmlPlugin } = require('./webpack.util.js')
module.exports = () => {
return {
...
entry: setEntry,//引入自定义入口文件的方法
plugins: [
...setHtmlPlugin(), //引入自定义设置html的方法
//plugins中的剩余代码同上
].filter(Boolean)
}
}
此外,如果需要自定义区分生产环境和开发环境,也可以新增两个不同的webpack
配置文件,区分两个不同的环境,这种情况一般在大型项目中比较常用,举个简单的例子:
- 在开发环境
webpack.dev.js
中
javascript
const config = require('./webpack.config.js')
module.exports = Object.assign({}, config, {
mode: "development",
devtool: 'inline-source-map',
devServer: {
open: true,
hot: true,
port: 8000,
static: "./public",
historyApiFallback: true,
//proxy: {
// '/': {
// target: 'http://127.0.0.1',
// pathRewrite:{'^/':'/'},
// secure: false,
// changeOrigin: true,
// },
//}
},
...
})
- 在生产环境
webpack.prod.js
中配置
javascript
const config = require('./webpack.config.js')
module.exports = Object.assign({}, config, {
mode: "production",
devtool: false,
...
})
最后,在package.json
文件中分别设置两个不同环境的启动方式:
javascript
{
"name": "webpack5",
"version": "1.0.0",
"description": "搭建webpack5框架",
"main": "webpack.config.js",
"scripts": {
"build": "webpack --config webpack.prod.js --mode production", //生产环境
"start": "webpack serve --config ./webpack.dev.js --mode development", //开发环境
"test": "echo \"Error: no test specified\" && exit 1" //暂无测试环境,可根据自己的业务配置
},
"keywords": [],
"author": "高级架构师",
"license": "ISC",
"dependencies": {
"clean-webpack-plugin": "^4.0.0",
"element-plus": "^2.4.2",
"esbuild-webpack-plugin": "^1.1.0",
"vue": "3.2.26",
},
"devDependencies": {
"@babel/core": "^7.23.3",
"@babel/plugin-transform-runtime": "^7.23.4",
"@babel/preset-env": "^7.23.3",
"babel-loader": "^9.1.3",
"html-webpack-plugin": "^5.5.3",
"mini-css-extract-plugin": "^2.7.6",
"vue-loader": "^17.3.1",
"vue-style-loader": "^4.1.3",
"webpack": "^5.89.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1"
}
}
我们想启动开发环境:npm run dev
,线上环境:npm run build
最后也是本文最重要的,码字不易,我会持续输出前端技术干货,欢迎点赞关注加收藏,你的鼓励是我持之以恒码字的动力,感谢!!!