webpack5提升打包构建速度(四)

1、SourceMap:找到映射后源代码出错位置

SourceMap(源代码映射)是一个用来生成源代码与构建后代码一一映射的文件的方案。

它会生成一个 xxx.map 文件,里面包含源代码和构建后代码每一行、每一列的映射关系。当构建后代码出错了,会通过 xxx.map 文件,从构建后代码出错位置找到映射后源代码出错位置,从而让浏览器提示源代码文件出错位置,帮助我们更快的找到错误根源。

/* 
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/    "use strict";
/******/    var __webpack_modules__ = ({

/***/ "./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/less/index.less":
/*!**********************************************************************************************************!*\
  !*** ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/less/index.less ***!
  \**********************************************************************************************************/
/***/ ((module, __webpack_exports__, __webpack_require__) => {

eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/noSourceMaps.js */ \"./node_modules/css-loader/dist/runtime/noSourceMaps.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ \"./node_modules/css-loader/dist/runtime/api.js\");\n/* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__);\n// Imports\n\n\nvar ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_noSourceMaps_js__WEBPACK_IMPORTED_MODULE_0___default()));\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, \".box2 {\\n  width: 100px;\\n  height: 100px;\\n  background-color: deeppink;\\n}\\n\", \"\"]);\n// Exports\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___);\n\n\n//# sourceURL=webpack://webpack5/./src/less/index.less?./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js");

/***/ }),
// 其他省略

打包完代码出错完全找不到哪里出错了,如果在配置文件中配置好属性,就能方便的找到打包后出错的代码所在行。

如何配置?

开发模式下配置:cheap-module-source-map

优点:打包编译速度快,只包含行映射

缺点:没有列映射

module.exports = {
  // 其他省略
  mode: "development",
  devtool: "cheap-module-source-map",
};

生产模式:source-map

优点:包含行/列映射

缺点:打包编译速度更慢

module.exports = {
  // 其他省略
  mode: "production",
  devtool: "source-map",
};
2、HMR/模块热替换(HotModuleReplacement):在程序运行中,替换、添加或删除模块,而无需重新加载整个页面。

如何配置?

在devServer中配置hot:true

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

经过上面的设置, css 样式经过 style-loader 处理,已经具备 HMR 功能了。但是 js 还不行。js要经过下面的设置方式:

import count from './js/count'
import sum from './js/sum'
import './css/index.css'
import './css/index.less'
import './css/index.sass'

const result = count(8, 2)
console.log(result, 'result')
console.log(count(8, 2))
console.log(sum(2, 3))

// 判断是否支持HMR功能  这样设置是指这两个js文件更新时,局部刷新内容
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(5, 6);
        console.log(result2);
    });
}

上面的写法还是比较麻烦的,之后我们还是会用到loader去处理:vue-loader, react-hot-loader

3、OneOf:匹配上一个 loader, 剩下的就不忽略了。

如何配置?

在module中rules的loader用oneOf全部都包起来。生产模式也是这样配置。

 module: {
        rules: [{
            oneOf: [{
                    // 用来匹配 .css 结尾的文件
                    test: /\.css$/,
                    // use 数组里面 Loader 执行顺序是从右到左
                    use: ["style-loader", "css-loader"],
                },
                {
                    test: /\.less$/,
                    use: ["style-loader", "css-loader", "less-loader"],
                },
                {
                    test: /\.sass$/,
                    use: ["style-loader", "css-loader", "sass-loader"],
                },
                {
                    test: /\.(png|jpe?g|gif|webp)$/,
                    type: "asset",
                    parser: {
                        dataUrlCondition: {
                            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                        }
                    },
                    //设置图片打包后的路径
                    generator: {
                        filename: 'dist/images/[hash:10][ext][query]'
                    }
                },
            ]
        }],
    },
4、Include/Exclude:在对 js 文件处理时,要排除 node_modules 下面的文件。

include: 包含,只处理 xxx 文件
***exclude:***排除,除了 xxx 文件以外其他文件都处理

如何设置

例如 module中这样设置:

{
       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", // 默认值
    }),
]
5、多进程打包:开启电脑的多个进程同时干一件事,速度更快

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

如何设置

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

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

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

  2. 下载包

    npm i thread-loader -D

3.使用

在module的rules中的引入babel-loader的use中添加如下代码

{
    loader: "thread-loader", // 开启多进程
     options: {
          workers: threads, // 数量
      },
 },

在plugins的new ESLintWebpackPlugin中配置 threads, // 开启多进程

最后在optimization中new TerserPlugin中配置如下设置:

  optimization: {
    minimize: true,
    minimizer: [
      // css压缩也可以写到optimization.minimizer里面,效果一样的
      new CssMinimizerPlugin(),
      // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
      new TerserPlugin({
        parallel: threads // 开启多进程
      })
    ],
  },

所以总的module代码配置如下:

module.exports = {
    //入口文件
    entry: {
        index: './src/main.js',
        admin: './src/main2.js',
    },
    //出口文件
    output: {
        path: undefined, // 开发模式没有输出,不需要指定输出目录
        filename: "static/js/[name]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: /\.sass$/,
                    use: ["style-loader", "css-loader", "sass-loader"],
                },
                {
                    test: /\.(png|jpe?g|gif|webp)$/,
                    type: "asset",
                    parser: {
                        dataUrlCondition: {
                            maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
                        }
                    },
                    //设置图片打包后的路径
                    generator: {
                        filename: 'dist/images/[hash:10][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, // 开启多进程
        }),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            // css压缩也可以写到optimization.minimizer里面,效果一样的
            new CssMinimizerPlugin(),
            // 当生产模式会默认开启TerserPlugin,但是我们需要进行其他配置,就要重新写了
            new TerserPlugin({
                parallel: threads // 开启多进程
            })
        ],
    },

    //模式
    mode: "production",
    devtool: "source-map",
}

这个时候再打包试试看,其实目前文件比较小的话,实际打包的速度比之前是慢的,只有文件的内容足够大时,处在一个临界值的时候,才发现用这个方法打包速度大大提高!

相关推荐
祈澈菇凉1 天前
webpack和grunt以及gulp有什么不同?
前端·webpack·gulp
AsBefore麦小兜1 天前
Vite vs Webpack
前端·webpack
垣宇2 天前
Vite 和 Webpack 的区别和选择
前端·webpack·node.js
小纯洁w3 天前
Webpack 的 require.context 和 Vite 的 import.meta.glob 的详细介绍和使用
前端·webpack·node.js
海盗强3 天前
Webpack打包优化
前端·webpack·node.js
祈澈菇凉3 天前
如何优化 Webpack 的构建速度?
前端·webpack·node.js
懒羊羊我小弟3 天前
常用 Webpack Plugin 汇总
前端·webpack·npm·node.js·yarn
祈澈菇凉4 天前
Webpack的持久化缓存机制具体是如何实现的?
前端·webpack·gulp
懒羊羊我小弟5 天前
Webpack 基础入门
前端·webpack·rust·node.js·es6
刽子手发艺5 天前
Selenium+OpenCV处理滑块验证问题
opencv·selenium·webpack