Как стать автором
Обновить

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

Уровень сложностиПростой
Время на прочтение3 мин
Количество просмотров4.8K

Можно написать на 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():

  <script type="module">
    import { mountRT } from "https://esm.sh/release-timeline";
    const options = {...};
    mountRT(options);
  </script>

После этого произойдет монтирование приложения на `<div id="release-timeline" />`

Vue 3 пакет

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

<script setup>
import { ReleaseTimeline, DefaultOptions as options } from "release-timeline";
import "release-timeline/dist/style.css";

// repository to visualize
options.github.owner = "vuesence";
options.github.repo = "release-timeline";
</script>

<template>
  <ReleaseTimeline :options="options" />
</template>

Web component

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

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

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

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

<script setup>
import ReleaseTimeline from "./ReleaseTimeline.vue";

defineProps({
  options: String,
});

let options = window.rt_options;

if (!options) {
  options = JSON.parse(props.options);
}
</script>

<template>
  <ReleaseTimeline :options="options" />
</template>

<style lang="scss">
@import "./css/user-badge.scss";
@import "./css/timeline-item.scss";
@import "./css/timeline-item-issues.scss";
@import "./css/release-timeline.scss";
</style>

Это обертка на 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.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Приходилось ли вам работать с веб компонентами (custom elements)?
28.95% Да11
71.05% Нет27
Проголосовали 38 пользователей. Воздержались 5 пользователей.
Теги:
Хабы:
Всего голосов 1: ↑1 и ↓0+1
Комментарии0

Публикации

Истории

Работа

Ближайшие события

Конференция HR API 2024
Дата14 – 15 июня
Время10:00 – 18:00
Место
Санкт-ПетербургОнлайн
Конференция «IT IS CONF 2024»
Дата20 июня
Время09:00 – 19:00
Место
Екатеринбург
Summer Merge
Дата28 – 30 июня
Время11:00
Место
Ульяновская область