22_webpack_优化

Terser是一个JS的解析(Parser)、Mangleer(绞肉机)、Compresor(压缩机)的工具

绞肉机
如:一个函数 function functionsWithLongNames(){ } 名称很长,那么打包的文件占用的空间就相对大一些,如果经过工具来对代码进行转化,把函数的名称变成 function a(){} 或者function b(){} 这些较短名称的函数,那么他打包之后的文件占用的体积相对会比较少一些
以前称之为这个过程为丑化,现在变成了绞肉机

压缩机
知道TreeShaking的都知道有些dead code elimination(死代码删除)
如:if(false){console.log('123')}

Terser对JS文件进行解析,对代码进行丑化,压缩的工具集

早期我们是通过uglify-js来压缩、丑化JS代码,但是现在这个库已经不维护了,也不支持ES6以上的语法的

Terser是从uglify-es fork过来的,并且保留它原来的大部分API,以及适配uglify-es和uglify-js@3等;

因为Terser是一个独立的工具,所以我们可以单独安装、使用
  安装:npm i terser (默认安装了cli的工具)

  使用:npx terser [输入文件] -o [输出文件] [options]

 

Terser在webpack中配置

真实开发,我们不需要手动的通过terser来处理我们的代码,我们可以直接通过webpack来处理

  在webpack中有一个minimizer属性,在production模式下,默认就是使用TerserPlugin来处理我们的代码的

  如果我们对默认的配置不满意,也可以自己来创建TerserPlugin的示例,并且覆盖相关的配置

wepback5不需要下载terser-webpack-plugin直接引入

const TerserPlugin = require('terser-webpack-plugin');
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        // 使用多进程并行运行来提高构建速度。默认并发运行次数:。os.cpus().length - 1
        parallel: true,
        // 是否应将注释提取到单独的文件中
        extractComments: false,
        terserOptions: {
          compress: {
            arguments: true,
          },
          mangle: true,
          toplevel: true,
          keep_classnames: true,
          keep_fnames: true,
        },
      }),
    ],
  },

 

 

 

CSS的压缩

CSS压缩通常是去除无用的空格等(因为很难去修改选择器、属性的名称、值等)

css的压缩我们可以使用另外一个插件:css-minimizer-webpack-plugin

安装:

npm i css-minimizer-webpack-plugin -D

npm i postcss -D 不安装postcss会报错

使用:

const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");


plugins:[
    new CleanWebpackPlugin({}),
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash:8].css",
    }),
    new CssMinimizerWebpackPlugin(),
  ],

 

 

Scope Hoisting

什么是ScopeHoisting(作用域提升)呢?

  scope Hoisting从webpack3开始增加的一个新功能
  功能实时对作用域进行提升,并且让webpack打包后的代码更小、运行更快

默认情况下webpack打包会有很多的函数作用域,包括一些(比如最外层的)IIFE

  无论是从最开始的代码运行,还是加载一个模块,都需要执行一系列的函数

  Scope Hoisting可以将函数合并到一个模块中来运行

使用Scope Hoisting非常的简单,默认这个插件就会启用

  在production模式下,默认这个模块就会启用

  在development模式下,我们需要自己来打开该模式

development模式下配置:

const webpack = require("webpack");

  plugins: [
    new webpack.optimize.ModuleConcatenationPlugin(),
  ],

转化前:

(() => {
  "use strict";
  var e = {
      "./src/math.js": /*!*********************!*\
  !*** ./src/math.js ***!
  \*********************/ (e, r, _) => {
        function sum(e, r) {
          return e + r;
        }
        function mul(e, r) {
          return e * r;
        }
        _.r(r), _.d(r, { mul: () => mul, sum: () => sum });
      },
    },
    r = {};
  function __webpack_require__(_) {
    var t = r[_];
    if (void 0 !== t) return t.exports;
    var u = (r[_] = { exports: {} });
    return e[_](u, u.exports, __webpack_require__), u.exports;
  }
  (__webpack_require__.d = (e, r) => {
    for (var _ in r)
      __webpack_require__.o(r, _) &&
        !__webpack_require__.o(e, _) &&
        Object.defineProperty(e, _, { enumerable: !0, get: r[_] });
  }),
    (__webpack_require__.o = (e, r) =>
      Object.prototype.hasOwnProperty.call(e, r)),
    (__webpack_require__.r = (e) => {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(e, "__esModule", { value: !0 });
    });
  var _ = {};
  (() => {
    /*!*********************!*\
  !*** ./src/main.js ***!
  \*********************/
    __webpack_require__.r(_);
    var e = __webpack_require__(/*! ./math */ "./src/math.js");
    console.log((0, e.sum)(20, 30));
  })();
})();

 

转化后:

(() => {
  "use strict";
  var e = {
    r: (e) => {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(e, "__esModule", { value: !0 });
    },
  };
  /*!*********************************!*\
  !*** ./src/main.js + 1 modules ***!
  \*********************************/
  e.r({}),
    console.log(
      (function sum(e, o) {
        return e + o;
      })(20, 30)
    );
})();

 

注意事项:这个插件内部原理其实是依赖于esmodule的静态分析的
esmodule对模块进行解析时,会进行静态分析,在静态分析的时候,这个插件可以分析出来哪些代码可以做作用域提升

如果一个模块被多个模块所引入了不可能每个模块都复制一份代码,这个时候不做作用域提升了

推荐在开发过程中,推荐使用esmodule

如果你在项目中使用了第三方模块,那么第三方模块中可能使用esmodule或者commonjs,那么当我们使用import语句导入模块的时候它指向的是main字段指向的入口文件(package.json中的main属性指向的文件)
  我们可以进行配置:
  resolve.mainFields 4.1.3 优化 resolve.mainFields 配置 - 简书 (jianshu.com)

 

HTTP压缩

文件太小不会压缩,如果压缩了,返回到客户端还要解压反而影响效率

npm  i compression-webpack-plugin -D

   minRatio: 0.8, //压缩比,对比源文件,只有压缩比能达到0.8的时候才压缩,没有达到0.8的时候就没必要压缩了

 

inline-chunk-webpack-plugin

当我们吧runtimeChunk设置为true的时候,运行时的文件会单独打包成一个文件,但是其中的代码量非常少,所以我们没有必要让他单独生成一个文件,直接让他嵌入到html中就可以了

npm i react-dev-utils -D

引入

const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
使用
plugin:[
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/])
]

 

图片压缩

 

posted @ 2022-05-14 21:18  Mr-Hou88888  阅读(81)  评论(0编辑  收藏  举报