0. Введение

В этом руководстве я собираюсь поделиться своим опытом создания библиотеки UMD JavaScript, которую можно использовать везде, библиотека совместима с экосистемами AMD (определение асинхронного модуля) и CommonJS, а также может быть загружена в тег <script>.

Для получения дополнительной информации о AMD, CommonJS и UMD Дэвид Калхун написал отличный блог, в котором сравнил их, его настоятельно рекомендуется прочитать.

Хорошо, приступим!

1. Создайте библиотеку JavaScript.

Мы собираемся создать супер простой калькулятор :)

Создать новый репозиторий

Перейдите в Github и создайте новый проект с именем calculator, инициализируйте репозиторий с помощью README, .gitignore и выберите лицензию.

Клонируйте только что созданный репозиторий и войдите в папку:

> git clone [email protected]:<GH_USERNAME>/calculator.git && \
  cd calculator

Инициализировать пакет NPM и установить зависимости Node.js.

Мы будем использовать Webpack, чтобы объединить библиотеку для распространения, и использовать babel, чтобы помочь перенести синтаксис ES6, чтобы наша библиотека работала в большинстве браузеров.

> npm init -y
> npm i -D webpack webpack-cli babel-loader @babel/core \
  @babel/preset-env

Строим библиотеку

В Webpack есть отличное руководство по созданию библиотек, давайте возьмем его структуру папок.

> mkdir -p {src,dist,examples/browser,examples/node}
> touch src/index.js examples/browser/index.html \
  examples/node/example.js

Теперь структура папок должна выглядеть так:

.
├── dist
├── examples
│   ├── browser
│   │   └── index.html
│   └── node
│       └── example.js
└── src
    └── index.js

Реализуйте библиотеку

Пора реализовать библиотеку!

src / index.js

module.exports = {
  add: (num1, num2) => num1 + num2,
  sub: (num1, num2) => num1 - num2,
};

Как видите, наш калькулятор очень простой.

examples / node / example.js

const {add, sub} = require('./calculator.js');
console.log('1 + 2 = ' + add(1, 2));
console.log('2 - 1 = ' + sub(2, 1));

examples / browser / index.html

<html>
<head>
  <title>Test Calculator</title>
</head>
<body>
  <script src='./calculator.js'></script>
  <script>
    const {add, sub} = calculator;
    console.log('1 + 2 = ' + add(1, 2));
    console.log('2 - 1 = ' + sub(2, 1));
  </script>
</body>
</html>

Вышеупомянутые два файла в основном используются для локального тестирования.

Объедините библиотеку

Нам нужно настроить Webpack и Babel, чтобы они работали на нас.

> touch webpack.config.js .babelrc

webpack.config.js

const path = require('path');
module.exports = {
  mode: 'production',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'calculator.js',
    library: 'calculator',
    libraryTarget: 'umd',
    globalObject: 'this',
  },
  module: {
    rules: [{
      test: /\.js$/,
      exclude: /(node_modules)/,
      use: 'babel-loader',
    }],
  },
};

.babelrc

{
  "presets": ["@babel/preset-env"]
}

И нам нужно обновить package.json. Самая важная часть здесь - изменить свойство main, чтобы оно указывало на dist/calculator.js.

package.json

"main": "dist/calculator.js",
"scripts": {
  "build:browser": "webpack && cp dist/calculator.js examples/browser",
  "build:node": "webpack && cp dist/calculator.js examples/node/ && node examples/node/example.js",
  "build": "webpack"
}

О, убедитесь, что папка dist включена в окончательный дистрибутив, просто раскомментируйте строку dist, если вы ее видите.

.gitignore

...
# Nuxt.js build / generate output
.nuxt
# dist

Протестируйте библиотеку

Давайте проведем небольшое локальное тестирование вручную, чтобы убедиться, что библиотека может работать с Node.js и браузером.

> npm run build:node
1 + 2 = 3
2 - 1 = 1
> npm run build:browser

Отлично! Мы только что завершили наш первый этап, пора выпускать релиз!

2. Автоматизируйте релизы.

Раньше я использовал release-it, чтобы вручную выпустить библиотеку, и мне нужно решить, будет ли это патч, второстепенный или основной выпуск.

Semantic-release использует сообщения фиксации для определения типа выпуска, пока сообщения фиксации следуют стилю обычных фиксаций. А в semantic-release есть несколько подключаемых модулей для создания журнала изменений, публикации в Github и NPM с примечанием к выпуску, так что давайте воспользуемся этим.

Установите зависимости Node.js

> npm i -D husky @semantic-release/{changelog,git,github,npm,commit-analyzer,release-notes-generator} @commitlint/{cli,config-conventional}

Мы используем husky для подключения к командам git, в основном нам нужно убедиться, что сообщения коммитов соответствуют обычному стилю коммитов, вы увидите, как он настроен позже.

Локальные конфигурации

Нам нужно настроить несколько вещей.

> touch commitlint.config.js .releaserc

commitlint.config.js

module.exports = {
  extends: [
    '@commitlint/config-conventional'
  ]
};

Это используется для линтинга наших сообщений о фиксации.

.releaserc

{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    ["@semantic-release/changelog", {
      "changelogFile": "docs/CHANGELOG.md",
    }],
    "@semantic-release/npm",
    ["@semantic-release/git", {
      "assets": ["dist/**/*.{js,css}", "docs", "package.json"],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }],
    "@semantic-release/github"
  ]
}

Это конфигурация семантического релиза. Очень важно знать, что все плагины выполняются в определенном порядке!

Обновите package.json, мы собираемся называть наш пакет, следуя стилю именования пакетов NPM в области видимости. Сбросьте номер версии на 0.0.0, настройте husky, добавив сценарий для семантического выпуска позже.

Обратите внимание, что у нас также есть publishConfig и для свойства access установлено значение «public», это используется, потому что мы принимаем имя пакета области действия.

"name": "@jeantimex/calculator",
"version": "0.0.0",
"husky": {
  "hooks": {
    "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
  }
},
"publishConfig": {
  "access": "public"
},
"scripts": {
  ...
  "semantic-release": "semantic-release"
}

Хорошо, локальная настройка завершена, перейдем к удаленной стороне.

Мы собираемся использовать Travis CI для автоматизации выпуска.

Удаленные настройки: настройка Travis

Сначала активируйте репозиторий, нажмите кнопку Sync account, чтобы Трэвис получил новый репозиторий из Github.

Нажмите кнопку «Настройки» рядом с зеленой кнопкой активации. Мы собираемся создать две переменные среды.

Поскольку мы собираемся опубликовать библиотеку в NPM, нам нужно создать токен NPM для предоставления разрешений для Travis.

> npm login
> npm profile enable-2fa auth-only
> npm token create
┌────────────────┬──────────────────────────────────────┐
│ token          │ 01234567-8901-2345-6789-012345678901 │
├────────────────┼──────────────────────────────────────┤
│ cidr_whitelist │                                      │
├────────────────┼──────────────────────────────────────┤
│ readonly       │ false                                │
├────────────────┼──────────────────────────────────────┤
│ created        │ 2020-05-11T01:53:11.292Z             │
└────────────────┴──────────────────────────────────────┘

Затем нам также необходимо предоставить разрешения для Трэвиса на чтение и запись (публикацию) в Github. Подробнее см. Здесь.

Ниже приведен снимок экрана с разрешениями Github для токена:

Когда у нас появятся токены, добавьте их на странице настроек Трэвиса.

Теперь давайте настроим Трэвиса.

> touch .travis.yml

.travis.yml

language: node_js
node_js:
  - 12
jobs:
  include:
    # Define the release stage that runs semantic-release
    - stage: release
      node_js: lts/*
      script: skip
      deploy:
        provider: script
        skip_cleanup: true
        script:
          - npx semantic-release

По сути, мы просим Трэвиса запустить семантический релиз :)

Освободить библиотеку

Наконец-то пора выпускать релиз!

> git add .
> git commit -m "feat: introduce calculator"
> git push

Вы увидите, как Трэвис создает и развертывает библиотеку.

После его завершения наша библиотека будет опубликована в NPM.

И Github показывает, что новый выпуск будет красивой примечанием к выпуску.

Также автоматически создается журнал изменений!

🎉 Наш калькулятор работает! Поздравляю, у вас получилось!

3. Проверьте библиотеку.

Теперь посмотрим, может ли библиотека работать везде.

Observable работает с библиотеками AMD, поэтому мы можем require наш калькулятор там и посмотреть, работает ли он, да, работает!

Затем давайте проверим, работает ли наша библиотека с CommonJS на repl.

Наконец, наша библиотека должна нормально работать через тег скрипта.

<script src="//unpkg.com/@jeantimex/[email protected]/dist/calculator.js"></script>
<script>
  const {add, sub} = calculator;
  console.log('1 + 2 = ' + add(1, 2));
  console.log('2 - 1 = ' + sub(2, 1));
</script>

Вот и все, надеюсь, вам понравится и эта статья окажется полезной.

Исходный код: https://github.com/jeantimex/calculator