Ts src что это
Перейти к содержимому

Ts src что это

  • автор:

Заголовочные файлы

Для установки связи с внешними файлами скриптов javascript в TS служат декларативные или заголовочные файлы. Это файлы с расширением .d.ts , они описывают синтаксис и структуру функций и свойств, которые могут использоваться в программе, не предоставляя при этом конкретной реализации. Их действие во многом похоже на работу файлов с расширением .h в языках C/C++. Они выполняют своего рода роль оберток над библиотеками JavaScript.

Рассмотрим, как мы можем использовать заголовочные файлы. Иногда в программах на javascript используются глобальные переменные, которые должны быть видны для всех функций приложения. Например, пусть на веб-странице (или во внешнем подключаемом файле javascript) в коде js определена переменная:

    Metanit.com  

Приложение на TypeScript

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

И, допустим, мы хотим использовать эту переменную message в коде TypeScript в файле app.ts:

console.log(message);

При запуске приложения компилятор TS не сможет скомпилировать программу, так как для кода TS глобальная переменная пока не существует. В этом случае нам надо подключать определение глобальной переменной с помощью декларативных файлов. Для этого добавим в проект новый файл, который назовем globals.d.ts и который будет иметь следующее содержимое:

declare let message: string;

С помощью ключевого слова declare в программу на TS подключается определение глобальной переменной.

То есть у нас получится следующая структура проекта:

  • app.ts
  • globals.d.ts
  • index.html

Компиляция

Если мы компилируем, передавая компилятору в консоли название файла:

tsc app.ts

То в этом случае компилятор не найдет автоматически файл globals.d.ts. В этом случае нам надо в файле app.ts явно указать расположение файла globals.d.ts с помощью директивы reference

/// console.log(message);

Заголовочные файлы в TypeScript

Если же мы полагаемся на файл конфигурации tsconfig.json, просто выполняя команду

Подобным образом мы можем подключать другие компоненты кода JavaScript — функции, объекты, классы. Рассмотрим их подключение.

Функции

Пусть на веб-странице в коде js объявлены две следующие функции:

let message = «Hello TypeScript!»; function hello() < console.log(message); >function sum(a, b)

Функция hello() выводит значение переменной message на консоль, а функция sum() возвращает сумму двух чисел.

И, допустим, в коде TS мы хотим вызывать эти функции:

hello(); let result = sum(2, 5); console.log(result);

В этом случае подключение в файле globals.d.ts выглядело бы так:

declare function hello(): void; declare function sum(a: number, b: number): number;

Подключение объектов

Пусть в коде JavaScript есть следующий объект:

const tom = < name: "Tom", age: 37, print()< console.log(`Name: $Age: $`); > >

Используем этот объект в коде typescript:

tom.print();

В этом случае определение объекта в файле globals.d.ts выглядело бы так:

declare const tom: void>;

Подключени сложных объектов

Однако может возникнуть сложность с подключением более сложных объектов. Например, пусть есть такой объект javascript:

var points = [< X: 10, Y: 34 >, < X: 24, Y: 65 >, < X: 89, Y: 12 >];

Для данного массива объектов в файле globals.d.ts мы можем определить соответствующий отдельному объекту интерфейс и подключить массив объектов некоторого интерфейса, который содержит два свойства X и Y:

interface IPoint < X: number; Y: number; >declare var points: IPoint[];

И в TS мы сможем использовать этот массив:

for (let point of points) < console.log(`Точка с координатами X = $Y = $`); >

Консольный вывод браузера:

Точка с координатами X = 10 Y = 34 Точка с координатами X = 24 Y = 65 Точка с координатами X = 89 Y = 12

Подключение классов

Рассмотрим последний пример — подключение в typescript классов, определенных в javascript. Пусть в коде JavaScript определен следующий класс Person:

class Person < constructor(name, age)< this.name = name; this.age = age; >display() < console.log(this.name, this.age); >>

Для этого класса в файле globals.d.ts определим следующее объявление класса:

declare class Person

Для класса прописываем все его поля и методы, при этом методы (в том числе конструктор) не имеют реализации, для них только определяются параметры и их типы и тип возвращаемого значения.

И в коде TypeScript используем этот класс:

let tom = new Person("Tom", 37); tom.display(); // Tom 37 console.log(tom.name); // Tom

Основы TypeScript: компилятор TypeScript (tsc) и tsconfig.json

Добро пожаловать в первую часть серии из десяти частей, посвящённой основам TypeScript. В этой первой части мы рассмотрим компилятор TypeScript ( tsc ) и файл конфигурации ( tsconfig.json ).

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

Компилятор TypeScript ( tsc )

1. Что такое tsc

tsc — это компилятор TypeScript. Он принимает TypeScript код (файлы .ts или .tsx ) и компилирует его в JavaScript код (файлы .js ), который может быть выполнен средой выполнения JavaScript.

2. Как установить tsc

Вы можете установить tsc глобально с помощью npm (Node Package Manager/Менеджер пакетов Node), выполнив команду:

npm install -g typescript

3. Компиляция TypeScript кода

После установки tsc вы можете компилировать TypeScript файлы, выполнив следующую команду в терминале:

tsc yourfile.ts

4. Параметры компилятора

tsc поставляется с различными параметрами компилятора, позволяющими настроить процесс компиляции. Например:

tsc - target ES5 - outDir ./dist

Эта команда устанавливает целевую версию ECMAScript на ES5 и указывает каталог для вывода .js файлов как ./dist .

tsconfig.json

1. Что такое tsconfig.json

tsconfig.json — это файл конфигурации для проектов TypeScript. Он позволяет указать параметры компилятора, включить/исключить файлы и настроить другие параметры для вашего TypeScript-проекта.

2. Создание файла tsconfig.json

Вы можете создать файл tsconfig.json вручную в корне проекта или использовать команду tsc —init для генерации базового файла конфигурации.

3. Параметры компилятора в tsconfig.json

В tsconfig.json могут быть включены различные параметры компилятора. К числу распространённых относятся:

  • compilerOptions : Определяет параметры компилятора.
  • include : Указывает массив шаблонов файлов для включения в компиляцию.
  • exclude : Указывает массив шаблонов файлов, которые нужно исключить из компиляции.
  • extends : Позволяет расширить другой конфигурационный файл.

4. Пример tsconfig.json

 
"compilerOptions":
"target": "es5",
"module": "commonjs",
"outDir": "./dist"
>,
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules"
]
>

Этот пример устанавливает целевое значение ES5, систему модулей — CommonJS, каталог для вывода — ./dist , включает все файлы TypeScript в каталог src и исключает каталог node_modules .

Использование tsconfig.json позволяет поддерживать согласованную конфигурацию во всем проекте TypeScript и упрощает процесс компиляции, избавляя от необходимости указывать опции при каждом запуске команды tsc .

Основы TypeScript

  1. Основы TypeScript: компилятор TypeScript ( tsc ) и tsconfig.json
  2. Основы TypeScript: JavaScript в сравнении с TypeScript
  3. Основы TypeScript: Примитивы и базовые типы
  4. Основы TypeScript: Неявные и Явные типы, Утверждения типов
  5. Основы TypeScript: Создание типов, перечислений и интерфейсов
  6. Основы TypeScript: Объединение, Литеральные и Размеченные типы
  7. Основы TypeScript: Типизация функций и сигнатур
  8. Основы TypeScript: Any , Void , Never , Null , Строгие проверки Null
  9. Основы TypeScript: ООП практика, классы и наследование

TypeScript: Раскладываем tsconfig по полочкам. Часть 1

Я большой фанат TypeScript. Каждый свой новый проект я предпочитаю писать на нём, а не на чистом JavaScript. В данной статье я не буду рассматривать причины выбора TypeScript или о его преимуществах и недостатках. Я хочу, чтобы данный пост стал своего рода шпаргалкой для тех, кто хочет понять, как настраивать tsconfig , разложить по полочкам его многочисленные флаги и, возможно, узнать некоторые полезные трюки.

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

Если открыть официальный референс tsconfig , то там будет полный список всех настроек, разделённых по группам. Однако, это не даёт понимания, с чего начать и что из данного обширного списка опций обязательно, а на что можно не обращать внимания (по крайней мере до поры до времени). Плюс, иногда опции сгруппированы по некому техническому, а не логическому смыслу. Например, некоторые флаги проверок можно найти в группе Strict Checks , некоторые в Linter Checks , а другие в Advanced . Это не всегда удобно для понимания.

Все опции, как и саму статью, я разделил на две группы – базовые и «проверки». В первой части статьи разговор пойдёт про базовые настройки, а во второй уже про различные проверки, т. е. про тюнинг строгости компилятора.

Структура tsconfig

Рассмотрим структуру и некоторые особенности конфига.

  • tsconfig.json состоит из двух частей. Какие-то опции необходимо указывать в root , а какие-то в compilerOptions
  • tsconfig.json поддерживает комментарии. Такие IDE как WebStorm и Visual Studio Code знают об этом и не выделяют комментарии как синтаксическую ошибку
  • tsconfig.json поддерживает наследование. Опции можно разделить по некоторому принципу, описать их в разных файлах и объединить с помощью специальной директивы

Это болванка нашего tsconfig.json :

К root опциям относится только следующие: extends , files , include , exclude , references , typeAcquisition . Из них мы будем рассматривать первые 4. Все остальные опции размещаются в compilerOptions .

Иногда в root секции конфига можно встретить такие опции как compileOnSave и ts-node . Эти опции не являются официальными и используются IDE для своих целей.

Секция root

extends

Type: string | false, default: false.

Указывает путь к файлу из которого нужно унаследовать опции. По большей части, служит инструментом упорядочивания. Можно разделить опции по некой логике, чтобы они не смешивались. Например, вынести настройки строгости в отдельный файл, как в примере болванки конфига. Однако, учитывая поддержку комментариев в tsconfig.json это можно сделать проще:

Рассмотрим другой use-case, где комментариями отделаться не получится. Если необходимо создать production и development конфиги. Так бы мог выглядеть tsconfig-dev.json версия конфига:

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

Если вы решите использовать эту опцию. То увидеть итоговую, объединённую версию конфига поможет команда tsc —showConfig .

files

Type: string[] | false, default: false, связана с include .

Указать список конкретных файлов для компиляции можно использовав данную опцию.

< "compilerOptions": <>, "files": [ "core.ts", "app.ts" ] >

Данная опция подходит лишь для совсем маленьких проектов из нескольких файлов.

include

Type string[], default: зависит от значения files , связана с exclude .

Если опция files не указана, то TypeScript будет использовать эту директиву для поиска компилируемых файлов. Если include так же не указана, то её значение будет неявно объявлено как [«**/*»] . Это означает, что поиск файлов будет осуществляться во всех папках и их подпапках. Такое поведение не оптимально, поэтому в целях производительности лучше всегда указывать конкретные пути. Можно прописывать как пути к конкретным файлам, так и паттерны путей.

< "compilerOptions": <>, "include": [ "src/**/*", "tests/**/*" ] >

Если паттерны не указывают конкретных расширений, то TypeScript будет искать файлы с расширениями .ts , .tsx и .d.ts . А если включен флаг allowJs , то ещё .js и .jsx .

Следующие форматы записей делают одно и тоже src , ./src , src/**/* . Я предпочитаю вариант ./src .

Технически, используя опции include и exclude , TypeScript сгенерирует список всех подходящих файлов и поместит их в files . Это можно наблюдать если выполнить команду tsc —showConfig .

exclude

Type: string[], default: [«node_modules», «bower_components», «jspm_packages»].

Директива служит для того, чтобы исключать некоторые лишние пути или файлы, которые включились директивой include . По умолчанию, опция имеет значение путей пакетных менеджеров npm , bower и jspm , так как модули в них уже собраны. Помимо этого, TypeScript будет так же игнорировать папку из опции outDir , если она указана. Это папка, куда помещаются собранные артефакты сборки. Логично, что их нужно исключить. Если добавить свои значения в эту опцию, то необходимо не забыть восстановить умолчания. Так как пользовательские значения не объединяются со значениями по умолчанию. Другими словами, необходимо вручную указать корень модулей своего пакетного менеджера.

< "compilerOptions": <>, "exclude": [ "node_modules", "./src/**/*.spec.ts" ] >

Опция exclude не может исключить файлы, указанные через files .

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

Секция compilerOptions

target

Type: string, default: ES3 , влияет на опции lib , module .

Версия стандарта ECMAScript, в которую будет скомпилирован код. Здесь большой выбор: ES3 , ES5 , ES6 (он же ES2015 ), ES2016 , ES2017 , ES2018 , ES2019 , ES2020 , ESNext . Для backend приложений/пакетов подойдёт ES6 , если рассчитываете только на современные версии Node.js и ES5 , если хотите поддержать более старые версии. На данный момент стандарт ES6 , с небольшими оговорками, поддерживается 97.29% браузеров. Так что для frontend приложений ситуация аналогичная.

module

Type: string, default: зависит от target , влияет на опцию moduleResolution .

Модульная система, которую будет использовать ваше собранное приложение. На выбор: None , CommonJS , AMD , System , UMD , ES6 , ES2015 , ES2020 или ESNext . Для backend приложений/пакетов подойдёт ES6 или CommonJS в зависимости от версий Node.js , которые хотите поддерживать. Для frontend приложений под современные браузеры также подходит ES6 . А для поддержки более старых браузеров и для изоморфных приложений, определённо стоит выбрать UMD .

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

moduleResolution

Type: string, default: зависит от module .

Стратегия, которая будет использоваться для импорта модулей. Здесь всего две опции: node и classic . При этом classic в 99% не будет использоваться, так как это legacy. Однако, я специально упомянул этот флаг, так как он меняется в зависимости от предыдущего флага. При изменении значения module режим moduleResolution может переключиться на classic и в консоли начнут появляться сообщения об ошибках на строчках с импортами.

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

lib

Type: string[], default: зависит от target .

В зависимости от того какой target установлен в конфиге, TypeScript подключает тайпинги ( *.d.ts-файлы ) для поддержки соответствующих спецификаций. Например, если ваш target установлен в ES6 , то TypeScript подключит поддержку array.find и прочих вещей, которые есть в стандарте. Но если target стоит ES5 , то использовать метод массива find нельзя, так как его не существует в этой версии JavaScript. Можно подключить полифилы. Однако, для того, чтобы TypeScript понял, что теперь данную функциональность можно использовать, необходимо подключить необходимые тайпинги в секции lib . При этом, можно подключить как весь стандарт ES2015 , так и его часть ES2015.Core (только методы find , findIndex и т. д.).

Конечно, правильным выбором будет подключать тайпинги только той функциональности, для которой установлены полифилы.

Для --target ES5 подключаются: DOM, ES5, ScriptHost Для --target ES6: DOM, ES6, DOM.Iterable, ScriptHost

Как только вы что-либо добавляете в lib умолчания сбрасываются. Необходимо руками добавить то, что нужно, например DOM :

outDir

Type: string, default: равняется корневой директории.

Конечная папка, куда будут помещаться собранные артефакты. К ним относятся: .js , .d.ts , и .js.map файлы. Если не указывать значение для данной опции, то все вышеуказанные файлы будут повторять структуру исходных файлов в корне вашего проекта. В таком случае будет сложно удалять предыдущие билды и описывать .gitignore файлы. Да и кодовая база будет похожа на свалку. Советую складывать все артефакты в одну папку, которую легко удалить или заигнорировать системой контроля версий.

Если оставить опцию outDir пустой:

├── module │ └── core.js │ └── core.ts ├── index.js └── index.ts

Если указать outDir :

├── dist │ └── module │ | └── core.js │ └── index.js ├── module │ └── core.ts └── index.ts

outFile

Type: string, default: none.

Судя по описанию, данная опция позволяет объединить все файлы в один. Кажется, что бандлеры вроде webpack больше не нужны… Однако, опция работает только если значение module указано None , System или AMD . К огромному сожалению, опция не будет работать с модулями CommonJS или ES6 . Поэтому скорее всего использовать outFile не придётся. Так как опция выглядит максимально привлекательно, но работает не так как ожидается, я решил предупредить вас об этом гигантском подводном камне.

allowSyntheticDefaultImports

Type: boolean, default: зависит от module или esModuleInterop .

Если какая-либо библиотека не имеет default import , лоадеры вроде ts-loader или babel-loader автоматически создают их. Однако, d.ts-файлы библиотеки об этом не знают. Данный флаг говорит компилятору, что можно писать следующим образом:

// вместо такого импорта import * as React from 'react'; // можно писать такой import React from 'react';

Опция включена по умолчанию, если включен флаг esModuleInterop или module === «system».

esModuleInterop

Type: boolean, default: false.

За счёт добавления болерплейта в выходной код, позволяет импортировать CommonJS пакеты как ES6 .

// библиотека moment экспортируется только как CommonJS // пытаемся импортировать её как ES6 import Moment from 'moment'; // без флага esModuleInterop результат undefined console.log(Moment); // c флагом результат [object Object] console.log(Moment);

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

alwaysStrict

Type: boolean, default: зависит от strict .

Компилятор будет парсить код в strict mode и добавлять “use strict” в выходные файлы.

По умолчанию false, но если включен флаг strict , то true.

downlevelIteration

Type: boolean, default: false.

Спецификация ES6 добавила новый синтаксис для итерирования: цикл for / of , array spread , arguments spread . Если код проекта преобразовывается в ES5 , то конструкция с циклом for / of будет преобразована в обычный for :

// код es6 const str = 'Hello!'; for (const s of str)
// код es5 без downlevelIteration var str = "Hello!"; for (var _i = 0, str_1 = str; _i < str_1.length; _i++)

Однако, некоторые символы, такие как emoji кодируются с помощью двух символов. Т. е. такое преобразование в некоторых местах будет работать не так, как ожидается. Включенный флаг downlevelIteration генерирует более многословный и более «правильный», но менее производительный код. Код получается действительно очень большим, поэтому не буду занимать место на экране. Если интересно посмотреть пример, то перейдите в playground и выберете в настройках target -> es5 , downlevelIteration -> true .

Для работы данного флага, необходимо, чтобы в браузере была реализация Symbol.iterator . В противном случае необходимо установить полифил.

forceConsistentCasingInFileNames

Type: boolean, default: false.

Включает режим чувствительности к регистру (case-sensitive) для импорта файлов. Таким образом, даже в case-insensitive файловых системах при попытке сделать импорт import FileManager from ‘./FileManager.ts’ , если файл в действительности называется fileManager.ts , приведёт к ошибке. Перестраховаться лишний раз не повредит. TypeScript — это про строгость.

Опции секции compilerOptions, которые нужны не в каждом проекте

declaration

Type: boolean, default: false.

С помощью включения данного флага, помимо JavaScript файлов, к ним будут генерироваться файлы-аннотации, известные как d.ts -файлы или тайпинги. Благодаря тайпингам становится возможным определение типов для уже скомпилированных js файлов. Другими словами код попадает в js , а типы в d.ts -файлы. Это полезно в случае, например, если вы публикуете свой пакет в npm . Такой библиотекой смогут пользоваться разработчики, которые пишут как на чистом JavaScript, так и на TypeScript.

declarationDir

Type: string, default: none, связан с declaration .

По умолчанию тайпинги генерируются рядом с js -файлами. Используя данную опцию можно перенаправить все d.ts -файлы в отдельную папку.

emitDeclarationOnly

Type: boolean, default: false, связан с declaration .

Если по какой-то причине вам нужны только d.ts -файлы, то включение данного флага предотвратит генерацию js -файлов.

allowJs

Type: boolean, default: false.

Портировать ваш JavaScript проект на TypeScript поможет данный флаг. Активировав allowJs TypeScript компилятор будет обрабатывать не только ts файлы, но и js . Нет нужды полностью мигрировать проект, прежде чем продолжить его разработку. Можно это делать файл за файлом, просто меняя расширение и добавляя типизацию. А новый функционал сразу можно писать на TypeScript.

checkJs

Type: boolean, default: false, связан с allowJs .

TypeScript будет проверять ошибки не только в ts , но и в js -файлах. Помимо встроенных тайпингов для языковых конструкций JavaScript, TS-компилятор так же умеет использовать jsDoc для анализа файлов. Я предпочитаю не использовать этот флаг, а наводить порядок в коде в момент его типизации. Однако, если в вашем проекте хорошее покрытие кода jsDoc, стоит попробовать.

С версии 4.1 при включении checkJs , флаг allowJs включается автоматически.

experimentalDecorators и emitDecoratorMetadata

Type: boolean, default: false.

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

Флаг experimentalDecorators просто активирует синтаксис, а emitDecoratorMetadata в рантайме предоставляет декораторам дополнительные мета-данные, с помощью которых можно значительно расширить области применения данной фичи.

Для работы emitDecoratorMetadata необходимо подтянуть в проект библиотеку reflect-metadata.

resolveJsonModule

Type: boolean, default: false.

Флаг позволяет включить возможность импортировать *.json файлы. Ничего дополнительно устанавливать не требуется.

// необходимо указывать расширение .json import config from './config.json'

jsx

Type: string, default: none.

Если проект использует React, необходимо включить поддержку jsx . В подавляющем большинстве случаев будет достаточно опций react или react-native . Так же есть возможность оставить jsx-код нетронутым с помощью опции preserve или использовать кастомные преобразователи react-jsx и react-jsxdev .

Завершение первой части

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

UPD: Здесь можно прочитать вторую часть статьи.

Минимальный проект #

Начнем с создания новой папки. Мы назовем ее proj , однако ей можно дать любое необходимое имя.

mkdir proj cd proj

Структура проекта будет следующей:

proj/ +- src/ +- dist/

Файлы TypeScript будут находиться в папке src , компилироваться с помощью TypeScript, а результат выводиться в dist .

Давайте создадим эту структуру:

mkdir src mkdir dist

Инициализация проекта

Превратим эту папку в npm-пакет.

npm init

Вам зададут несколько вопросов. Для всех можно использовать вариант ответа по умолчанию, кроме вопроса о точке входа ( entry point: ). В качестве точки входа введите ./dist/main.js . Вы всегда можете вернуться и изменить все, что указали, в сгенерированном файле package.json .

Установка зависимостей

Теперь используем npm install , чтобы установить пакеты. В первую очередь глобально установите TypeScript и gulp. (Если вы пользуетесь Unix-системой, то, возможно, команды npm install придется запускать через sudo ).

npm install -g typescript gulp-cli

Затем установите gulp и gulp-typescript в качестве зависимостей времени разработки. Gulp-typescript — это плагин к gulp для поддержки TypeScript.

npm install --save-dev gulp gulp-typescript

Создание простого примера

Давайте напишем несложную программу. Создайте файл main.ts в папке src :

function hello(compiler: string) < console.log(`Привет от $`); > hello("TypeScript");

Создайте файл tsconfig.json в корне проекта proj :

Создание gulpfile.js

Создайте файл gulpfile.js в корне проекта:

var gulp = require("gulp"); var ts = require("gulp-typescript"); var tsProject = ts.createProject("tsconfig.json"); gulp.task("default", function () < return tsProject.src() .pipe(ts(tsProject)) .js.pipe(gulp.dest("dist")); >);

Тестирование полученного приложения

gulp node dist/main.js

Приложение должно вывести в консоль «Привет от TypeScript!».

Добавление модулей #

Прежде чем добраться до Browserify, соберем код и добавим к нему модули. Следующую структуру вы, скорее всего, будете использовать и для настоящих приложений.

Создайте файл src/greet.ts :

export function sayHello(name: string) < return `Привет от $`; >

Теперь измените код в src/main.ts так, чтобы sayHello импортировалась из greet.ts :

import < sayHello >from "./greet"; console.log(sayHello("TypeScript"));

И, наконец, добавьте src/greet.ts в tsconfig.json :

Убедитесь, что модули работают, запустив gulp и проверив работу кода в Node:

gulp node dist/main.js

Обратите внимание, что хотя мы применили синтаксис модулей из ES2015, TypeScript создал модули CommonJS, которые используются в Node. Для целей этого руководства формат CommonJS вполне подходит, но вы можете установить параметр module на объекте настроек, чтобы выбрать формат модулей.

Browserify #

Теперь перенесем проект с Node в браузер. Для этого пришлось бы упаковать все модули в один JavaScript-файл. К счастью, именно это и делает Browserify. Больше того, Browserify позволяет использовать модульную систему CommonJS, которая применяется в Node, и модули для которой по умолчанию создает TypeScript. Это значит, что вносить много изменений в уже настроенную связку TypeScript и Node не потребуется.

Сначала установите browserify, tsify, и vinyl-source-stream. tsify это плагин для Browserify, который, подобно gulp-typescript, предоставляет доступ к компилятору TypeScript. vinyl-source-stream позволяет согласовать файловый вывод Browserify и формат под названием vinyl, который понимает gulp.

npm install --save-dev browserify tsify vinyl-source-stream

Создание страницы

Создайте файл index.html в src :

Теперь измените main.ts , чтобы обновить страницу:

import < sayHello >from "./greet"; function showHello(divName: string, name: string) < const elt = document.getElementById(divName); elt.innerText = sayHello(name); >showHello("greeting", "TypeScript");

При вызове showHello вызывается sayHello , которая изменяет текст параграфа. Теперь замените код в gulpfile.js на следующий:

var gulp = require("gulp"); var browserify = require("browserify"); var source = require('vinyl-source-stream'); var tsify = require("tsify"); var paths = < pages: ['src/*.html'] >; gulp.task("copy-html", function () < return gulp.src(paths.pages) .pipe(gulp.dest("dist")); >); gulp.task("default", ["copy-html"], function () < return browserify(< basedir: '.', debug: true, entries: ['src/main.ts'], cache: <>, packageCache: <> >) .plugin(tsify) .bundle() .pipe(source('bundle.js')) .pipe(gulp.dest("dist")); >);

Здесь создается задача copy-html , которая затем добавляется как зависимость для default . Это значит, что при каждом запуске default сначала будет вызываться copy-html . Кроме того, задача default была изменена так, что вместо gulp-typescript теперь вызывается Browserify с плагином tsify. К счастью, оба эти вызова позволяют передать один и тот же объект параметров для компилятора TypeScript.

После вызова bundle мы используем source (наш псевдоним для vinyl-source-stream), чтобы дать получаемой сборке имя bundle.js .

Протестируйте страницу, запустив gulp и открыв в браузере страницу dist/index.html . На ней должен быть текст «Привет от TypeScript».

Обратите внимание, что мы указали debug: true для Browserify. Это заставляет tsify генерировать карты кода внутри создаваемого файла сборки. Карты кода позволяют отлаживать в браузере не упакованный JavaScript-код, а исходный TypeScript. Можно проверить, работают ли карты кода, открыв в браузере отладчик и установив точку останова в main.ts . При обновлении страницы эта точка останова должна спровоцировать паузу, и браузер позволит отлаживать greet.ts .

Watchify, Babel, и Uglify #

Теперь, когда мы собираем код с Browserify и tsify, можно добавить к сборке различные возможности с помощью плагинов для Browserify.

  • Watchify запускает gulp и держит его запущенным, выполняя инкрементальную компиляцию при сохранении какого-либо файла. Это позволяет автоматизировать в браузере цикл «редактирование» — «сохранение» — «обновление».
  • Babel представляет собой очень гибкий компилятор, превращающий ES2015 и выше в ES5 и ES3. Это позволяет применять к коду обширные и настраиваемые трансформации, которые не поддерживаются TypeScript.
  • Uglify минимизирует код, чтобы он загружался быстрее.

Watchify

Начнем с Watchify и реализуем фоновую компиляцию:

npm install --save-dev watchify gulp-util

Теперь измените gulpfile.js следующим образом:

var gulp = require("gulp"); var browserify = require("browserify"); var source = require('vinyl-source-stream'); var watchify = require("watchify"); var tsify = require("tsify"); var gutil = require("gulp-util"); var paths = < pages: ['src/*.html'] >; var watchedBrowserify = watchify(browserify(< basedir: '.', debug: true, entries: ['src/main.ts'], cache: <>, packageCache: <> >).plugin(tsify)); gulp.task("copy-html", function () < return gulp.src(paths.pages) .pipe(gulp.dest("dist")); >); function bundle() < return watchedBrowserify .bundle() .pipe(source('bundle.js')) .pipe(gulp.dest("dist")); >gulp.task("default", ["copy-html"], bundle); watchedBrowserify.on("update", bundle); watchedBrowserify.on("log", gutil.log);

Здесь, фактически, три изменения, но они требуют небольшой переработки кода.

  1. Мы «завернули» экземпляр browserify в вызов watchify , и сохранили результат в переменной.
  2. Вызвали watchedBrowserify.on(«update», bundle); , так что Browserify будет запускать функцию bundle при каждом изменении TypeScript-файлов.
  3. Вызвали watchedBrowserify.on(«log», gutil.log); для вывода сообщений на консоль.

Из-за (1) и (2) вызов browserify пришлось вынести из задачи default . Кроме того, функции для задачи default пришлось дать имя, так ее будут вызывать и Watchify, и Gulp. Добавление вывода на консоль необязательно, но полезно для отладки.

Теперь при старте Gulp он запустится и останется в запущенном состоянии. Попробуйте изменить код showHello в файле main.ts , и сохранить его. Вы должны будете увидеть похожий вывод:

proj$ gulp [10:34:20] Using gulpfile ~/src/proj/gulpfile.js [10:34:20] Starting 'copy-html'. [10:34:20] Finished 'copy-html' after 26 ms [10:34:20] Starting 'default'. [10:34:21] 2824 bytes written (0.13 seconds) [10:34:21] Finished 'default' after 1.36 s [10:35:22] 2261 bytes written (0.02 seconds) [10:35:24] 2808 bytes written (0.05 seconds)

Uglify

Сначала установите Uglify. Поскольку задача Ugligy заключается в обфускации кода, также придется установить vinyl-buffer и gulp-sourcemaps, чтобы карты кода продолжали работать.

npm install --save-dev gulp-uglify vinyl-buffer gulp-sourcemaps

Теперь измените gulpfile.js следующим образом:

var gulp = require("gulp"); var browserify = require("browserify"); var source = require('vinyl-source-stream'); var tsify = require("tsify"); var uglify = require('gulp-uglify'); var sourcemaps = require('gulp-sourcemaps'); var buffer = require('vinyl-buffer'); var paths = < pages: ['src/*.html'] >; gulp.task("copy-html", function () < return gulp.src(paths.pages) .pipe(gulp.dest("dist")); >); gulp.task("default", ["copy-html"], function () < return browserify(< basedir: '.', debug: true, entries: ['src/main.ts'], cache: <>, packageCache: <> >) .plugin(tsify) .bundle() .pipe(source('bundle.js')) .pipe(buffer()) .pipe(sourcemaps.init()) .pipe(uglify()) .pipe(sourcemaps.write('./')) .pipe(gulp.dest("dist")); >);

Обратите внимание, что для uglify понадобился всего один вызов; вызовы buffer и sourcemaps нужны только для того, чтобы карты кода продолжали работать. Эти вызовы создают отдельный файл с картами кода вместо внедренных в файл, которые были раньше. Теперь можно запустить Gulp и проверить, что из кода в bundle.js получилось нечто нечитаемое:

gulp cat dist/bundle.js

Babel

Для начала установите Babelify. Как и Uglify, Babelify обфусцирует код, поэтому понадобится vinyl-buffer и gulp-sourcemaps.

npm install --save-dev babelify vinyl-buffer gulp-sourcemaps

Теперь измените gulpfile.js следующим образом:

var gulp = require('gulp'); var browserify = require('browserify'); var source = require('vinyl-source-stream'); var tsify = require('tsify'); var sourcemaps = require('gulp-sourcemaps'); var buffer = require('vinyl-buffer'); var paths = < pages: ['src/*.html'] >; gulp.task('copyHtml', function () < return gulp.src(paths.pages) .pipe(gulp.dest('dist')); >); gulp.task('default', ['copyHtml'], function () < return browserify(< basedir: '.', debug: true, entries: ['src/main.ts'], cache: <>, packageCache: <> >) .plugin(tsify) .transform("babelify") .bundle() .pipe(source('bundle.js')) .pipe(buffer()) .pipe(sourcemaps.init()) .pipe(sourcemaps.write('./')) .pipe(gulp.dest('dist')); >);

Также необходимо, чтобы TypeScript генерировал ES2015-код. Тогда Babel превратит созданный TypeScript ES2015-код в ES5. Измените tsconfig.json :

Для столь простого скрипта созданный Babel ES5-код должен быть очень похож на код, созданный TypeScript.

Поддержите перевод документации:

Поддерживатель | Github Репозиторий
Documentation generated by mdoc.

Добавить комментарий

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