高级也便是相对于基础的优化。从以下视点进行优化:
提高开发体会;
提高打包构建速度
削减代码体积
优化代码运转功用
提高开发体会
SourceMap
为什么
SourceMap用来生成源代码与与构建后的代码–映射的文件的计划。
Source map能够理解为一个地图, 经过它能够获知编译后的代码 对应编译前的代码位置。这样当代码遇到异常, 咱们就能够经过报错信息定位至精确的位置。 一起在浏览器 sources 也能够查看到源码。
是什么
开发形式
- cheap-module-source-map
长处:打包编译速度快,只包括行映射
缺陷:无列映射
怎样用
在开发形式下装备
devtool:"cheap-module-source-map"
出产形式
- source-map
长处:包括队伍映射
缺陷:打包编译速度慢
在出产形式下装备
devtool:"source-map"
提高打包构建速度
Hot Module Replacement 热模块替换
为什么
咱们在修正代码的时分,只修正了一个模块,webpack会默许把一切模块从头打包一遍。可是咱们只想把修正的模块从头打包,提高速度。
是什么
Hot Module Replacement 热模块替换
怎样用
经过在devServer设置hot:true
devServer:{
host:"localhost", //发动服务器的域名
port:"3000", //发动服务器端口号
open:true, //是否主动打开浏览器
hot:true, //打开hmr
},
js运用hml,在main.js中设置
if(module.hot){
//判断是否支持热模块功用
module.hot.accept("./js/count")
module.hot.accept("./js/sum")
}
oneOf
每个文件只能被一个loader处理
rules: [
{
oneOf: [ //每个文件只能被其中一个loader处理
{ test: /\.css$/, 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", "less-loader"] },
{
test: /\.(png|jpe?g|gif|webp)$/,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
},
},
generator: {
//输出文件名称,10代表hash值只取前10位
filename: "static/images/[hash:10][ext][query]",
},
},
{
test: /\.(ttf|woff?2|)$/,
type: "asset/resource",
generator: {
//输出名称,10代表hash值只取前10位
filename: "static/media/[hash:10][ext][query]",
},
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
},
],
Include和Exclude
为什么
开发时咱们需求运用第三方库和插件,一切文件都下载到node_modules中了,而这些文件是不需求编译直接运用的。所以咱们在对js文件进行处理时,要扫除node_modules中的文件。
是什么
include:包括,只处理xxx文件
exclude:扫除,扫除xxx文件以外的文件都处理
怎样用
exclude和include只运用一个
{
test: /\.js$/,
exclude: /node_modules/, //扫除node_modules,其他都处理
// include:path.resolve(__dirname,"./src"), //只处理src下的文件,其他不处理
loader: "babel-loader",
},
Cache
为什么
每次打包都需求经过eslint查看和babel编译,速度比较慢
咱们能够缓存之前的eslint查看和babel编译成果,这样二次打包的速度就更快了
是什么
对eslint查看和babel编译进行缓存
怎样做
{
test: /\.js$/,
exclude: /node_modules/, //扫除node_modules,其他都处理
// include:path.resolve(__dirname,"./src"), //只处理src下的文件,其他不处理
loader: "babel-loader",
options:{
cacheDirectory:true, //敞开babel缓存
cacheCompression:false,//封闭缓存文件紧缩
}
},
测验:打包完成后在node_modules中增加了cache的文件
Thead多进程
为什么
当项目越来越庞大时,打包速度越来越慢,甚至于需求一个下午才干打包出来代码。这个速度是比较慢的。
咱们想要继续提高打包速度,其实便是要提高 js 的打包速度,因为其他文件都比较少。
咱们能够敞开多进程一起处理 js 文件,这样速度就比之前的单进程打包更快了。
是什么
多进程打包:敞开电脑的多个进程一起干一件事,速度更快。
需求留意:请仅在特别耗时的操作中运用,因为每个进程发动就有大约为 600ms 左右开销。
怎样用
下载包
npm i thread-loader -D
在webpack.prod.js获取cpu核数
// nodejs中心模块,直接运用
const os = require("os");
// cpu核数
const threads = os.cpus().length;
//TerserPlugin webpack自带紧缩js
const TerserPlugin = require("terser-webpack-plugin");
装备出产环境
use: [
{
loader:"thread-loader", //敞开多进程
options: {
workers: threads, //敞开个进程数量
},
},
{
loader: "babel-loader",
options: {
cacheDirectory: true, //敞开babel缓存
cacheCompression: false, //封闭缓存文件紧缩
},
},
],
plugins: [
// 紧缩js 当出产形式会默许敞开TerserPlugin,可是咱们需求进行其他装备,就要从头写了
new TerserPlugin({
parallel: threads // 敞开多进程
})
],
optimization
对打包成果进行优化,放置紧缩操作
const TerserWebpackPlugin = require("terser-webpack-plugin");
optimization: {
minimizer: [
new TerserPlugin({
parallel: threads, // 敞开多进程
}),
//紧缩css
new CssMinimizerPlugin(),
],
},
开发环境装备同上
削减代码体积
tree-shaking
为什么
开发时咱们引用一些东西库或第三方组件库,如果没有特殊处理,咱们打包时会引进整个库,体积太大。
是什么
tree-shaking用于描绘移除js中的没有用到的代码。
留意:依靠es module
怎样用
webpack出产环境默许敞开,无需装备
babel
为什么
babel为编译的每个文件都插入了辅佐代码,使体积过大。所以需求将重复的辅佐代码作为一个独立的模块,避免重复运用。
是什么
@babel/plugin-transform-runtime
禁用babel主动对每个文件的runtime注入,而是引进。并且使一切代码从这儿引进。
怎样用
安装包
npm i @babel/plugin-transform-runtime -D
装备(测验环境和出产环境都要装备)
{
loader: "babel-loader",
options: {
cacheDirectory: true, //敞开babel缓存
cacheCompression: false, //封闭缓存文件紧缩
plugins:["@babel/plugin-transform-runtime"]
},
},
Image Minimizer
为什么
如果开发中引进了较多图片,那么图片体积会比较大,将来请求速度比较慢。咱们能够对图片进行紧缩,削减体积
留意:如果图片是在线链接则不需求,本地图片则需求打包
是什么
image-minimizer-webpack-plugin用来紧缩图片的插件
怎样用
下载 npm i image-minimizer-webpack-plugin imagemin -D
无损紧缩
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo -D
有损紧缩
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant,
imagemin-svgo -D
装备(出产形式)
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
new ImageMinimizerPlugin({
minimizer: {
implementation: ImageMinimizerPlugin.imageminGenerate,
options: {
plugins: [
["gifsicle", { interlaced: true }],
["jpegtran", { progressive: true }],
["optipng", { optimizationLevel: 5 }],
[ "svgo", { plugins: [ "preset-default", "prefixIds", { name: "sortAttrs", params: { xmlnsOrder: "alphabetical", }, }, ],
},
],
],
},
},
}),
打包时会报错,安装两个文件(jpegtran.exe,optipng.exe官网下载)到 node_modules 中才干解决。
需求复制到node_modules\jpegtran-bin\vendor
下面
优化代码运转功用
code split
为什么
打包代码的时分会把一切js文件打包到一个文件下。体积太大,如果只想烘托首页,只需求加载首页的js。其他的js文件不加载。
所以咱们需求将打包的代码进行切割,生成多个js文件,按需加载。
是什么
1.切割文件。将打包的文件进行切割,生成多个js文件。
2.按需加载。需求哪个文件加载哪个文件
怎样做
参考链接blog.csdn.net/goudexingwu…
实践开发时多为单页面运用,在出产环境的optimization中装备
//代码切割操作
splitChunks:{
chunks:"all",
//其他运用默许值
}
测验
将main.js中引进的文件注释,在点击按钮时才加载此文件。在html文件中写点击按钮
main.js按需引进测验如下
document.getElementById("btn").onclick = function () {
import("./js/count").then(({ count }) => {
console.log(count(2, 9));
});
};
count文件在一进入页面时不加载,只有点击按钮时才加载。
给模块命名
// webpack特殊的命名方法/*webpackChunkName: "count"*/
document.getElementById("btn").onclick = function () {
import(/*webpackChunkName: "count"*/ "./js/count").then(({ count }) => {
console.log(count(2, 9));
});
};
出产环境在output中装备
//给打包输出的其他文件命名
chunkFilename:"static/js/[name].js",
一致命名装备
//入口文件打包输出的文件名
filename: "static/js/[name].js",
chunkFilename:"static/js/[name].chunk.js",
//对其他文件命名资源处理
assetModuleFilename: 'static/media/[hash:10][ext][query]',
对css一致命名做处理
new MiniCssExtractPlugin({ filename: "static/css/[name].css",
chunkFilename:"static/css/[name].chulk.css" }),
preload/prefetch(兼容性不太好)
为什么
尽管咱们前面现已做了代码切割,按需加载,可是有些资源需求咱们点击或许触发时才加载,如果文件体积过大,加载慢,用户体会极其不好。咱们需求在浏览器的闲暇时刻加载后续的资源,需求用到preload和prefetch。
是什么
preload:告知浏览器立即加载的资源
prefetch:告知浏览器在闲暇时刻才干够加载资源
共同点:
只加载不履行,有缓存
差异
preload加载优先级高,只能够加载当时页面的资源
prefetch既能够加载当时页面要运用的资源,也能够加载下一个页面要运用的资源。
怎样用
下载包
npm i --save-dev @vue/preload-webpack-plugin
本来运用的是 preload-webpack-plugin,但其与webpack5不兼容所以采用其替代品
装备
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
new PreloadWebpackPlugin({
rel:"preload",
as:"script",
// rel:"prefetch",
})
//有一个文件发生变化,只当时文件的缓存变化,其他文件的换成不受影响
runtimeChunk:{
name:(entrypoint) => `runtime-${entrypoint.name}.js`,
}
core-js
为什么
babel对js的处理无法处理async函数,promise目标等,存在必定的兼容性问题。
是什么
专门做es6及以上api的polyfill(补丁)
怎样用
修正main.js
安装包
npm i core-js
完好引进
在main.js中引进:import “core-js”
按需加载
import “core-js/es/promise”
按需主动引进
修正babel.config.js
module.exports = {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage", //按需加载主动引进
corejs: 3,
},
],
], //预设,babel插件。扩展babel功用,编译es6语法
};
PWA
为什么
用户能够离线拜访
是什么
渐进式网络运用程序,在离线时运用程序能够正常运转。内部经过service workers实现。
怎样用
安装包npm i workbox-webpack-plugin -D
在出产环境装备
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,//这些选项协助快速启用
skipWaiting: true//不允许遗留任何“旧的”
})
在main.js
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').then(registration => {
console.log('sw注册成功了 ', registration);
}).catch(registrationError => {
console.log('SW注册失败 ', registrationError);
});
});
}
此时sw注册失败,需求npm i serve -g后serve dist拜访,即可在无网络时拜访页面。