Публикация веб-компонентов с помощью Vite, Lit и Storybook

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

Я думал о том, чтобы написать простые веб-компоненты, но в них много «котловой плиты», поэтому я выбрал Lit для этой работы. И Vite для разработки и упаковки.

Создание нового проекта Vite

Начнем с установки нового проекта Vite.

npm create vite@latest my-webcomponents -- --template lit-ts
Войти в полноэкранный режим Выйдите из полноэкранного режима

Установите Storybook

npx sb@latest init --builder storybook-builder-vite
Войдите в полноэкранный режим Выйти из полноэкранного режима

Storybook по умолчанию использует webpack, но поскольку мы используем Vite, мы предпочтем использовать плагин storybook-builder-vite.

Storybook 7 будет лучше и более модульным, когда дело доходит до того, какую систему сборки он использует под капотом, будь то vite, esbuild, swc…

Изменения в конфигурации Vite

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

// vite.config.js
import { defineConfig } from 'vite'

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: 'src/my-element.ts',
      formats: ['es'],
    },
    rollupOptions: {
      // If we want to publish standalone components we don't externalize lit,
      // if you are going to use lit in your own project, you can make it a dep instead.
      // external: /^lit/, <-- comment this line
    },
  },
})
Вход в полноэкранный режим Выход из полноэкранного режима

Изменения в конфигурации Typescript

Поскольку мы добавили storybook, нам нужно исключить файлы .stories.ts из компиляции typescript, иначе при публикации в NPM они будут включены.

// tsconfig.json
{
  "compilerOptions": {
    "module": "esnext",
    "lib": ["es2017", "dom", "dom.iterable"],
    "declaration": true,
    "emitDeclarationOnly": true,
    "outDir": "./types",
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "useDefineForClassFields": false
  },
  "include": ["src/**/*.ts"],
  "exclude": ["src/**/*.stories.ts"], // <-- this is the line we need to add
  "references": [{ "path": "./tsconfig.node.json" }]
}
Вход в полноэкранный режим Выход из полноэкранного режима

Изменения в конфигурации сборника рассказов

Для работы storybook-builder-vite в конфиге storybook необходимо изменить конфиг vite. Нам нужно включить и исключить некоторые пакеты из конфигурации vite.

// .storybook/main.js
module.exports = {
  stories: ['../src/ **/*.stories.mdx', '../src/** /*.stories.@(js|jsx|ts|tsx)'],
  addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
  framework: '@storybook/web-components',
  core: {
    builder: 'storybook-builder-vite',
  },
  async viteFinal(config, { configType }) {
    // customize the Vite config here
    config.optimizeDeps.include = [...(config.optimizeDeps?.include ?? []), '@storybook/web-components']
    config.optimizeDeps.exclude = [...(config.optimizeDeps?.exclude ?? []), 'lit', 'lit-html']

    // return the customized config
    return config
  },
}
Вход в полноэкранный режим Выход из полноэкранного режима

Теперь у нас есть работающий Storybook

Существует недостаток использования веб-компонентов (lit) в storybook, который заключается в том, что он не поддерживает горячую перезагрузку. Поэтому каждое изменение будет заставлять Storybook делать полную перезагрузку. Надеюсь, в будущем эта проблема будет решена.

Публикация в NPM

В этом разделе описаны шаги, необходимые для публикации в NPM, если вы не планируете публиковать в NPM, можете пропустить этот раздел.

Во-первых, если вы хотите публиковать автономные веб-компоненты, вам нужно будет переместить lit в devDependency в вашем package.json.

  • Также вместо экспорта только одного файла dist/my-element.es.js мы изменим его так, чтобы у нас был файл barrel, который экспортирует все компоненты.
  • и изменим оба index.html и vite.config.js, чтобы они указывали на src/index.ts.
  • Затем нам также нужно изменить package.json, чтобы экспортировать правильные файлы.
  • И мы также хотим сделать пакет публичным, удалив "private": true и выбрав имя и лицензию.

После этого мы должны быть готовы к работе, выполнив следующие действия

npm run build
Войти в полноэкранный режим Выйти из полноэкранного режима

затем проверить /dist/, чтобы убедиться, что там находятся нужные файлы, и что наш package.json указывает на эти файлы.

затем мы можем запустить

npm publish
Войти в полноэкранный режим Выйти из полноэкранного режима

Если все прошло успешно, вы сможете использовать ваш новый пакет, импортировав его

<script type="module" src="https://cdn.skypack.dev/my-element"></script>
<my-element name="Lit"></my-element>
Войдите в полноэкранный режим Выйти из полноэкранного режима

Пример репозитория

Если вы не хотите все копировать и вставлять, я создал демонстрационный проект на github. вы можете найти его здесь https://github.com/leon/blog-vite-lit-storybook.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *