随笔 - 40  文章 - 0 评论 - 3 阅读 - 14845
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

1. webpack5的解构代码打包方式

针对下面文件进行打包.

// moduleA
export default {
    a: 1,
}
// index.js
import moduleA from "./moduleA";
console.log("hello webpack", moduleA);

webpack5的打包结果, 就这28行. 但是webpack4有300多行. 300多行里很多是 引入函数import的实现,
但是在webpack5这里, 由于发现moduleA里是静态文件,可以直接拷贝过去, 所以没有import的实现.
就是说webpack5的打包结果会根据项目具体情况, 使用解构的方式, 只打包必须用的代码, 而不是像webpack4一样,打包所有可能用的代码.

(() => {
    var r = {
        208: () => {
            "use strict";
            console.log("hello webpack", {
                a: 1
            })
        },
        956: r => {
            r.exports = {
                entry: "./src/index.js",
                mode: "production"
            }
        }
    },
        e = {};
    function o(t) {
        var s = e[t];
        if (void 0 !== s) return s.exports;
        var n = e[t] = {
            exports: {}
        };
        return r[t](n, n.exports, o),
            n.exports
    }
    o(208),
        o(956)
})();

2. webpack5,webpack4的缓存cache

相同代码
webpack5

  • 未缓存, 2233ms
  • 缓存, 未修改业务代码, 157ms
  • 缓存, 修改了业务代码, 386ms

webpack4

  • 未缓存, 2423ms
  • 缓存, 未修改业务代码, 360ms
  • 缓存, 修改了业务代码, 360ms

对比总结

  • webpack5 比 webpack4的文件压缩策略更优, 分割文件后的vendor体积更小
  • webpack5 缓存构建性能优于webpack4
  • webpack5 缓存的功能显著优于webpack4.

3. Webpack5的URIs.

webpack5支持在请求中处理协议

  • 支持data, 支持base64或原始编码, Mimetype可以在module.rule中被映射到加载器和模块类型. 例如import x from "data:text/javascript, export default 42"(data:text/javascript 表示js代码)
  • 支持file, 支持引入本地资源文件(飞项目中资源)
  • 支持http(s), 需要通过 new webpack.experiments.schemesHttp(s)UriPlugin()选择加入, 默认情况下, 当目标位web时, 这些URI会导致对外部资源的请求
// data
import data from "data:text/javascript, export default 'hello webpack'";
console.log(data); // hello webpack;

// file, 从绝对路径获取文件.(非当前项目目录的文件)
import dataFile from "file:///Users/liumeng/desktop/a.txt"

// https, 需要再webpack.config.js里配置, allowwebUris属性,允许https的请求
import img from "https://xxxx/xx.png"

4. webpack5 更好的treeshaking

  1. 如果module导出的是简单数据类型,比如数字,字符串,boolean, webpack5会直接把这个简单数据类型直接, 替换到对应使用位置, 去掉导出的逻辑. 减少了相关代码.
// moduleA
export default {
    a: 1,
    b: function() {console.log(123)}
}

// index.js
import { a } from "moduleA.js";
console.log(a)

// index.js build之后,会直接把a的值拿出来,放到变量a里面, 从而去掉引入的过程.实现更好的treeshaking
console.log(1);
  1. 如果导入内容未使用,则webpack5不会打包. webpack4则会打包进去.
    如果用import "a.js", 如果a.js里什么都没做, webpack5不会导入a.js, webpack4依旧会导入a.js
    总之webpack5的treeshaking更加的智能.
// 只导入了vue, 没有使用.
import vue from 'vue';
console.log(123)

// webpack5会把vue的内容去掉.
console.log(123)

// webpack4,会把vue的内容打包进去.
  1. sideEffects 控制treeshaking

sideEffects:

  1. package.json的属性
  2. 控制treeshaking的程度, 如果为true, 则认为代码有用, 不会被treeshaking掉. false,则是最大程度的treeshaking. 能去掉都去掉.
  3. 可以使boolean,也可以是数组, ["./src/lib.js"],表示该文件有用,不能被treeshaking掉.
{
    // package.json 
    "sideEffects": true, // false
}

5. webpack5支持package.json的 exports 属性

js可以在node环境和浏览器web环境运行. 有些工具库也确实需要支持这两个环境, 比如工具库 lodash
但是在node和web中原生对象是不同的. node能用require, fs, path, os. web能用import,document, window.这就需要分开处理.
就是说同一个工具,node,web环境的代码是不同的, 需要不同的版本.原来是需要我们自己去判断的.
package.json的 exports 就解决了这个问题. 对应环境自动使用对应版本的代码,不用我们自己做判断了.

// package.json
{
    "exports": {
        // 如果能用require,说明是node环境, 则用a.js为入口文件
        "require": "./a.js",
        // 如果能用import, 说明是web环境,则用b.js为入口.
        "import": "./b.js"
    }
}

该特性只有webpack5支持, webpack4暂不支持.

6. module federation 模块联邦

模块联邦是 webpack5新内置的一个重要功能, 可以让跨应用间真正做到模块共享,
webpack5新增 module Federation功能, 可以帮助多个独立的构建组成一个应用程序,不同的构建可以独立开发与部署.
可以实现微前端.

项目示例: 微应用: webpack-new-feature/demo2/app_a ; 主应用: webpack-new-feature/demo2/app_b

微应用app_a

下面的代码, 用npm run serve启动后, 可以从http://127.0.0.1:3000/app_a.js看到打包后的index.js代码.
注意: 默认的文件名是main.js,但是我们设置了filename:"app_a.js"就把请求地址改了.

// index.js
function run() {
    console.log("子应用启动app_a中...");
    return "run";
}
export default run;

// webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
export default {
    plugins: [
        new ModuleFederationPlugin({
            // 没有filename时, 文件路径默认是 localhost:3000/main.js, 
            // 设置了filename后,文件路径是 localhost:3000/app_a.js
            filename: "app_a.js",
            // 对外名称为main, 别的地方引入时用 import("main/moduleA").
            name: 'appA',
            exposes: {
                // main下面的子模块
                './moduleA': './index.js',
            }
        })
    ],
}

// package.json
{
    "serve": "webpack serve --config ./webpack.config.js"
}

主应用app_b

先启动app_a, 再启动app_b,就能再app_b的代码中引用app_a的模块. 例子: 壹钱包的mice就是主应用, 签到系统就是微应用. 先启动签到系统项目,再启动mice,就能再mice里通过地址看签到系统的效果了

// 主应用业务代码
console.log("主应用app_b启动主");
import("appA/moduleA").then((res) => {
    const run = res.default;
    console.log(run());
})

// webpack.config.js
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
export default {
     plugins: [
        new ModuleFederationPlugin({
            filename: "app_b.js",
            name: "app_b",
            // 引入的微应用.
            remotes: {
                // 微应用名称@微应用文件地址
                appA: "appA@http://localhost:3000/app_a.js",
            }
        })
    ],
}

posted on   下辈子当座桥-李飞  阅读(43)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示