在微前端qiankun中使用Vite你踩坑了吗?

前端那些趣事

共 4280字,需浏览 9分钟

 ·

2022-01-22 01:31

哈喽,我是树酱。之前搭建的微前端体系已经稳步运行将近两年了,最近遇到一些童鞋反馈。之前据说qiankun并不支持Vite打包的应用,那是不是我就无法使用了?

是的,官方暂未有文档表明已经支持Vite。接下来我会从Vite聊起,然后一步步解析如何去解决在qiankun微前端体系中集成基于Vite构建的子应用.

1 为什么要用Vite?

在Vite没有诞生之前,我们前端大多都是基于 webpack 构建的,主要离不开以下两点:

  • 本地开发(热更新HMR)
  • 打包上线

webpack的核心简单概括就是将各类资源打包整合在一起,形成bundle的能力。但是随着项目的不断迭代,慢慢演变成一个中大型项目,这时候你会发现打包时间太久了,换句话说构建效率变低了。

bundle工具的演变

而在Bundle工具的演变过程中,我们见证了 webpack[1]Rollup[2] 和 Parcel[3] 等工具,同时构建效率也在逐步提升,如下图所示👇

webpack vs rollup vs parcel vs esbuild

而伴随着浏览器对ES模块(ESM)逐步支持兼容,是不是有更快的方式可以解决构建问题?

那就是基于浏览器支持的 ESM import特性实现的 bundless, 通过利用浏览器进行模块间依赖加载,而不需要在编译时进行。

换句话说我们不再需要构建一个完整的 Bundle(下文我们称为:Bundless)。当我们修改文件时,浏览器只需要重新加载单个文件即可。

image.png

啊乐同学:那有哪些 Bundless 解决方案 ?

(见下文)Vite就是其一,回顾下Vite的优势:👇

  • 在开发模式下:基于esbuild 预构建依赖(减少HTTP请求) + 浏览器自主加载对应的模块,热更新页面!

  • 在生产模式下:基于Rollup的打包,速度也有一定提升

你一旦体验到Vite的神速!你真的会停不下来 🚀

🍚 饭后思考:

  • esbuild不是比Rollup更快吗?生产模式下,为何不用esbuild构建?👉 参考答案[4]

  • 如果是对于原生ESM不支持的浏览器,开发模式咋处理?👉 参考答案[5]

  • 不是说好bundless?为何还要用esbuild 预构建依赖呢?👉 参考答案[6]

  • Bundless方案除了Vite之外,还有哪些?👉 参考答案[7]

  • Vite 的目标是要干掉 Webpack?👉 参考答案[8]

2. 微前端框架qiankun与Vite

通过上文,我们了解到使用Vite的优势。那是否qiankun支持基于vite构建的子应用集成呢?这里我们以vue3+vite的demo为例

会遇到以下两个需要解决的问题:

  • 开发模式:在开发环境下,如果我们使用 vite 来构建 vue3 子应用,基于vite的构建机制,会在子应的 html 的入口文件的 script 标签上携带 type=module。而我们知道qiankun父应用引入子应用,本质上是将html做为入口文件,并通过import-html-entry这个库去加载子应用所需要的资源列表Js、css,然后通过eval直接执行,而基于vite构建的js中import、export并没有被转码,会导致直接报错(不允许在非 type=module 的 script 里面使用 import)

  • 生产模式:生产模式下,因为没有诸如webpack中支持运行时publicPath,也就是__webpack_public_path__,换句话说就是vite不支持运行时publicPath,其主要作用是用来解决微应用动态载入的脚本、样式、图片等地址不正确的问题。

🌲 拓展阅读:

一开始import-html-entry会过滤掉type=module的文件,导致缺失js却直接eval最终执行出错,后期这个问题官方已经支持👇

  • Support of type=module and nomodule attribute in import-html-entry[9]

目前qiankun官网文档并没有基于Vue3+Vite构建的子应用打包的文档指引,但是我们可以在Github的Issue中找到一些解决方案,主要通过以下这两种方式解决

2.1 只解决生产模式的集成

我们可以通过对子应用vite配置的构建配置改造来实现

首先修改Vite.config.js·中的build配置, 默认Vite的输出目标targetmodule,需改为esnext

然后在配置文件中引入 @rollup/plugin-html[10]

上图省略部分方法,详情请看本节末尾的Demo实例[11],代码实现的目的是为了构建html文件作为子应用的入口,构建结果如下所示👇

其他环节跟基于Webpack的配置大致相同,这里不一一赘述

虽然这种方式针对生产模式可以实现集成,但是存在几个局限性:

  • 我们知道为了让qiankun 拿到子应用export的生命周期函数,所以需要将子应用打包成 umd 格式,而vite的code-splitting(代码分割)功能并不支持iifeumd两种格式,这会导致路由无法实现懒加载。
  • 因为vite不支持运行时publicPath,只能在打包时写死Base配置

  • 图片最终会被打包成 base64

更详细的Demo集成例子:👉  app-vue-vite[12]

2.2 解决开发模式 + 生产模式的集成

单独解决生产模式的集成也不方便,毕竟很多时候需要我们在本地环节进行调试,那有什么方式可以同时让Vite支持这两种模式的集成呢?

Github上有一名开源作者开发了一款Vite插件叫vite-plugin-qiankun,通过这个插件可以在qiankun下走通这两种模式。甚至保留了vite构建模块的优势

  1. 修改Vite.config.js
  1. 修改子应用的main.ts,将生命周期mountbootstrapunmount 等通过插件函数renderWithQiankun在其中暴露完成。其他配置与基于webpack构建的子应用相同
=

⏰ 注意事项:

  • qiankun官方是以window.__POWERED_BY_QIANKUN__来判断当前是否为qiankun环境下,而该插件引用之后是通过qiankunWindow.__POWERED_BY_QIANKUN__来判断

🐸 局限性:

  • 生产模式下依旧不支持publicPath, 需要将vite.config.jsbase配置写死。导致多环境部署不便捷。无法像在webpack结合window.INJECTED_PUBLIC_PATH_BY_QIANKUN + publicpath来解决

更详细的Demo集成例子:👉 viteapp[13]

2.3  Vite对runtime publicpath的支持

目前在Vite官方文档没查阅到相关的配置,但在Github中找到一个插件vite-plugin-dynamic-publicpath[14]。如果你有更好的解决方案,也欢迎评论区留言

2.4 关于Vite的Dotenv配置

如果你从 vue-cli 切换到Vite 需要注意 Dotenv 命名的变化

  • vite前缀是 VITE_ ,vue-cli 是 VUE_APP_
  • 获取方式也不一样,在vite是通过 import.meta.env,而在 vue-cli则是通过 process.env

3.最后

如果你有其他解决方式,欢迎在评论区留言,也可以加我微信,我们一起喝茶🍵 讨论

你好,我是🌲 树酱,请你喝杯🍵 记得三连哦~

1.阅读完记得点个赞哦,有👍 有动力

2.关注公众号前端那些趣事,陪你聊聊前端的趣事

3.文章收录在Github frontendThings 感谢Star✨

参考资料

[1]

webpack: https://webpack.js.org/

[2]

Rollup: https://rollupjs.org/

[3]

Parcel: https://parceljs.org/

[4]

👉 参考答案: https://cn.vitejs.dev/guide/why.html#why-not-bundle-with-esbuild

[5]

👉 参考答案: https://cn.vitejs.dev/guide/#browser-support

[6]

👉 参考答案: https://cn.vitejs.dev/guide/dep-pre-bundling.html

[7]

👉 参考答案: https://cn.vitejs.dev/guide/comparisons.html

[8]

👉 参考答案: https://www.zhihu.com/question/477139054/answer/2156019180

[9]

Support of type=module and nomodule attribute in import-html-entry: https://github.com/umijs/qiankun/issues/507

[10]

@rollup/plugin-html: https://github.com/rollup/plugins/tree/master/packages/html

[11]

Demo实例: https://github.com/gongshun/qiankun-vue-demo/blob/feature/vite-child/app-vue-vite/vite.config.ts

[12]

👉  app-vue-vite: https://github.com/gongshun/qiankun-vue-demo/tree/feature/vite-child/app-vue-vite

[13]

👉 viteapp: https://github.com/tengmaoqing/vite-plugin-qiankun/tree/master/example/viteapp

[14]

vite-plugin-dynamic-publicpath: https://github.com/jy0529/vite-plugin-dynamic-publicpath


浏览 107
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报