2

我们正在使用 Vue.js + Vuetify.js 开发一种微前端方法来构建我们的网络客户端。整个分布式系统由许多微服务组成,这些微服务执行一些任务并产生一些数据。主要思想是每个服务还提供一个封装编译的Vue组件(片段),显示微服务的数据,并且可以在运行时由客户端按需获取和渲染。所以每个服务都有以下结构:

- ui
- fragments
- service specific source code

ui仅包含使用vue/cli. 该片段比普通的 Vue 组件更重要,如下所示:

<template>
  <v-menu
          ...
        >
          <template v-slot:activator="{ on }">
            <v-text-field
              ...
              v-on="on"
            ></v-text-field>
          </template>
          <v-date-picker v-model="date" no-title @input="menu1 = false"></v-date-picker>
        </v-menu>
</template>

<script>
export default {
  name: 'HelloWorld'
  ...
};
</script>

这个组件被编译成一个包helloworld.umd.min.js,并从服务中作为静态文件提供:

vue-cli-service build --mode production --target lib --inline-vue --formats umd-min --watch --name helloworld ./src/components/HelloWorld.vue

在客户端,我们通过创建一个<script src="http://localhost:2000/helloworld.umd.min.js">带有指向服务片段的 URL 的标签来在运行时将片段绑定到特定页面上。当浏览器获取包时,HelloWorld组件可用并使用 Vue 动态组件呈现,如下所示:

// component is the HellowWorld bundled component
<component :is="component" v-bind="bindProps"></component>

这种方法并不完美,但通常有效。在大多数情况下,如此捆绑的组件被提取、渲染和显示为客户端的一部分,没有任何问题。然而,在上面的示例组件中,我们使用了DatePickerVuetify 示例中的 Vuetify。在客户端渲染此片段会导致浏览器选项卡完全崩溃,因此该选项卡仍然不负责。我已经发现这是由作用域插槽引起的,因此删除以下插槽定义将修复浏览器崩溃:

<template v-slot:activator="{ on }">...

此外,其他复杂的 Vuetify 组件也无法通过使用所描述的方法正常工作。例如 VuetifyCarouselTabs组件(选项卡)是没有选项卡内容的渲染端,如下面的屏幕截图所示: 在此处输入图像描述

主要问题

编译嵌套的 Vuetify 组件会导致所描述的渲染问题是什么?将 Vue.js + Vuetify.js 组件编译成一个包以避免这个问题的正确方法是什么?

任何讨论都会有所帮助!

4

1 回答 1

1

编辑:虽然我在这里提出了几种解决方案,但我还没有测试过任何一个,它应该与一粒盐一起服用。我最近开始使用微前端,所以我对它们的工作原理有一个粗略的了解。如果我说错了,请毫不犹豫地修正我的答案

我也在问自己同样的问题。我怀疑这种奇怪的行为是由 treeshaking 引起的。我认为,如果您在所有组件中使用 Vuetify,则可以在要导入的捆绑脚本之外使用带有 vuetify 的脚本标签。

<script src="http://vuetify.cdn" />

<!-- All below should be microfrontends, suposed to be written in Vue with Vuetify -->
<script src="helloworld.umd.min.js" />
<script src="foo.umd.min.js" />
<script src="bar.umd.min.js" />

如果您所有的微前端都基于 Vuetify,您可以更改您的 webpack 配置以不捆绑 vuetify 并通过 CDN 在全局宏前端中使用它。这会有一个缺点,但是,如果您的任何前端是用 Angular 制作的,那么用户会下载 Vuetify 而不会使用它,您应该找到一种方法来逐个下载这些库。这应该可以使用导入方法的上下文进行管理。

该库single-spa应该允许您执行以下操作:

registerComponent({
  renderOn: "/hello-world",
  import: () => {
    if (!window.vuetify) {
      window.vuetify = true;
      const script = document.createElement("script")
      script.src = "http://vuetify.cdn"
      document.appendChild(script);
    }
    
    return import("helloworld.umd.min.js")
  }
})

我知道这看起来很hacky,但这应该可以解决问题,防止您的用户下载他们当时不需要的内容,并允许您更好地控制下载流程,将 vuetify 缓存在他们的浏览器本地

于 2021-02-04T20:11:47.220 回答