• 652 webpack代码分离:多入口起点,入口依赖,SplitChunks,动态导入,代码懒加载,optimization.chunkIds、runtimeChunk,Prefetch和Preload


    认识代码分离


    多入口起点


    Entry Dependencies(入口依赖)


    SplitChunks


    SplitChunks自定义配置

    • 当然,我们可以自定义更多配置,我们来了解几个非常关键的属性:


    SplitChunks自定义配置解析


    SplitChunks自定义配置解析


    动态导入(dynamic import)


    动态导入的文件命名


    代码的懒加载


    optimization.chunkIds配置


    optimization. runtimeChunk配置


    Prefetch和Preload


    目录结构


    package.json

    {
      "name": "webpack_devserver",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "build": "webpack --config ./config/webpack.common.js --env production",
        "serve": "webpack serve --config ./config/webpack.common.js --env development"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "@babel/core": "^7.12.17",
        "@babel/preset-env": "^7.12.17",
        "@babel/preset-react": "^7.12.13",
        "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
        "babel-loader": "^8.2.2",
        "clean-webpack-plugin": "^3.0.0",
        "css-loader": "^5.0.2",
        "html-webpack-plugin": "^5.2.0",
        "react-refresh": "^0.9.0",
        "style-loader": "^2.0.0",
        "vue-loader": "^15.9.6",
        "vue-template-compiler": "^2.6.12",
        "webpack": "^5.23.0",
        "webpack-cli": "^4.5.0",
        "webpack-dev-server": "^3.11.2",
        "webpack-merge": "^5.7.3"
      },
      "dependencies": {
        "axios": "^0.21.1",
        "dayjs": "^1.10.4",
        "express": "^4.17.1",
        "lodash": "^4.17.21",
        "react": "^17.0.1",
        "react-dom": "^17.0.1",
        "react-router-dom": "^5.2.0",
        "vue": "^2.6.12",
        "webpack-dev-middleware": "^4.1.0"
      }
    }
    
    

    webpack.common.js

    const resolveApp = require("./paths");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const VueLoaderPlugin = require("vue-loader/lib/plugin");
    const TerserPlugin = require("terser-webpack-plugin");
    
    const { merge } = require("webpack-merge");
    
    const prodConfig = require("./webpack.prod");
    const devConfig = require("./webpack.dev");
    
    const commonConfig = {
      entry: {
        // 【多入口】
        main: "./src/main.js",
        index: "./src/index.js"
        // main: { import: "./src/main.js", dependOn: "shared" },
        // index: { import: "./src/index.js", dependOn: "shared" },
        // lodash: "lodash",
        // dayjs: "dayjs"
        // shared: ["lodash", "dayjs"]
      },
      output: {
        path: resolveApp("./build"),
        filename: "[name].bundle.js", // 【[name]是entry中的key。】
        chunkFilename: "[name].[hash:6].chunk.js" // 动态导入的文件命名
      },
      resolve: {
        extensions: [".wasm", ".mjs", ".js", ".json", ".jsx", ".ts", ".vue"],
        alias: {
          "@": resolveApp("./src"),
          pages: resolveApp("./src/pages"),
        },
      },
      optimization: {
        // 对代码进行压缩相关的操作
        minimizer: [
          new TerserPlugin({
            extractComments: false,
          }),
        ],
        // natural: 使用自然数(不推荐),
        // named: 使用包所在目录作为name(在开发环境推荐)
        // deterministic: 生成id, 针对相同文件生成的id是不变
        // chunkIds: "deterministic",
        // 【splitChunks:webpack会自动配置开发环境和生产换的值】
        splitChunks: {
          // async:异步导入, initial:同步导入, all:异步/同步导入
          chunks: "all",
          // 最小尺寸: 单位是字节,如果拆分出来一个, 那么拆分出来的这个包的大小最小为minSize
          minSize: 20000,
          // 将大于maxSize的包, 拆分成不小于minSize的包
          maxSize: 20000,
          // minChunks表示引入的包, 至少被导入了几次 【才拆分】
          minChunks: 1,
          cacheGroups: {
            // 【vendor:供应商。所有第三方的东西匹配到了后,打包到vendor里,不是必须叫vendor,可以自定义】
            vendor: {
              test: /[\/]node_modules[\/]/, // 这里是路径,匹配windows、mac平台
              filename: "[id]_vendors.js",
              // name: "vendor-chunks.js",
              priority: -10 // 优先级,都是写负数
            },
            // bar: {
            //   test: /bar_/, // 这里是文件,不是路径
            //   filename: "[id]_bar.js"
            // }
            default: {
              // 如果一个文件被引入了2次,就单独打包出来一个js文件
              minChunks: 2,
              filename: "common_[id].js",
              priority: -20
            }
          }
        },
        // true/multiple
        // single
        // object: name
        runtimeChunk: {
          name: function(entrypoint) {
            return `why-${entrypoint.name}`
          }
        }
      },
      module: {
        rules: [
          {
            test: /.jsx?$/i,
            use: "babel-loader",
          },
          {
            test: /.vue$/i,
            use: "vue-loader",
          },
          {
            test: /.css/i,
            use: ["style-loader", "css-loader"],
          },
        ],
      },
      plugins: [
        new HtmlWebpackPlugin({
          template: "./index.html",
        }),
        new VueLoaderPlugin(),
      ],
    };
    
    module.exports = function(env) {
      const isProduction = env.production;
      process.env.NODE_ENV = isProduction ? "production" : "development";
    
      const config = isProduction ? prodConfig : devConfig;
      const mergeConfig = merge(commonConfig, config);
    
      return mergeConfig;
    };
    

    main.js

    import _ from 'lodash';
    import dayjs from 'dayjs';
    
    import "./bar_01";
    import "./bar_02";
    
    console.log("Hello Main");
    console.log(_.join(["Hello", "Main"]));
    console.log(dayjs(), "Main");
    
    // 只要是异步导入的代码, webpack都会进行代码分离
    // magic comments
    import(/* webpackChunkName: "foo" */"./foo").then(res => {
      console.log(res);
    });
    
    import(/* webpackChunkName: "foo_02" */"./foo_02").then(res => {
      console.log(res);
    });
    

    index.js

    // import _ from 'lodash';
    // import dayjs from 'dayjs';
    
    import "./bar_01";
    
    console.log("Hello Index");
    
    const button = document.createElement("button");
    button.innerHTML = "加载元素";
    
    button.addEventListener("click", () => {
      // prefetch -> 魔法注释(magic comments)
      /* webpackPrefetch: true */
      /* webpackPreload: true */
      import(
        /* webpackChunkName: 'element' */
        /* webpackPrefetch: true */
        "./element"
      ).then(({ default: element }) => {
        document.body.appendChild(element);
      })
    });
    document.body.appendChild(button);
    

    babel.config.js

    const presets = [
      ["@babel/preset-env"],
      ["@babel/preset-react"],
    ];
    
    const plugins = [];
    const isProduction = process.env.NODE_ENV === "production";
    
    // React HMR -> 模块的热替换 必然是在开发时才有效果
    if (!isProduction) {
      plugins.push(["react-refresh/babel"]);
    } else {
    
    }
    
    module.exports = {
      presets,
      plugins
    }
    


  • 相关阅读:
    day33-1 线程队列
    day32-4 GIL全局解释锁
    day32-3 阻塞非阻塞同步异步&异步回调
    day32-2 线程池与进程池
    day32-1 事件Event
    Chrome设置--disable-web-security解决跨域问题
    去除系统部分属性触摸是出现的色值
    初始化一个React项目
    ## normalize.css 中文版
    vue组件的3种书写形式
  • 原文地址:https://www.cnblogs.com/jianjie/p/14536321.html
Copyright © 2020-2023  润新知