美文网首页
微前端webpack升级Vite

微前端webpack升级Vite

作者: 飞飞廉 | 来源:发表于2024-01-18 15:36 被阅读0次

背景

我们代码采用的是webpack的微前端架构,但是由于代码越来越多,巨石应用越来越大,本地启动编译时间需要10s,所以决定升级本地启动环境为vite,提升开发效率。但是由于是微前端架构,升级过程中遇到了很多问题,逐个分析解决。

核心原理

Vite 是一种现代化的前端开发构建工具,它的核心原理和特性可以归纳为以下几个方面:

  1. 基于 ES 模块的开发模式:Vite 通过基于 ES 模块的开发模式,可以让开发者在开发过程中以更加自然的方式编写代码。开发者可以通过 import/export 语句来引用其他模块,而无需使用其他工具将这些模块打包在一起。

  2. 快速的冷启动:Vite 采用了一种“按需编译”的策略,只会在需要时编译文件,这样就避免了像其他打包工具一样需要一次性编译所有的文件,导致启动时间较长的问题。因此,Vite 的冷启动速度非常快,可以显著提高开发效率。

  3. 开发模式下的缓存:在Vite开发模式下,当一个模块被第一次引用时,Vite会将该模块的依赖关系分析并缓存到.vite/deps目录下。这样在下一次重新编译时,Vite就可以直接使用缓存的依赖关系,Vite可以减少重复的依赖分析和编译操作,从而加快编译速度。同时,由于缓存的依赖关系是按照模块路径组织的,因此Vite还可以检测到依赖关系的变化,并在需要时自动更新缓存。

  4. 轻量快速的热重载HMR:Vite 采用了一种基于原生 ES 模块系统的高效的热更新机制(HMR),可以在开发过程中快速地更新代码,并在浏览器中实时地查看更新效果,而无需刷新页面。这也大大提高了开发效率。

  5. 支持多种开发语言:Vite 不仅支持 JavaScript 和 TypeScript,还支持 Vue、React、Svelte 等多种前端开发框架,可以让开发者在开发过程中更加灵活。

总之,Vite 的核心原理是通过基于 ES 模块的开发模式、快速的冷启动、高效的 HMR 以及对多种开发语言的支持,来提高前端开发的效率。

微前端改造

1、vite-plugin-federation 替换ModuleFederationPlugin

由于我们代码使用的是微前端框架,主要使用webpack的ModuleFederationPlugin来实现各个模块之间的独立,升级为vite时我们首先采用的是使用针对vite的插件vite-plugin-federation 来进行整体升级改造。

vite-plugin-federation的使用方式与Webpack 5中的模块联邦相似,通过配置来定义不同子应用程序之间的依赖关系和公共模块,从而实现代码的复用和分发。在实际应用中,可以将一个大型的应用程序拆分成多个独立的子应用程序,通过这种方式实现微服务架构和多人合作开发等需求。

但是在改造过程中发现,该plugin实现的核心原理是各个模块之间的remote和exposes需要先build,build的时候相当于使用rollup进行打包编译,这样就失去了vite本身最难得的快的属性。所以最后我们决定放弃使用该插件。

2、采取本地开发模式摒弃微前端多个server模式,准备通过alias将多个子模块合并成一个子模块。

核心原理:rewrite文件间/模块间的引用路径,本地开发只需要单个vite server

1)alias方案初期尝试过程中遇到两个卡点

  1. 子模块之间互相调用,通过commonLibs,commonApp这种别名进行引用,我们需要识别出文件的真正路径,这个主要是通过原模块中导出的remotes文件导出的exposes,能找到真正的路径。
    [图片上传失败...(image-f35d07-1705649743183)
    [图片上传失败...(image-d89aea-1705649639438)]

解决方案:vite提供的resolve的alias配置中支持customResolver,其中的id和importer可以提供一些自定义的方案,id是代码中要解析的from后边的path,importer是该文件的目录。所以我们可以先根据id去exposes中找到最终的路径,这样就可以解析这种子模块的引用方式。

[图片上传失败...(image-cb3d7f-1705649639438)]

  1. 各个子模块的app开头的引用一般都指向自己的子模块的src,我们改成一个server之后,需要识别app所属的模块,并指向对应的src位置。

[图片上传失败...(image-6fe9c-1705649639438)]

解决方案:从importer中提取出所属模块,然后把app替换成该子模块下的src路径

[图片上传失败...(image-135c0e-1705649639438)]

2)遇到的问题和解决方案

  1. vite模式下子模块中的node_modules的引用会优先取离他最近的node_modules中去取,所以由于该特性无需处理npm包的alias。

  2. connected-react-router问题,启动过程中报错了,查一下原因是connected-react-router和react-router、react-dom的兼容性问题,由于connected-react-router缺少维护,和路由版本兼容要求高,因此解决方案是下掉connected-react-router,下掉connected-react-router的过程中需要注意几个点,后续大家也不要用这种方式去使用了。

[图片上传失败...(image-6a206d-1705649639438)]

下线的过程中发现报了一个错,是使用useHistory或者useLocation的时候,Context找不到。一开始以为是单例问题,尝试了很多解决方案,只保留一个模块的这个npm包还是不行,排除单例问题,后来发现这个文件报错位置在react-router里,但我们由于下掉connected-react-router的过程中,BrowserRouter使用的是react-router-dom的,Context也是通过react-router-dom下发的,但我们代码里使用的useHistory等是引入的react-router,因此改掉了这个引用就解决了问题。

[图片上传失败...(image-fe816-1705649639438)]

    • 下掉最外层的入口

[图片上传失败...(image-8eb8de-1705649639438)]

    • 下掉路由对history的注入和监听;注意要同时下掉state.router的取用逻辑。

[图片上传失败...(image-f7212a-1705649639438)]

[图片上传失败...(image-527cdb-1705649639438)]

[图片上传失败...(image-b02b9c-1705649639438)]

    • 下掉dispatch(puh(url))的使用;采用useHistory进行跳转。

[图片上传失败...(image-351304-1705649639438)]

  1. alias副作用导致的单例问题。

vite中alias相对路径会把文件打到有后缀的文件,我们alias的子模块的替换由于exposes中披露了文件后缀,所以也会打到有后缀的文件,但是app的alias打到的是无后缀的文件,这样就会生成两份,对于使用context这样全局数据的来说,就会由于无法保证单例导致context数据清空的bug。

这边把用sharedInfo的context的引用路径改成了相对路径,或者加上.js后缀即可。

还有app/utils/flags的引用也要加上后缀或者使用相对路径。

[图片上传失败...(image-ef7fe2-1705649639438)]

对大部分的app引用没有影响,只是影响这种需要保证单实例的。

[图片上传失败...(image-e5e100-1705649639438)]

[图片上传失败...(image-353150-1705649639438)]

  1. 微前端模块中除了alias引入的非单实例问题,也有一些模块需要单实例,以前维护在sharedInfo里去保证,如果有多个npm包的话,在vite中自身支持导出的是一个模块,来保证单实例问题,从vite的预构建输出结果可以看出。

在 Vite 中,不同的 Node.js 模块(node_modules 目录下的不同包)可以共享一个单例模式的包,这是通过 Vite 的模块解析器和缓存机制来实现的。具体来说,Vite 会对每个模块进行缓存,当第一次请求一个模块时,Vite 会解析该模块及其依赖项,然后将其保存在内存中,下次请求该模块时,会直接从缓存中读取,而不是重新解析和构建。

在 Vite 中,当多个模块引用同一个依赖时,Vite 会将这些模块中的依赖项映射到同一个缓存中的实例,从而实现了单例模式。这样做可以提高应用程序的性能,减少内存占用和加载时间。

需要注意的是,Vite 的单例模式只是在开发模式下生效。在生产模式下,由于 Vite 会对依赖项进行代码拆分和压缩,因此每个模块都会引用自己的依赖项的独立实例,这样可以减小应用程序的大小并提高性能。

[图片上传失败...(image-f4f425-1705649639438)]

[图片上传失败...(image-b41d46-1705649639438)]

  1. mockService中间件

vite也支持启动服务时做一些mock服务,具体改造方式如下

[图片上传失败...(image-eecaf4-1705649639438)]

  1. css注入变量

启动过程中发生如下报错,是因为less的一些全局变量没有注入,增加vite配置注入即可。

[图片上传失败...(image-3c3d00-1705649639438)]

[图片上传失败...(image-a03728-1705649639438)]

  1. 静态资源解析

代码中引入了一些html或者docx结尾的静态资源,启动过程中会报错,增加静态资源的配置即可。

[图片上传失败...(image-fcac48-1705649639438)]

[图片上传失败...(image-396fbe-1705649639438)]

  1. 全局变量注入

可以通过define配置注入一些全局变量。

[图片上传失败...(image-8c14b4-1705649639438)]

  1. babel插件问题

react插件中支持babel的一些presets和plugin,但是有一些会和react插件内置的冲突,要注意避坑,比如之前我就把原来代码库中的babel配置直接抄过来传入了react插件中,结果就报错了。比如presets中的@babel/preset-env和@babel/preset-react就会和react插件有冲突。

[图片上传失败...(image-e5d4a8-1705649639438)]

[图片上传失败...(image-75e027-1705649639438)]

效果评估

现状

[图片上传失败...(image-f95bf0-1705649639438)]

改进后指标

冷启动:8s左右

热更新:保存即更新,几乎实时更新,不需要刷新和等待时长。

注意事项

相关文章

网友评论

      本文标题:微前端webpack升级Vite

      本文链接:https://www.haomeiwen.com/subject/baxdodtx.html