Spec-Zone.ru › Lit 2

Публикация

На этой странице приведены рекомендации по публикации компонента Lit в npm — менеджере пакетов, которым пользуется подавляющее большинство библиотек и разработчиков JavaScript. См. раздел Стартовые наборы: в нём представлены шаблоны компонентов, подготовленные для публикации в npm.

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

Чтобы опубликовать компонент в npm, ознакомьтесь с инструкциями по публикации пакетов npm.

В конфигурации package.json должны быть поля type, main и module:

package.json

{
  "type": "module",
  "main": "my-element.js",
  "module": "my-element.js"
}

Также создайте файл README с описанием использования компонента.

Публикация современного JavaScript

Мы рекомендуем публиковать модули JavaScript со стандартным синтаксисом ES2019, поскольку он поддерживается всеми браузерами с автоматическим обновлением и позволяет создавать самый быстрый и компактный JavaScript. Пользователи вашего пакета всегда могут воспользоваться компилятором для поддержки старых браузеров, но они не смогут преобразовать устаревший JavaScript в современный синтаксис, если вы скомпилируете код до публикации.

Однако важно, что если вы используете недавно предложенные или нестандартные возможности JavaScript, такие как TypeScript, декораторы и поля классов, их следует скомпилировать в стандартный ES2019, который поддерживается браузерами изначально, до публикации в npm.

Компиляция с помощью TypeScript

Следующий пример JSON — это частичный tsconfig.json, в котором используются рекомендуемые параметры для целевой версии ES2019, включается компиляция декораторов и выводятся типы .d.ts для пользователей:

tsconfig.json

"compilerOptions": {
  "target": "es2019",
  "module": "es2015",
  "moduleResolution": "node",
  "lib": ["es2019", "dom"],
  "declaration": true,
  "declarationMap": true,
  "experimentalDecorators": true,
  "useDefineForClassFields": false
}

Обратите внимание: для параметра useDefineForClassFields должно быть задано значение false только в том случае, если target имеет значение esnext или выше, однако мы рекомендуем явно убедиться, что для этого параметра задано значение false.

При компиляции из TypeScript следует указать файлы объявлений (сгенерированные на основе указанного выше declaration: true) для типов компонента в поле types файла package.json и убедиться, что файлы .d.ts и .d.ts.map также публикуются:

package.json

{
  ...
  "types": "my-element.d.ts"
}

Дополнительную информацию см. в документации по tsconfig.json.

Компиляция с помощью Babel

Чтобы скомпилировать компонент Lit, использующий предлагаемые возможности JavaScript, ещё не включённые в ES2019, используйте Babel.

Установите Babel и необходимые плагины Babel. Например:

npm install --save-dev @babel/core
npm install --save-dev @babel/plugin-proposal-class-properties
npm install --save-dev @babel/plugin-proposal-decorators

Настройте Babel. Например:

babel.config.js

const assumptions = {
  "setPublicClassFields": true
};

const plugins = [
  ['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true } ],
  ["@babel/plugin-proposal-class-properties"],

];

module.exports = { assumptions, plugins };

Запустить Babel можно с помощью плагина для сборщика, например @rollup/plugin-babel, или из командной строки. Дополнительную информацию см. в документации Babel.

Рекомендации по публикации

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

Не импортируйте полифилы в модули

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

Пакетам могут потребоваться полифилы для тестов и демонстраций. Если они нужны, добавляйте их только в devDependencies.

Не объединяйте, не минифицируйте и не оптимизируйте модули

Объединение и другие оптимизации относятся к приложению. Объединение повторно используемого компонента перед публикацией в npm может также привести к тому, что в приложении пользователя окажется несколько версий Lit (и других пакетов), поскольку npm не может удалить дубликаты пакетов. Это увеличивает размер приложения и может привести к ошибкам.

Оптимизация модулей перед публикацией также может помешать оптимизациям на уровне приложения.

Объединение и другие оптимизации могут быть полезны при раздаче модуля с CDN, однако, поскольку пользователям могут понадобиться несколько пакетов, зависящих от Lit, раздача с CDN может привести к загрузке большего объёма кода, чем необходимо. Поэтому мы рекомендуем для приложений, критичных к производительности, всегда собирать проект из npm, где можно удалить дубликаты пакетов, вместо загрузки объединённых пакетов с CDN.

Если вы хотите поддержать использование с CDN, рекомендуем чётко разделить модули для CDN и модули, предназначенные для использования в production. Например, поместите их в отдельную папку или добавляйте только в выпуск GitHub, но не включайте в публикуемый модуль npm.

Указывайте расширения файлов в спецификаторах импорта

Разрешение модулей Node не требует указания расширений файлов, поскольку, если расширение не задано, Node ищет в файловой системе файлы с одним из нескольких возможных расширений. При импорте some-package/foo Node импортирует some-package/foo.js, если этот файл существует. Аналогичным образом инструменты сборки, преобразующие спецификаторы пакетов в URL, могут выполнять такой поиск в файловой системе во время сборки.

Однако спецификация карт импорта, которую браузеры начинают внедрять, позволит браузеру загружать модули с простыми спецификаторами пакетов непосредственно из исходного кода, без преобразований. Для этого в манифесте карты импорта задаётся соответствие спецификаторов импорта URL (вероятно, манифест будет автоматически сгенерирован инструментом на основе, например, установленного npm-пакета).

Карты импорта позволяют сопоставлять импорты с URL, но поддерживают только два типа сопоставления: точное и по префиксу. Это означает, что можно легко задать псевдоним для всех модулей пакета, сопоставив имя пакета с одним префиксом URL. Однако, если вы пишете импорты без расширений файлов, в карту импорта потребуется добавить отдельную запись для каждого файла в пакете. Это может значительно увеличить размер карты импорта.

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

Публикуйте типы TypeScript

Чтобы с элементом было проще работать из TypeScript, мы рекомендуем:

  • Добавлять запись HTMLElementTagNameMap для всех элементов, написанных на TypeScript.

    @customElement('my-element')
    export class MyElement extends LitElement { /* ... */ }
    
    declare global {
      interface HTMLElementTagNameMap {
        "my-element": MyElement;
      }
    }
  • Публиковать типы .d.ts в пакете npm.

Дополнительную информацию о HTMLElementTagNameMap см. в разделе Предоставление качественных типов TypeScript.

Определяйте элементы самостоятельно

Модуль, в котором объявлен класс веб-компонента, всегда должен содержать вызов customElements.define() (или декоратор @customElement), чтобы определить элемент.

Сейчас веб-компоненты всегда определяются в глобальном реестре. Для каждого определения пользовательского элемента необходимо использовать уникальное имя тега и уникальный класс JavaScript. Попытка зарегистрировать одно и то же имя тега или один и тот же класс дважды завершится ошибкой. Просто экспортировать класс и рассчитывать, что пользователь вызовет define(), ненадёжно. Если два разных компонента зависят от общего третьего компонента и оба пытаются определить его, один из них завершится ошибкой. Этой проблемы не возникает, если элемент всегда определяется в том же модуле, где объявлен его класс.

Недостаток такого подхода заключается в том, что два разных элемента с одинаковым именем тега нельзя импортировать в один проект.

В платформу постепенно добавляются области видимости реестров пользовательских элементов. Реестры с областью видимости позволяют пользователю компонента выбирать имя тега пользовательского элемента для заданной области теневого корня. Когда браузеры начнут поддерживать эту возможность, станет возможным публиковать для каждого компонента два модуля: один будет экспортировать класс пользовательского элемента без побочных эффектов, а другой — регистрировать его глобально с заданным именем тега.

До тех пор мы рекомендуем продолжать регистрировать элементы в глобальном реестре.

Экспортируйте классы элементов

Чтобы поддержать создание подклассов, экспортируйте класс элемента из модуля, в котором он определён. Это позволит создавать подклассы для расширения функциональности, а также регистрировать элементы в реестрах пользовательских элементов с областью видимости в будущем.

Дополнительная литература

Более общие рекомендации по созданию качественных повторно используемых веб-компонентов см. в документе Контрольный список Gold Standard для веб-компонентов.

Редактировать эту страницу

© Google LLC
Licensed under the Creative Commons Attribution 3.0 Unported License.
https://lit.dev/docs/v2/tools/publishing/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API