微前端集成优化:让所有子应用体积更小,加载更快!

news2024/9/25 13:19:29

简介

随着前端的日益发展,微前端架构越来越受到青睐。它通过将前端应用拆分为多个独立的子应用,每个子应用可以独立开发、部署和运行,从而提升了开发效率和团队协作。目前主流的微前端方案应该是qiankun了。

以笔者公司为例,采用的就是qiankun框架,主应用采用了vue3,子应用五花八门都有。笔者公司前端服务的子应用大约有400多个,后期也会继续增多!因此,如何优化子应用的体积和加载速度,提升用户体验和性能是我们亟待解决的问题!本文将分享我们公司用到的一些优化方案。

优化方案

在代码层的优化,比如按需加载、懒加载、静态资源优化的都是大家熟知的方案了,这里我就展开了。我们主要的优化在打包上,我们减少体积的两大方案主要是:

  • gzip压缩
  • 依赖共享

本文将详细介绍依赖共享,在了解依赖共享前,我们先了解一下普通的项目打包浏览器初次加载需要请求的文件。

项目初次加载需要请求的文件

对于一个没有特殊配置打包项的普通项目,其核心的请求文件如下:

请求文件

作用

资源尺寸

请求时间

0.js

路由页面内容

(prefetch cache)

60 ms

app.js

main.js等非路由页面内容

893 kB

12 ms

chunk-vendors.js

node_modules内容

37.9 MB

427ms

可以看到,影响一个前端服务体积、加载速度的主要文件就是第三方依赖chunk-vendors.js!

优化思路

依赖共享

假设我们有非常多的子应用,每个子应用的nodmodlues依赖打包也是单独的,在请求这个子应用时,这个依赖文件也是必须请求的!

但是,我们很多子应用的第三方依赖都是重复的!比如vue的底层依赖、store的依赖、eslint的依赖及一些常用的工具依赖!

如果每个子应用都打包自己的依赖库,这是非常愚蠢的,会导致重复加载,浪费带宽和资源!如果我们能让这些公用的依赖只加载一次,那么,所有子应用都不需要额外请求这些依赖,打包体积也会非常小,这样自然会极大的提升每个子应用加载速度!

那么,我们如何才能实现依赖共享呢?

外部化依赖

最简单的实现方案就是可以将常用的依赖库)配置为外部依赖,不打包在每个子应用中,而是通过CDN加载,如这样:

为什么能提高加载速度

当我们采用外部依赖的时候,首先所有应用不需要打包nodemodules的依赖,体积上非常小,在请求基础文件时自然会快很多!

当我们加载主应用时,主应用通过CDN的方式请求了vue的底层依赖、一些常用的公共库等所有依赖。当我们加载子应用时,和主应用相同的这些依赖因为已经请求过了,浏览器会通过缓存机制直接读取已经缓存的数据,避免了重新请求,子应用的加载速度也得到了进一步的提升!

技术方案

目前主流框架如vite、webpack的打包工具默认都是将nodemodlues依赖打包成js文件,我们通过一些配置,就可以将打包方式改变,打包成CDN引文的形式。

使用vite-plugin-cdn-import

首先,安装所需的包

npm install vite-plugin-cdn-import --save-dev

然后,创建或编辑你的 vite.config.js 文件,并添加插件配置:

import { defineConfig } from 'vite';
import cdnImport from 'vite-plugin-cdn-import';
 
export default defineConfig({
  plugins: [
    cdnImport({
      imports: [
        {
          // 库名,比如 `react`
          libraryName: 'react',
          // 库的CDN地址,比如 `https://cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js`
          url: 'https://cdn.jsdelivr.net/npm/react@17.0.1/umd/react.production.min.js',
          // 生产环境是否使用CDN
          prod: true,
          // 开发环境是否使用CDN
          dev: false,
        },
        // 可以继续添加其他库的配置...
      ],
    }),
  ],
});

在上面的配置中,libraryName 是你想要替换的库名,url 是CDN上该库的地址。prod 和 dev 分别指示是否在生产环境和开发环境中使用CDN。

现在,当你运行 Vite 开发服务器或构建你的项目时,所有列在 imports 数组中的依赖项都将通过CDN链接注入到你的代码中。

这种方式的缺点就是,所有依赖都要我们一个个配置,非常麻烦!

借助rollup-plugin-html

要在打包时将所有的 node_modules 依赖以 <script> 标签的形式引入到 HTML 文件中,我们也可以使用 Rollup 的插件,如 rollup-plugin-html 和 rollup-plugin-node-resolve,并结合一些自定义逻辑来生成最终的 HTML 文件。以下是一个具体的实现步骤:

安装必要的插件

经安装了必要的 Rollup 插件:

npm install --save-dev rollup-plugin-html rollup-plugin-node-resolve rollup-plugin-terser

配置 Rollup

接下来,在 rollup.config.js 中配置 Rollup:

import resolve from '@rollup/plugin-node-resolve';
import html from '@rollup/plugin-html';
import { terser } from 'rollup-plugin-terser';
import { defineConfig } from 'rollup';

const generateHTML = () => {
    return {
        name: 'generate-html',
        generateBundle(options, bundle) {
            const scriptTags = Object.keys(bundle)
                .filter(fileName => fileName.endsWith('.js'))
                .map(fileName => `<script src="${fileName}"></script>`)
                .join('\n');

            const htmlContent = `
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My App</title>
</head>
<body>
    ${scriptTags}
</body>
</html>
            `;

            this.emitFile({
                type: 'asset',
                fileName: 'index.html',
                source: htmlContent
            });
        }
    };
};

export default defineConfig({
    input: 'src/main.js',
    output: {
        dir: 'dist',
        format: 'esm',
        entryFileNames: 'static/js/[name]-[hash].js',
        chunkFileNames: 'static/js/[name]-[hash].js',
        assetFileNames: 'static/assets/[name]-[hash][extname]'
    },
    plugins: [
        resolve(),
        terser(),
        generateHTML()
    ]
});

generateHTML 是一个自定义的 Rollup 插件,用于生成 index.html 文件,并自动插入打包生成的 JavaScript 文件。

    • generateBundle 钩子:在生成包的过程中调用。它通过遍历 bundle 对象中的所有文件,找到以 .js 结尾的文件,并生成相应的 <script> 标签。
    • this.emitFile 方法:用于将生成的 HTML 内容作为一个新文件输出到 dist 目录中。

上述方案中,我们通过generateBundle钩子实现了所有js文件的遍历与cdn链接的生成。这个方法中,html文件是在vite.config.js中写的,然而我们一般可能更倾向于外部引入index.html。

优化方案

此方案只给出大致思路:

  • 借助generateBundle钩子获取所有文件的cdnList
// 借助generateBundle 钩子实现
const cdnList = getCdnList()
  • 使用 createHtmlPlugin 注入数据

使用 vite-plugin-html 提供的 createHtmlPlugin 插件,将 cdnList 作为数据注入到 HTML 模板中:

import { createHtmlPlugin } from 'vite-plugin-html';

const packageName = edgeClient ? 'meos-autocontrol-web-edge' : 'meos-control-web';

export default defineConfig(({ mode }) => {
  const plugins = [
    // ...其他插件
    createHtmlPlugin({
      minify: true,
      inject: {
        data: {
          title: packageName,
          cdnList: cdnList
        }
      }
    }),
    // ...其他插件
  ];

  return {
    // ...其他配置
    plugins,
    // ...其他配置
  };
});
  • 在 index.html 中使用模板语法将 cdnList 渲染到 HTML 中
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <link rel="icon" type="image/svg+xml" href="/vite.svg" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="Content-Security-Policy" />
        <title><%- title -%></title>
        <% cdnList.forEach(function(cdn) { %> <%- `
        <script src="${cdn}"></script>
        ` -%> <% }) %>
    </head>
    <body>
        <div id="app"></div>
        <script type="module" src="./src/main.ts"></script>
    </body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2083957.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI在医学领域:基础模型和视觉-语言模型在计算病理学应用概述

近年来&#xff0c;人工智能&#xff08;AI&#xff09;基于方法在计算病理学&#xff08;CPath&#xff09;领域中的应用迅速增长&#xff0c;这主要得益于数字幻灯片扫描仪的广泛采用。因此&#xff0c;大规模的全幻灯片图像&#xff08;Whole Slide Images, WSIs&#xff09…

Linux内存管理(1)——MMU内存管理单元及Buddy算法详解

文章目录 1.内存管理单元&#xff08;MMU&#xff09;1.1 MMU的作用1.2 MMU相关概念1.3 ARM处理器访问内存过程 2.内存优化之buddy伙伴算法2.1 背景2.2 优缺点2.2 原理 最近复习Linux内存管理部分&#xff0c;简单将自己的理解记录一下 内存&#xff1a;包括随机存储器&#xf…

委托 by 操作符

属性委托给属性 使用 by:: 操作符&#xff0c;代表调用系统内置的方法。 读&#xff1a;getVaule 写&#xff1a;setValue 共享同一个数据。 /*** 属性委托给属性* by:: 系统内置的方法&#xff0c;非自定义的* 共享同一个数据*/ var num:Float 9999.0f/*** newNum属性委托…

黑神话悟空-画质提升+帧数提升+超宽屏+写实画质补丁+无光追也可拥有的超强画质

超真实画质提升&#xff01;&#xff01;&#xff01; 下载地址&#xff1a;https://pan.quark.cn/s/529202fbbbef

Python | Leetcode Python题解之第381题O(1)时间插入、删除和获取随机元素-允许重复

题目&#xff1a; 题解&#xff1a; import random class RandomizedCollection:def __init__(self):"""Initialize your data structure here."""self.table {}self.ns []def insert(self, val: int) -> bool:"""Inserts …

WPF 手撸插件 七 日志记录(二)

1、本文使用Serilog进行记录日志&#xff0c;目前想只用log4net进行日志记录&#xff0c;但是Serilog有想学习一下&#xff0c;所有这里使用控制台项目来学习一下Serilog。我使用的还是.Net Framework 4.5. 2、NuGet 安装Serilog 2.12.0、Serilog.Sinks.Console 4.1.0&#xf…

智能学习辅助系统——后端部分

目录 前言 一、准备工作 1.需求&环境搭建 1.1需求说明 1.2环境搭建 2.开发规范 2.1 开发规范-REST 2.2 开发规范-统一响应结果 3.开发流程 二、部门管理 1.查询部门 &#xff08;1&#xff09;原型和需求 &#xff08;2&#xff09;接口文档 &#xff08;3&…

阿里巴巴1688 阿里228滑块 网站分析(不涉及逆向)

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我…

R语言统计分析——回归模型深层次分析

参考资料&#xff1a;R语言实战【第2版】 本文主要讨论回归模型的泛化能力和变量相对重要性的方法。 1、交叉验证 从定义上看&#xff0c;回归方法就是从一堆数据中获取最优模型参数。对于OLS&#xff08;普通最小二乘&#xff09;回归&#xff0c;通过使得预测误差&#xff0…

【书生大模型实战营(暑假场)】进阶任务六 MindSearch CPU-only 版部署

进阶任务六 MindSearch CPU-only 版部署 任务文档GitHub CodeSpace硅基流动HuggingFace Space 任务&#xff1a; MindSearch 部署到Github Codespace 和 Hugging Face Space 笔者部署在 HuggingFace 的 MindSearch 模型链接为&#xff1a;ccdgyro/MindSearch 1 开发机创建和环…

重塑视频监控体验:WebRTC技术如何赋能智慧工厂视频高效管理场景

视频汇聚EasyCVR视频监控平台&#xff0c;作为一款智能视频监控综合管理平台&#xff0c;凭借其强大的视频融合汇聚能力和灵活的视频能力&#xff0c;在各行各业的应用中发挥着越来越重要的作用。 EasyCVR平台不仅兼容多种主流标准协议及私有协议/SDK的接入&#xff08;如&…

汽车线束品牌服务商推荐-力可欣:致力于汽车连接线束和汽车连接器的开发、生产和应用

汽车线束品牌服务商推荐-力可欣&#xff1a;致力于汽车连接线束和汽车连接器的开发、生产和应用

医院建筑的电气设计——保障医疗质量与安全的坚固基石

医疗资源与水平的提升成为了衡量民生福祉的重要标尺。随着一批批新建医院及既有医院的华丽蜕变&#xff0c;从社区医院到综合医院&#xff0c;再到医疗城、医疗集聚区的崛起&#xff0c;不仅彰显了政府对民生健康的深切关怀&#xff0c;也预示着我国医疗体系正迈向智能化、高效…

C++初学(17)

17.1、字符函数库cctype C有一个与字符相关的、非常方便的函数软件包&#xff0c;它可以简化如确定字符是否为大写字母、数字或标点符号等工作。这些函数的原型是在头文件cctype中定义的。如果ch是一个字母&#xff0c;则isalpha(ch)函数返回一个非零值&#xff0c;否则返回0。…

关于zotero无法识别拖入的pdf和caj的题录信息

一、首先要安装好茉莉花插件 1、点击链接&#xff0c;进入Zotero 插件商店&#xff0c; Zotero 插件商店 | Zotero 中文社区 (zotero-chinese.com) 搜索&#xff1a;Jasminum&#xff0c;选择好版本&#xff0c;点击下载 2、 下载好后&#xff0c;点击“工具”&#xff0c;…

兔子序列(c语言)

1.//描述 //兔子发现了一个数字序列&#xff0c;于是开始研究这个序列。兔子觉得一个序列应该需要有一个命名&#xff0c; // 命名应该要与这个序列有关。由于兔子十分讨厌完全平方数&#xff0c; // 所以兔子开创了一个新的命名方式&#xff1a;这个序列中最大的不是完全平方数…

kubectl陈述式资源管理

目录 概念 kubectl的基础命令 *每天常用的查看集群的基本信息 deployment的部署方式 deployment 的特点 基于deployment创建pod 手动缩容 service的类型以及工作原理 创建service service的类型 修改service的类型为nodeport **nodeport实验&#xff1a;对外暴露端…

数据结构(Java)实现:栈和队列

文章目录 1. 栈的模拟实现1.1 普通栈的模拟实现1.2 泛型栈的模拟实现 2. 栈的介绍3. 栈的使用4. 栈的应用场景4.1 改变元素的序列4.2 将递归转换为循环4.3 使用栈解题 5. 栈的链表实现6. 队列概念7. 队列的使用8. 模拟队列的实现8.1 链式队列8.2 顺序队列 9. 双端队列 1. 栈的模…

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图

C++和OpenGL实现3D游戏编程【连载6】——不规则图形的纹理贴图 1、本节实现的内容 上一节我们讨论了纹理贴图的相关基础操作,但上一节的纹理贴图操作基本上都是规则图形,包括圆形和球形虽然复杂一点,但是它也是规则的。这一节课我们要讨论一下,怎么在不规则图形上纹理贴图…

​polarctf靶场[web]upload1​

[web]upload1 考点&#xff1a;文件上传漏洞 不信邪&#xff0c;先上传php&#xff0c;发现被拦截 在上传jpg和png图片&#xff0c;发现也被拦截 所以先拦截抓包&#xff0c;上传个有一句话木马的png图片 将文件后缀改为php&#xff0c;先在重发器发送&#xff0c;发现上传成…