鲜花网站建设企划书,如何推广微信视频号,国外 wordpress模板,微网站开发价格简介
随着前端的日益发展#xff0c;微前端架构越来越受到青睐。它通过将前端应用拆分为多个独立的子应用#xff0c;每个子应用可以独立开发、部署和运行#xff0c;从而提升了开发效率和团队协作。目前主流的微前端方案应该是qiankun了。
以笔者公司为例#xff0c;采用…简介
随着前端的日益发展微前端架构越来越受到青睐。它通过将前端应用拆分为多个独立的子应用每个子应用可以独立开发、部署和运行从而提升了开发效率和团队协作。目前主流的微前端方案应该是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: [{// 库名比如 reactlibraryName: react,// 库的CDN地址比如 https://cdn.jsdelivr.net/npm/react17.0.1/umd/react.production.min.jsurl: https://cdn.jsdelivr.net/npm/react17.0.1/umd/react.production.min.js,// 生产环境是否使用CDNprod: true,// 开发环境是否使用CDNdev: 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 langen
headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleMy 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 langenheadmeta charsetUTF-8 /link relicon typeimage/svgxml href/vite.svg /meta nameviewport contentwidthdevice-width, initial-scale1.0 /meta http-equivContent-Security-Policy /title%- title -%/title% cdnList.forEach(function(cdn) { % %- script src${cdn}/script -% % }) %/headbodydiv idapp/divscript typemodule src./src/main.ts/script/body
/html