DevGang
Авторизоваться

Использование Bazel с TypeScript

Bazel — это проект с открытым исходным кодом, изначально созданный Google, доработанный и протестированный в течение многих лет для запуска ресурсоемких, критически важных сервисов и приложений. Это отличный выбор для создания и тестирования проектов. Расширенное выполнение распределенного кэширования Bazel создает быстрые инкрементные и настраиваемые сборки, перестраивая только то, что необходимо. Он работает на нескольких языках и платформах, таких как Java, Go и JavaScript, а также в операционных системах, таких как IOS, Android, Linux и Windows.

Bazel автоматизирует сборку и тестирование программного обеспечения для таких задач, как запуск компиляторов и компоновщиков для создания исполняемых программ и библиотек, таких как преобразование файла JAVA в исполняемый файл JAR. Bazel можно сравнить с такими инструментами, как Apache Maven, Apache Ant, GNU Make или Gradle, но он стоит выше всех благодаря многоязычной и многоплатформенной поддержке. Он поставляется с настраиваемым языком высокого уровня Starlark, который описывает, как должен быть построен проект. Масштабируемость Bazel позволяет ему расти вместе с вашей кодовой базой и организацией. Он может работать с кодовыми базами любого размера, будь то огромные монолитные репозитории или несколько репозиториев.

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

В этом руководстве рассматривается, как опытные разработчики могут добавить Bazel в проект TypeScript для запуска быстрых и настраиваемых сборок. Вы научитесь настраивать Bazel в соответствии со своими потребностями с помощью правил Bazel. Вы также научитесь добавлять тесты, запускать их с помощью Bazel, а затем публиковать в npm.

TypeScript и Bazel

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

При использовании Bazel вы столкнетесь с несколькими правилами Bazel, созданными на основе компилятора TypeScript, которые можно использовать при настройке Bazel. Правила Bazel, которые обычно называют файлами BUILD, определяются как набор команд, которые работают с входными файлами для создания выходных данных, например, для преобразования файла TypeScript в файл JavaScript. Эти правила часто являются частью пакета Bazel; например, rules_nodejs. Некоторые из этих правил заключаются в следующем:

  1. tsc: это встроенный компилятор TypeScript, разработанный командой Microsoft. После загрузки rules_nodejs tsc можно показать в файле Bazel BUILD, добавив в него оператор загрузки load("@npm//typescript:index.bzl", "tsc"). Вот пример использования tsc в конфигурационном файле Bazel.
  2. ts_config: это правило используется для добавления файла конфигурации TypeScript в Bazel. С помощью этого правила вы можете передать ему файл tsconfig.json или даже добавить к нему дополнительный файл конфигурации JSON с помощью параметра deps.
  3. ts_project: это правило Bazel, которое может заменить правило tsc. Это позволяет использовать множество параметров, таких как srcs, исходные данные для переноса; out_dir, каталог, куда должны помещаться выходные файлы; tsconfig, используемый файл TSConfig; или объект JSON, содержащий правила транспиляции. Любое правило, которое работает с tsc, должно работать и с ts_project.

Создайте приложение TypeScript с помощью Bazel

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

Начните с создания каталога с именем demo_bzl_app:

$ mkdir demo_bzl_app && cd demo_bzl_app

Запустите проект Node.js, выполнив следующую команду:

$ npm init

Затем установите TypeScript:

$ npm config set save-prefix=''
$ npm install typescript@4.9.5 --save-dev

Теперь в вашем каталоге должны быть файлы package.json и package-lock.json.

Далее вы создадите файл tsconfig.json, в котором вы определите параметры компилятора TypeScript. Это можно сделать автоматически, выполнив следующее:

npx tsc --init --rootDir src --esModuleInterop --resolveJsonModule \
--lib 'es6, dom' --module commonjs --allowJs true --noImplicitAny true

Чтобы узнать больше о том, что означают эти параметры, см. документ Справочник по TSConfig. На этом этапе у вас должен быть файл tsconfig.json в корневом каталоге.

Теперь создайте каталог src, в котором будет жить код приложения. Внутри него создайте файл с именем index.ts. Расширение .ts указывает, что файл является файлом TypeScript:

$ mkdir src && touch readme.MD && touch src/index.ts

В файле index.ts добавьте следующий код:

index.ts
#!/usr/bin/env node

"use strict";
export function adder (one: number, two: number) {
    return one + two
}

export function concatenate (one: string, two: string) {
    return one + two
}


console.log("Hello! Welcome.");

Обычно файлы TypeScript .ts должны быть скомпилированы в файлы .js для выполнения. Обычно для компиляции кода используется npx tsc. tsc прочитает файл tsconfig.json и применит конфигурации при компиляции кода JavaScript. Но в этом уроке вы увидите, как вместо этого использовать Bazel.

Чтобы начать использовать Bazel, установите его на свой компьютер. Bazel можно установить на Linux, macOS и Windows. Чтобы узнать, как установить его для вашей платформы, воспользуйтесь их руководством по установке. Подтвердите, что он у вас установлен, набрав bazel в командной строке:

Скриншот Bazel
Скриншот Bazel

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

Файл WORKSPACE помогает Bazel идентифицировать каталог как проект Bazel, а файл BUILD помогает Bazel идентифицировать каталог как пакет Bazel. Проект Bazel может иметь в себе один или несколько пакетов, а пакет может содержать подпакеты или подкаталоги, содержащие файлы BUILD, таким образом образуя иерархию.

Создайте файл WORKSPACE и файл BUILD в корневом каталоге demo_bzl_app:

touch WORKSPACE && touch BUILD

В будущих проектах вы можете назначить каталог рабочим пространством Bazel, создав в этом каталоге пустой файл с именем WORKSPACE. Файл WORKSPACE может быть пустым, но он также может содержать инструкции для Bazel по загрузке зависимостей, необходимых для проекта Bazel.

В файле WORKSPACE добавьте следующий код:

WORKSPACE

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
    name = "aspect_rules_ts",
    sha256 = "7d964d57c6e9a54b0ce20f27e5ea84e5b42b6db2148ab7eb18d7110a082380de",
    strip_prefix = "rules_ts-1.2.4",
    url = "https://github.com/aspect-build/rules_ts/releases/download/v1.2.4/rules_ts-v1.2.4.tar.gz",
)

##################
# rules_ts setup #
##################
# Fetches the rules_ts dependencies.
# If you want to have a different version of some dependency,
# you should fetch it *before* calling this.
# Alternatively, you can skip calling this function, so long as you've
# already fetched all the dependencies.
load("@aspect_rules_ts//ts:repositories.bzl", "rules_ts_dependencies")

rules_ts_dependencies(
    # This keeps the TypeScript version in-sync with the editor, \
    which is typically best.
    ts_version_from = "//:package.json",

    # Alternatively, you could pick a specific version, or use
    # load("@aspect_rules_ts//ts:repositories.bzl", "LATEST_VERSION")
    # ts_version = LATEST_VERSION
)

# Fetch and register node, if you haven't already
load("@rules_nodejs//nodejs:repositories.bzl", "DEFAULT_NODE_VERSION", \
"nodejs_register_toolchains")

nodejs_register_toolchains(
    name= "node",
    node_version = DEFAULT_NODE_VERSION,
)

# Register aspect_bazel_lib toolchains;
# If you use npm_translate_lock or npm_import from aspect_rules_js \
you can omit this block.
load("@aspect_bazel_lib//lib:repositories.bzl", \
"register_copy_directory_toolchains", \
"register_copy_to_directory_toolchains")

register_copy_directory_toolchains()

register_copy_to_directory_toolchains()

Файл BUILD содержит несколько инструкций для Bazel по сборке пакета; эти инструкции называются правилами. В файле BUILD добавьте следующие правила для сборки файла TypeScript в src/index.ts:

WORKSPACE
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")

ts_project(
    name="transpile",
    srcs = ["src/index.ts"],
    tsconfig= "//:tsconfig.json",
    allow_js=True,
    resolve_json_module=True
)

Предыдущие правила в файле BUILD сообщают Bazel следующее:

  • Правило называется transpile.
  • Входные файлы, которые необходимо скомпилировать, находятся по пути src/index.ts.
  • Bazel должен извлечь конфигурацию компилятора из файла tsconfig.json в текущем каталоге, обозначаемом //.
  • allow_js имеет значение True, что означает, что TypeScript должен разрешать импорт файлов JavaScript в файлы проекта .ts.
  • Для параметра resolve_json_module задано значение True, что означает, что Bazel должен разрешать импорт файлов с расширением .json в файлы проекта .ts.

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

$ bazel build //:transpile
Скриншот $ bazel build //:transpile вывода терминала
Скриншот $ bazel build //:transpile вывода терминала

Это скомпилирует файл TypeScript в src/index.js к файлам JavaScript. К настоящему времени у вас должны быть свежесозданные папки Bazel, такие как bazel-bin и bazel-out. Это папки, в которые Bazel помещает ваши выходные данные сборки. Если вам когда-нибудь понадобится избавиться от них, вы можете просто запустить bazel clean, который удалит выходные данные из вашей сборки и сбросит внутренние кэши.

Результат предыдущей сборки можно найти в bazel-bin/src/index.js, который является символической ссылкой на bazel-out/darwin-fastbuild/bin/src/index.js. Это результат вашей сборки, который отражает каталог src в корневой папке.

Запустите выходной файл, запустив bazel-out/darwin-fastbuild/bin/src/index.js. Вы должны получить Hello! Welcome. вывод в консоль.

Добавьте тесты с помощью Jest

В этом руководстве вы будете использовать Jest для добавления тестов в проект demo_bzl_app. Начните с добавления Jest в npm:

npm install --save-dev jest ts-jest @types/jest

Затем вам нужно настроить Jest, выполнив следующее:

npx ts-jest config:init

Это создаст файл jest.config.js, который сообщает Jest и ts-jest, как обрабатывать файлы .ts. Кроме того, в файле WORKSPACE вы должны загрузить зависимость с именем rules_jest. Это библиотека Bazel, которая упрощает использование Jest с Bazel. Добавьте в файл WORKSPACE следующее:

WORKSPACE
http_archive(
    name = "aspect_rules_jest",
    sha256 = "9f327ea58950c88274ea7243419256c74ae29a55399d2f5964eb7686c7a5660d",
    strip_prefix = "rules_jest-0.15.0",
    url = "https://github.com/aspect-build/rules_jest/archive/refs/tags/v0.15.0.tar.gz",
)

####################
# rules_jest setup #
####################
# Fetches the rules_jest dependencies.
load("@aspect_rules_jest//jest:dependencies.bzl", "rules_jest_dependencies")

rules_jest_dependencies()

# Fetches the npm packages for jest-cli.
load("@aspect_rules_jest//jest:repositories.bzl", "jest_repositories")

jest_repositories(name = "jest")

load("@jest//:npm_repositories.bzl", jest_npm_repositories = \
"npm_repositories")

jest_npm_repositories()

Затем создайте тестовую папку и тестовый файл:

mkdir tests && touch tests/index.test.ts

В index.test.ts добавьте следующее:

index.test.ts
let { adder, concatenate } = require('../src/index.ts');

describe('adder module', () => {
    test('test_adder', ()=> {
        expect(adder(1,2)).toBe(3)
    });
});

describe('concatenate module', () => {
    test('test_concatenate', ()=> {
        expect(concatenate('mary',' had a little lamb'))\
        .toBe('mary had a little lamb')
    });
});

Приведенный выше код добавляет тестовые примеры для функций в src/index.ts.

Вам все еще нужно добавить способ, которым Bazel может вызывать Jest. В файле BUILD добавьте следующее:

Bazel.BUILD
load("@aspect_rules_jest//jest:defs.bzl", "jest_test")

jest_test(
    name = "test",
    config = "jest.config.js",
    data = [
        "src/index.ts", # the test file below depends on this file
        "tests/index.test.ts",
    ],
)

jest_test — это функция правила, загруженная из зависимостей, ранее загруженных в ваш файл Bazel WORKSPACE. Он называет правила test и сообщает Bazel, где найти файл конфигурации Jest. В нем также перечислены тестовый файл index.tests.ts и тестируемый файл index.ts.

Теперь вы можете запустить свои тесты с помощью Bazel, используя следующий код:

$ bazel run //:test
Скриншот $ bazel run //:test вывода терминала
Скриншот $ bazel run //:test вывода терминала

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

Чтобы опубликовать этот пакет в npm, вы сначала внесете некоторые изменения в файл BUILD, добавив новое правило. Добавьте в файл BUILD следующее:

Bazel.BUILD
load("@aspect_rules_js//npm:defs.bzl", "npm_package")

npm_package(
    name="demo_bzl_app",
    srcs = [":transpile", "readme.md", "package.json"],
    package="demo_bzl_app",
)

Здесь правило называется demo_bzl_app. srcs просит Bazel использовать выходные файлы из правила transpile. Помните, что правило transpile — это первое правило в файле BUILD. Это гарантирует, что transpile преобразует файлы TypeScript в .js до того, как пакету будет присвоено имя. Правило также требует от Bazel включения файлов readme.md и package.json, поскольку они потребуются для публикации в npm.

Теперь все, что вам нужно сделать, это запустить следующую команду:

$ bazel build //:demo_bzl_app

Перейдите в папку bazel-out/darwin-fastbuild/bin/. Вы должны увидеть папку с именем demo_bzl_app, которая содержит скомпилированные исходные файлы библиотеки .js, а также файлы readme.md и package.json. Это папка, которая будет опубликована в npm.

Затем создайте файл .gitignore и добавьте в него следующее:

.gitignore
bazel-*
node_modules

Затем запустите git init, git add и git commit, чтобы инициализировать репозиторий Git, добавить и зафиксировать все соответствующие файлы в Git соответственно.

Прежде чем вы сможете опубликовать свой пакет, вам необходимо создать учетную запись npm по адресу https://www.npmjs.com/signup. Войдите в свою учетную запись npm, используя npm login.

Затем создайте файл с именем publish.sh и добавьте следующее:

publish.sh
#!/bin/bash

echo "Removing old Bazel outputs"
bazel clean

echo "Running tests"
bazel run //:test

echo "Building package"
bazel build //:demo_bzl_app

echo "moving to output dir"
cd bazel-out/darwin-fastbuild/bin/demo_bzl_app

while true; do
    read -p "Are you ready to publish to NPM? " yn
    case $yn in
        [Yy]* ) 
          echo "Now publishing package to NPM";
         npm publish; break;;
        [Nn]* ) exit;;
        * ) echo "Enter yes or no.";;
    esac
done

echo "Done!"

Предыдущий скрипт удалит старые выходные данные Bazel, а затем запустит тесты и создаст выходные файлы перед публикацией в npm. В опубликованный пакет будет включена только папка demo_bzl_app. (README.md и package.json включены по умолчанию.)

Теперь вы можете публиковать:

$ bash publish.sh
Терминальный вывод публикации в npm
Терминальный вывод публикации в npm

Вы можете просмотреть свой пакет на npm. URL-адрес: https://npmjs.com/package/<your-package-name>. Для этого руководства это https://npmjs.com/package/demo_bzl_app. Обязательно увеличьте версию выпуска в package.json при следующей попытке публикации, чтобы избежать ошибки.

Если вы хотите увидеть полный исходный код из этого руководства, посетите этот репозиторий GitHub.

Заключение

Теперь вы завершили базовую сборку приложения TypeScript с помощью Bazel. Вы узнали, как определить рабочее пространство, а также пакет. Вы также узнали, как загружать зависимости, добавлять правила, создавать и тестировать проект, а также публиковать в npm - и все это с помощью Bazel.

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

Источник:

#JavaScript #TypeScript
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу