Сборка TypeScript-проекта с помощью gulp, webpack и линтированием на ESLint
Table of contents
Introduction
Базовый проект для сборки TypeScript
при помощи gulp
в ES6
и webpack для сборки бандла из отдельных модулей.
Для линтирования используется ESLint
с настройками как для файлов JS
, так и для файлов TS
.
В качестве примера создан интерфейс логирования с несколькими его реализациями.
Репозиторий с полным кодом проекта: https://github.com/superrosko/example-ts-basic.
Установка пакетов
Инициализация проекта:
npm init
После того, как мы инициировали node
-проект и заполнили информацию о нем, нам необходимо установить следующие пакеты:
npm install --save-dev typescript gulp gulp-clean gulp-typescript gulp-eslint eslint eslint-config-google @typescript-eslint/eslint-plugin @typescript-eslint/parser webpack webpack-cli ts-loader clean-webpack-plugin @babel/cli @babel/core @babel/node @babel/preset-env
- typescript - язык программирования, расширяющий возможности
JavaScript
- gulp - инструментарий для автоматизации трудоемких задач в вашей разработке
- gulp-clean - плагин
gulp
для удаления файлов и папок - gulp-typescript - компилятор
TypeScript
дляgulp
- gulp-eslint - плагин
eslint
дляgulp
- eslint - линтер стилей
- eslint-config-google - конфигурационный файл для
Google JavaScript style guide (ES2015+ version)
- @typescript-eslint/eslint - плагин
TypeScript
дляESLint
- @typescript-eslint/parser - плагин для линтирования
TypeScript
с помощьюESLint
- webpack - сборщик модулей
- webpack-cli -
CLI
для webpack - ts-loader - загрузчик
TypeScript
дляwebpack
- clean-webpack-plugin - плагин
webpack
для удаления файлов и папок - @babel/core @babel/cli @babel/node @babel/preset-env - транспайлер для работы с ES6
Настройка TS-проекта
{
"include": [
"src/**/*"
],
"exclude": [
"src/web-bundle.ts"
],
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"allowJs": true,
"checkJs": true,
"declaration": true,
"sourceMap": true,
"outDir": "./dist/",
"strict": true,
"noImplicitAny": true
}
}
В конфиге мы указываем директорию с исходниками и исключаем из сборки файлы web
-бандла.
Настройка babel
Для настройки правил транспиляции создадим в корне проекта файл .babelrc
со следующим содержимым:
{
"presets": [
"@babel/preset-env"
]
}
Настройка ESLint
Для настройки правил проверки создадим файл .eslintrc.json
в корне проекта со следующим содержимым:
{
"env": {
"es6": true,
"browser": true,
"node": true,
"es2017": true
},
"parserOptions": {
"ecmaVersion": 8,
"sourceType": "module"
},
"ignorePatterns": [
"dist/**/*"
],
"extends": [
"eslint:recommended",
"google"
],
"rules": {
"no-console": [
"error",
{
"allow": [
"warn",
"error",
"log"
]
}
]
},
"overrides": [
{
"files": [
"*.ts",
"*.tsx"
],
"extends": [
"eslint:recommended",
"google",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@typescript-eslint/recommended-requiring-type-checking"
],
"plugins": [
"@typescript-eslint"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"tsconfigRootDir": "."
}
}
]
}
В приведенном выше конфиге сформированы правила линтирования для файлов JS
, а с помощью опции overrides
добавлены правила линтирования и для файлов TS
.
Настройка gulp
Запуск линтирования и часть сборки мы будем производить с помощью задач gulp
, для этого создадим файл конфигурации gulpfile.babel.js
в корне проекта со следующим содержимым:
import gulp from 'gulp';
import gulpClean from 'gulp-clean';
import eslint from 'gulp-eslint';
import ts from 'gulp-typescript';
const tsProject = ts.createProject('tsconfig.json');
/**
* @type {{ts: [string, string]}}
*/
const paths = {
ts: ['./src/**/*.ts', '!./src/web-bundle.ts'],
};
/**
* Test TS lint
* @return {*}
*/
function testTsLint() {
return gulp.src(paths.ts).
pipe(eslint()).
pipe(eslint.format()).
pipe(eslint.failAfterError());
}
/**
* Clean dist folder
* @return {*}
*/
function cleanDist() {
return gulp.src('dist/*').
pipe(gulpClean({force: true}));
}
/**
* Build JS from TS
* @return {*}
*/
function buildJS() {
return tsProject.src().pipe(tsProject()).js.pipe(gulp.dest('dist'));
}
const tests = gulp.parallel(testTsLint);
exports.tests = tests;
const clean = gulp.series(cleanDist);
exports.clean = clean;
const build = gulp.series(tests, cleanDist, buildJS);
exports.build = build;
export default build;
Созданы всего 3 задачи:
cleanDist
- для очистки предыдущих сборок.buildJS
- собственно сама сборка JS из TS.testTsLint
- запуск линтирования.
Настройка webpack
Запуск сборки web
-бандла мы будем производить с помощью задач webpack
, для этого создадим файл конфигурации webpack.config.js
в корне проекта со следующим содержимым:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin;
const buildConfig = {
entry: {
'web-bundle': './src/web-bundle.ts',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
const outputExampleWebVoiceControl = Object.assign({}, buildConfig, {
output: {
filename: 'web-bundle.js',
path: path.resolve(__dirname, 'examples/example-web'),
},
plugins: [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: [
path.resolve(__dirname,
'./examples/example-web/web-bundle.js'),
],
}),
],
});
module.exports = [outputExampleWebVoiceControl];
Настройка npm
Задачи линтирования и сборки созданы, теперь добавим команды в package.json
:
{
"scripts": {
"build:dev": "gulp build && webpack --mode=development",
"build:prod": "gulp build && webpack --mode=production",
"test": "gulp tests"
}
}
Запуск сборки и линтирования
В директории ./src
создаем тестовый проект. Интерфейс логирования ILog.ts
:
interface ILog {
log(message: string): boolean;
}
А также его реализацию для консоли ConsoleLog.ts
:
/**
* Class ConsoleLog
*/
class ConsoleLog implements ILog {
/**
* log
* @param {string} message
* @return {boolean}
*/
public log(message: string): boolean {
console.log(message);
return true;
}
}
export {ConsoleLog};
И реализацию для web TextAreaLog.ts
:
/**
* Class TextAreaLog
*/
class TextAreaLog implements ILog {
private element?: HTMLTextAreaElement;
/**
* setTextAreaElement
* @param {HTMLTextAreaElement} element
*/
public setTextAreaElement(element: HTMLTextAreaElement): void {
this.element = element;
}
/**
* log
* @param {string} message
* @return {boolean}
*/
public log(message: string): boolean {
if (this.element !== undefined) {
this.element.value = this.element.value + message + '\n';
return true;
}
return false;
}
}
export {TextAreaLog};
Для использования в web создадим бандл:
import {TextAreaLog} from './classes/TextAreaLog';
import {ConsoleLog} from './classes/ConsoleLog';
const logTextArea = new TextAreaLog();
const logConsole = new ConsoleLog();
declare global {
interface Window {
logTextArea: TextAreaLog;
logConsole: ConsoleLog;
}
}
window.logTextArea = logTextArea;
window.logConsole = logConsole;
Для использования вне бандла мы экспортируем необходимый функционал в window
.
После запуска команды build:dev
или build:prod
в директории ./dist
будут созданы сборки.
Примеры использования сборок находятся в директории ./examples
.
Консольный пример example-node-console
:
const {ConsoleLog} = require('../../dist/classes/ConsoleLog');
const logConsole = new ConsoleLog();
logConsole.log('First message');
logConsole.log('Second message');
Для запуска используем команду:
node index.babel.js
Консольный пример example-babel-node-console
с синтаксисом ES6
:
import {ConsoleLog} from '../../dist/classes/ConsoleLog';
const logConsole = new ConsoleLog();
logConsole.log('First message');
logConsole.log('Second message');
Для запуска используем команду:
babel-node index.babel.js
Пример для web example-web
:
<!DOCTYPE html>
<html lang="en">
<head>
<title>TypeScript example basic!</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="row">
<div id="log">
<label>
<textarea id="textarea" rows="5" cols="33"></textarea>
</label>
</div>
</div>
<script src="web-bundle.js"></script>
<script src="log.js"></script>
</body>
</html>
window.logConsole.log('First message');
window.logConsole.log('Second message');
const textarea = document.getElementById('textarea');
window.logTextArea.setTextAreaElement(textarea);
window.logTextArea.log('First message');
window.logTextArea.log('Second message');
Файл web-bundle.js
собирается из web-bundle.ts
.
Для запуска используем команду в корне приложения, демонстрирующего пример работы с web:
http-server
Затем открываем предложенную ссылку в браузере.
Настройка линтирования в PHPStorm
Об ошибках, обнаруженных при линтинге, мы узнаем только во время запуска теста, но хорошо бы видеть их и во время написания кода. Для этого можно подключить конфигурацию из проекта в IDE. Откроем настройки линтирования по следующему пути:
File | Settings | Languages & Frameworks | JavaScript | Code Quality Tools | ESLint
Выберем Manual ESLint configuration
и сохраним настройки.
Теперь и PHPStorm
будет подсвечивать несоблюдение правил линтирования при редактировании.
А также в контекстном меню при клике по файлу js
появится пункт Fix ESLint Problems
, который будет исправлять файл в соответствии со стандартом линтирования.
Дата редактирования : 2020-11-12 00:40:45
Автор : Rosko