Содание Web components на Vue 3

0a9c2daff9f793f945d3770c3bd84d5b.jpg

Можно написать на Vue 3 какой-нибудь полезный компонент и захотеть дать возможность использовать его не только в Vue проектах, но и на любых других фронтендах. Сделать это несложно через регистрацию его как web component, или подключение «микро-фронтендом». Оба варианта будут рассмотрены ниже.

Рассмотрим универсализацию на примере release-timeline

При разработке используем Vite с двумя конфигами — один непосредственно для разработки и запуске в Dev режиме на сервере Vite, другой — для билда библиотеки.

// package.json

"scripts": {
  "build": "vite build",
  "build:lib": "vite --config vite.config-lib.ts build"

В vite.config-lib.ts указана точка входа index.ts и также указано, чтобы не включать в бандл дистрибутив Vue.

Самое интересное это именно точка входа index.ts. Она общая для всех режимов — npm vue библиотека, web component и микро-фронтенд. Это очень удобно при разработке и сборке.

import { createApp, defineCustomElement } from "vue";
import { DefaultOptions } from "./options";
import ReleaseTimelineCE from "./ReleaseTimeline.ce.vue";
import ReleaseTimeline from "./ReleaseTimeline.vue";
import App from "./App.vue";

if (globalThis.window) {
  window.customElements.define("release-timeline", defineCustomElement(ReleaseTimelineCE));
}

function mountRT(initOptions) {
  const app = createApp(App, { initOptions });
  app.mount("#release-timeline");
}

export { ReleaseTimeline, DefaultOptions, mountRT };

export {};

Микро-фронтенд

В данном режиме используется вызов mountRT():

  

После этого произойдет монтирование приложения на `

`

Vue 3 пакет

Библиотека экспортирует на 16 строке все нужные модули — ReleaseTimeline и DefaultOptions, и их можно сразу использовать в коде через импорт, как обычно.



Web component

С веб компонентами два момента:

  1. В качестве пропсов они принимают только строки. Поэтому если вам нужно передать массив или объект (как в нашем случае), нужно его либо сериализовать и десериализовать, либо передать опции через общий контекст — window. Не очень красиво, но работает.

  2. При подключении в проект как Vue библиотеку, CSS стили нужно импортировать отдельно. Практически всегда. В случае веб компонент стили итегрируются и не доступны для изменения снаружи, за исключением CSS переменных.

Чтобы организовать работу со стилями нам нужен ReleaseTimeline.ce.vue:





Это обертка на ReleaseTimeline, которая, во-первых, обрабатывает параметры, переданные через window, и во-вторых, работает со стилями.

Если бы главный компонент был один, мы могли бы поместить все стили в его style секцию. Но Vite при билде не собирает стили из компонент-потомков, поэтому приходится это делать вручную в ReleaseTimeline.ce.vue. Именно поэтому пришлось размещать их в отдельных файлах и использовать SCSS импорт. Суффикс ce.vue говорить сборщику использовать специальный режим для `custom elements`.

Возвращаясь к index.ts, — на 7 строке мы проверяем, что находимся в браузере (на случай использования в SSR/SSG средах — например, при сборке VitePress), и затем регистрируем веб компонент.

В итоге, для превращения Vue компонента в web component, нужна простая обертка и несколько строк в index.ts

Вот здесь — wc-demo — можно посмотреть код html страницы, чтобы увидеть пример использования release-timeline как веб компонента. Дистрибутив Vue подключается отдельно.

Наш Telegram-канал о Vue и фронтенд-разработке:  @vuefaq и вебсайт: Vue‑FAQ.org.

© Habrahabr.ru