Создание микро-интерфейсов с помощью скомпилированных инкапсулированных компонентов Vue.js + Vuetify.js

Мы разрабатываем подход к микро-интерфейсу с использованием Vue.js + Vuetify.js для создания нашего веб-клиента. Вся распределенная система состоит из множества микросервисов, которые выполняют некоторые задачи и производят некоторые данные. Основная идея состоит в том, что каждая служба также предоставляет инкапсулированный скомпилированный компонент (фрагмент) Vue, который отображает данные микросервиса и может быть извлечен и обработан клиентом по запросу во время выполнения. Итак, каждая служба имеет следующую структуру:

- ui
- fragments
- service specific source code

ui просто содержит приложение Vue + Vuetify, созданное с помощью 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>

Этот подход не идеален, но в целом работает. В большинстве случаев связанные таким образом компоненты извлекаются, визуализируются и отображаются как часть клиента без каких-либо проблем. Однако в приведенном выше примере компонента мы используем Vuetify DatePicker из примеров Vuetify. Визуализация этого фрагмента на стороне клиента приводит к полной сбою вкладки браузера, поэтому вкладка по-прежнему не несет ответственности. Я уже выяснил, что это вызвано слотом с ограниченной областью видимости, поэтому удаление определения следующего слота исправит сбой браузера:

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

Также другие сложные компоненты Vuetify работают некорректно при использовании описанного подхода. Например, компоненты Vuetify Carousel или Tabs (вкладки) визуализируются без содержимого вкладок, как показано на следующем снимке экрана. : введите описание изображения здесь

Основные вопросы

Что может вызвать описанные проблемы с рендерингом при компиляции вложенных компонентов Vuetify? Каким будет правильный подход к компиляции компонентов Vue.js + Vuetify.js в пакет, чтобы избежать этих проблем?

Любые обсуждения были бы полезны!


person Serg    schedule 25.02.2020    source источник


Ответы (1)


Изменить: Хотя я предлагаю здесь несколько решений, я не тестировал ни одно из них, и к нему следует относиться с недоверием. Я начал использовать микрофронтенды недавно, поэтому имею лишь приблизительное представление о том, как они работают. Не сомневайтесь, исправьте мой ответ, если я скажу что-то не так

Я задавал себе тот же вопрос. Я подозреваю, что это странное поведение вызвано дрожанием деревьев. Я думаю, что если вы используете 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, вы можете изменить конфигурацию своего веб-пакета, чтобы не связывать 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")
  }
})

Я знаю, что это кажется хакерским, но это должно помочь, не позволяя вашему пользователю загружать то, что ему не нужно в данный момент, и позволяя вам больше контролировать поток загрузок, имея vuetify, кэшируемый локально в своем браузере.

person Allan Lima    schedule 04.02.2021
comment
Спасибо, что поделились своими мыслями. Интерфейс основан только на Vue и Vuetify. Что я не упомянул в вопросе, так это то, что я импортировал компоненты Vuetify непосредственно во фрагмент, чтобы он работал в первую очередь. Мне также пришлось инициализировать Vuetify во фрагменте. Глобальная инициализация Vuetify через CDN - интересная идея. Не уверен, что это повлечет за собой другие недостатки в нашем процессе сборки. Весь подход довольно наивен. Вы можете посмотреть специальные библиотеки, такие как Luigi. - person Serg; 10.02.2021
comment
... Сейчас моя команда сосредоточена на другом. Ждем зрелости Vue 3. Затем мы снова хотим заняться этой проблемой. Не стесняйтесь размещать здесь свои выводы. - person Serg; 10.02.2021