Узнайте, как использовать Vue для создания пользовательских элементов, которые легко добавить в файлы Markdown вашего статического сайта.

вступление

Недавно я переделал Table to Markdown, преобразовав его из проекта Nuxt в статический сайт, созданный с помощью Blurry, предварительной версии генератора статических сайтов (SSG), над которым я работал. Я хотел простоты и производительности статического сайта, но мне все еще нужна была интерактивность.

Хотя я использую Blurry для создания статических сайтов, это руководство подойдет для любого генератора статических сайтов, например Hugo или Jekyll.

«Какая простота и производительность?» ты спрашиваешь? Что ж, одна проблема, с которой я столкнулся при работе с гибридной версией Table to Markdown от Nuxt.js, заключалась в том, что было трудно точно подсчитать просмотры страниц, поскольку иногда они отслеживались в коде на стороне сервера, а иногда — в коде на стороне клиента. — и мне не хотелось считать их дважды. У меня были те же проблемы с показами рекламы, и случайный подсчет их более одного раза мог привести к проблемам с любыми рекламными сетями, которые я использовал.

Со статическим сайтом эти просмотры страниц и показы рекламы не требовали никаких размышлений, потому что они срабатывали при загрузке HTML, вот и все.

Использование Vue для всего сайта привело к тому, что для вещей, для которых мне действительно не нужен был JavaScript, например для навигации по сайту, потребовалось довольно много JavaScript. Использование статического сайта означало, что я мог полагаться на обычную навигацию по гиперссылкам, не требуя ни одной строки JS, что означало более быструю загрузку страниц.

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

Веб-компоненты с Vue

Чтобы упростить интеграцию Vue с моим статическим сайтом, а не использовать Vue для управления всей страницей, я решил использовать Vue в одном пользовательском HTML-элементе через веб-компоненты.

Чтобы получить представление о том, к чему мы стремимся, вот фрагмент файла Markdown из таблицы в Markdown:

# Convert spreadsheet cells to Markdown

<div class="custom-element-container">
  <table-converter></table-converter>
</div>

Table to Markdown makes it easy to convert cells from Microsoft Excel, [...]<div class="custom-element-container">
  <table-converter></table-converter>
</div>
Table to Markdown makes it easy to convert cells from Microsoft Excel, [...]

Веб-компоненты позволяют создавать собственные автономные HTML-элементы, которые могут использовать JavaScript, чтобы делать все, что вы хотите. Большим преимуществом является то, что после включения JS, в котором определены веб-компоненты, вы можете использовать их так же, как обычный HTML-элемент, например <p> или <a>.

Звучит хорошо, а? Почти слишком хорошо? Ну, с этим подходом есть некоторые недостатки, но мы не можем их сгладить.

Морщины

Изменение макета после загрузки веб-компонента

Если вы следите за этим блогом, вы наверняка заметили, что у меня есть интерес к показателям PageSpeed.

При использовании веб-компонентов следует помнить, что их высота не учитывается при рендеринге страницы.

Сопоставляя высоту ваших веб-компонентов и высоту оболочки веб-компонента, вы можете избежать сдвигов макета контента, которые мешают вашим посетителям:

/* Main stylesheet */
.custom-element-container {
  min-height: 300px;
}

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

Область действия CSS

Чтобы обеспечить единообразие стилей статического сайта и веб-компонентов, вы можете использовать один и тот же файл CSS в обоих местах. Просто импортируйте свой файл CSS в свой компонент Vue:

<style>
@import('main.css')
</style>

Сохраняйте этот CSS-файл как можно меньшего размера, поскольку его содержимое может быть загружено дважды. Включите только необходимые стили, а для повышения скорости страницы рассмотрите возможность встраивания этого CSS-файла в базовый файл шаблона вашего статического сайта.

Дочерний компонент CSS

Если ваш однофайловый компонент Vue использует другие компоненты Vue, не являющиеся пользовательскими элементами, с тегами <style>, вы можете быть удивлены, увидев, что эти стили исчезают при использовании вашего пользовательского элемента.

Для некоторых обходных путей:

  • @import() соответствующий CSS в ваших дочерних компонентах
  • Вместо определения области действия CSS (<style scoped>) в компоненте верхнего уровня определите правила CSS, которые также будут применяться к дочерним компонентам.
  • Создавайте классы, элементы или используйте пользовательские свойства (переменные) CSS во встроенных атрибутах style=""/:style="{}" элементов в ваших дочерних компонентах.

Выполнение

Теперь, когда мы определили некоторые недостатки и способы их устранения, пришло время посмотреть, как преобразовать файл Vue в пользовательский элемент.

Конфигурация Vite

Во-первых, обновите плагин Vue для Vite, чтобы создавать веб-компоненты, и настройте Vite для размещения ваших встроенных компонентов там, где вы хотите:

import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
  // Get Vue to output custom elements
  plugins: [vue({ customElement: true })],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  build: {
    // Specify a directory in your SSG's build directory
    outDir: 'dist/elements',
    rollupOptions: {
      // Improvement: loop through files in the elements directory to build this object
      input: {
        'your-component': resolve(__dirname, 'src/elements/your-component.ts'),
      },
      // Use predictable file names
      output: {
        entryFileNames(chunkInfo) {
          return `${chunkInfo.name}.js`
        },
      },
    }
  }
})

Дополнительную информацию об использовании Vue для создания веб-компонентов см. в Документации по Vue.

Файл пользовательского элемента

В отдельном файле определите свой компонент Vue как пользовательский элемент, который сделает ваш компонент доступным для использования в HTML DOM:

// src/elements/your-component.ts
import { defineCustomElement } from 'vue'

import YourComponent from '@/components/YourComponent.vue'

customElements.define('your-component', defineCustomElement(YourComponent))

Создание отдельного файла для каждого веб-компонента может помочь уменьшить размер пакетов JavaScript за счет включения только необходимого кода для этого компонента.

Вы также можете определить множество пользовательских элементов в одном файле. Дополнительную информацию и рекомендации по созданию библиотеки пользовательских элементов см. в документах Vue.

Включите JS и пользовательский элемент в свои файлы SSG.

Теперь все, что осталось сделать, это включить файл вашего пользовательского элемента .js в соответствующий файл шаблона вашего SSG:

<script src="/elements/your-component.js" type="module"></script>

<your-component></your-component>

Заворачивать

Это обертка.

Эта статья завершена как однофайловый компонент Vue в пользовательском элементе веб-компонента после выполнения вышеуказанных шагов.