高级也便是相对于基础的优化。从以下视点进行优化:

提高开发体会;
提高打包构建速度
削减代码体积
优化代码运转功用

提高开发体会

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拜访,即可在无网络时拜访页面。