Этот материал призван продемонстрировать начальные шаги по созданию нод-проекта на машинописном языке с нуля 🚀
📙ПРОЧИТАЙТЕ ПРЕДЛОЖЕНИЕ
Приведенные ниже материалы являются рекомендациями для получения новых знаний, их не следует воспринимать как обязательное условие для прочтения или выполнения содержащихся здесь действий:
- Введение в Node.js (Single-Thread, Event-Loop и Marketplace)
- NVM — Управление несколькими установками Node.js
Я рекомендую использовать ESLint + Prettier + EditorConfig во всех проектах.
✔️ОБЯЗАТЕЛЬНО
- NodeJS
- NPM или Yarn
- Vscode*
В этом материале я буду использовать yarn в качестве менеджера пакетов
📦 ИСПОЛЬЗУЕМЫЕ ПАКЕТЫ
- машинопись
- ts-узел-dev
- римраф
- эслинт
- красивее
- шутка
- дотенв
- кор
- выражать
💻 ПРИСОЕДИНЯЕМСЯ К РАБОТЕ
Запустите каталог как проект Node.
Пример:
yarn init -y
Папки
Первоначально создайте структуру папок, чтобы начать организацию проекта. На личный вкус я структурирую папки следующим образом:
src
: Основная папка проекта;src/config
: Папка настроек проекта;src/modules
: Основные модули проекта. В этом сценарии числа и строки были созданы для примера;src/shared/errors
: Папка настроек для общих ошибок проекта;src/infra/http
: Папка настроек сервера приложений;src/infra/http/routes
: Папка настроек всех маршрутов приложений;
Эта структура папок является личным вкусом автора. Не стесняйтесь использовать свой.
EditorConfig
Это один из тех технологически независимых плагинов. Создайте файл .editorconfig
в корне проекта и добавьте следующую конфигурацию:
root = true [*] indent_style = space indent_size = 2 charset = utf-8 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true
Чтобы узнать больше о .editorconfig
, перейдите по ссылке -› https://editorconfig.org/
Начальные настройки
Давайте начнем с установки наших первых зависимостей для разработки:
yarn add typescript ts-node-dev rimraf @types/node -D
typescript
: Установите TypeScript и командную строку tsc;ts-node-dev
: Веб-сервер разработки для TypeScript;rimraf
: Этот модуль автоматически удаляет старые сборки;@types/node
: определение типов для собственного набора API/модулей NodeJS;
Выполните приведенную ниже инструкцию, чтобы сгенерировать tsconfig.json
(файл определений TypeScript):
yarn tsc --init --outDir "build" --rootDir "src"
Приведенная выше инструкция генерирует файл настроек с двумя переданными нами ссылками:
outDir
: каталог, в котором будет создана сборка проекта;rootDir
: Корневой каталог, в котором находится наш код TypeScript;
ESLint и красивее
Чтобы поддерживать хороший синтаксис и форматирование, необходимо использовать их вместе. Для этого установите его, запустив:
yarn add eslint prettier eslint-config-prettier eslint-plugin-prettier eslint-plugin-simple-import-sort -D
eslint
: анализирует код, проверяет синтаксические ошибки, форматирование и другие аспекты;prettier
: Займитесь форматированием и стандартизацией кода;eslint-config-prettier
: отключает правила ESLint, конфликтующие с Prettier;eslint-plugin-prettier
: позволяет запускать Prettier как правило ESLint;eslint-plugin-simple-import-sort
: Организует наш импорт в алфавитном порядке;
Приведенная ниже инструкция создаст файл определений .eslintrc.*
:
yarn eslint --init
Воспроизведите ответы, как показано ниже:
1 . Давайте настроим ESLint с фокусом на синтаксис и обнаружением проблем:
2 . Мы будем использовать шаблон импорта/экспорта ES6:
3 . Мы не будем использовать ни один из перечисленных фреймворков:
4 . Мы будем использовать TypeScript:
5 . Наш код будет работать на NodeJS:
6 . Формат, в котором будет создан файл настроек ESLint. Выберите JSON:
7 . Здесь мы ответим НЕТ на запрос об установке зависимостей определения типа. Этот путь необходим, так как они будут установлены с NPM, но мы используем YARN:
Теперь давайте установим две зависимости, упомянутые на шаге 7, в качестве зависимостей разработки:
yarn add @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest -D
Теперь отредактируйте сгенерированный файл (.eslintrc.json
) и замените его содержимое на:
{ "env":{ "es2020":true, "node":true }, "extends":[ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "parser":"@typescript-eslint/parser", "parserOptions":{ "ecmaVersion":2018, "sourceType":"module" }, "plugins":[ "@typescript-eslint" ], "rules":{ "prettier/prettier":"error", "no-useless-constructor":"off", "no-unused-vars":"off", "camelcase":"off", "@typescript-eslint/no-unused-vars":[ "warn", { "argsIgnorePattern":"^_" } ], "@typescript-eslint/naming-convention":[ "error", { "selector":"interface", "format":[ "PascalCase" ], "custom":{ "regex":"^I[A-Z]", "match":true } } ], "class-methods-use-this":"off", "import/extensions":"off" }, "settings":{ "import/resolver":{ "typescript":{ } } } }
Теперь создайте файл с именем .eslintignore
и добавьте в него этот контент:
node_modules build
Теперь создайте файл с именем prettier.config.js
и добавьте в него следующее содержимое:
module.exports = { singleQuote: true, trailingComma: 'all', arrowParens: 'avoid', };
singleQuote: true
› Использовать одинарные кавычки (‘);trailingComma: 'all'
› Чтобы всегда добавлять запятую (,) в конец объекта, разбитого на несколько строк;arrowParens: 'avoid'
› Чтобы круглые скобки (()) не добавлялись, когда стрелочная функция имеет только один параметр;
Шутка
Установка зависимостей:
yarn add jest ts-jest @types/jest -D
Чтобы создать файл определений Jest (jest.config.js
), просто запустите:
yarn jest --init
Появится викторина. Ответьте на вопросы анкеты по приведенным ниже ссылкам:
Шаг 3 позволяет нам работать с покрытием кода, то есть мы можем указать пути, которые должен наблюдать Jest, который, в свою очередь, сообщит, какая часть кода покрыта тестом, а какая именно не покрыта. Если вам не нужна эта функция, просто ответьте нет.
Отредактируйте файлjest.config.js
, найдите переменные preset и testMatch и задайте для них следующие значения:
preset: 'ts-jest', testMatch: ['**/*.spec.ts'],
Лично мне нравится централизовать все тесты в *.spec.ts
файлах по модулям проекта, кроме того, поскольку проект на TypeScript, нет ничего более справедливого, чем искать только файлы .ts . Чем проще регулярное выражение, тем быстрее будет выполняться поиск файлов.
Отредактируйте файл .eslintrc.json
и добавьте свойство "jest": true
следующим образом:
{ "env": { "es2020": true, "node": true, "jest": true //... code omitted
Если вы заинтересованы в использовании покрытия, вам нужно будет отредактировать файл jest.config.js
, найти и определить переменные следующим образом:
collectCoverage: true, collectCoverageFrom: ['<rootDir>/src/modules/**/services/*.ts'], coverageDirectory: 'coverage', coverageReporters: [ 'text-summary', 'lcov' ],
В collectCoverageFrom вы должны указать массив, содержащий расположение всех файлов, которые должны быть покрыты покрытием. Предполагая, что я хочу охватить другой каталог, который находится на том же уровне, что и сервисы, я бы просто добавил условие регулярного выражения: <rootDir>/src/modules/**/(services|helpers)/*.ts
. Другие шаблоны регулярных выражений см. в официальной документации.
Результат покрытия будет воспроизводиться в каталоге, указанном в переменной: coverageDirectory, не забудьте добавить этот каталог в .gitignore
.
Создайте папку services по адресу src/modules/numbers
и создайте файл Sum.spec.ts.
Добавьте к нему этот контент ( src/modules/numbers/services/Sum.spec.ts
):
describe('Only one test', () => { it('Sum 1 + 1 = 2', () => { expect(1 + 1).toBe(2); }); });
Файл выше предназначен только для проверки правильности работы Jest.
Теперь запустите команду:
yarn test
В результате у нас будет следующий вывод в консоли:
- Результат каждого из шагов;
- Сводка покрытия, то есть тестовое покрытие. Помните, что в файле
jest.config.js
мы заполнили определение collectCoverageFrom? Сводка покрытия вычисляет покрытие тестами для путей, указанных в collectCoverageFrom; - Резюме теста;
Какая же это не красивая вещь! Но вишенка на торте находится в ./covarage/lcov-report/index.html, откройте этот файл в браузере и посмотрите покрытие ваших тестов.
Поскольку в нашем приложении все еще нет кода, охваченного кодом, очевидно, результатом будет страница без данных о покрытии.
Вам нужно будет отредактировать tsconfig.json
и добавить оба покрытия в список игнорируемых каталогов:
"exclude": ["coverage"]
Приведенное выше определение должно быть введено на том же уровне, что и compilerOptions, а не как внутренний элемент. Если вы забудете добавить это определение в файл, процесс сборки завершится ошибкой.
Настройка package.json
Отредактируйте package.json, найдите сеанс main
и scripts
и измените их, как показано ниже:
"main": "./build/shared/infra/http/server.js", "scripts": { "build": "rimraf ./build && tsc", "dev": "ts-node-dev --respawn --transpile-only --inspect -- ./src/shared/infra/http/server.ts", "lint": "eslint --fix --ext .js,.ts,.json .", "test": "jest" }
main
: указывает конечную точку нашего приложения. Обратите внимание, что мы указываем на каталог сборки, то есть при запуске node . эта конечная точка будет вызываться;build
: использует rimraf для исключения каталога ./build, затем создает файлы JavaScript с помощью tsc ;dev
: запустите ts-node-dev;- =›
--respawn
: активировать режим просмотра; - =›
--transpile-ony
: Заботьтесь только о выполнении (перенесите код в JavaScript), это гарантирует лучшую производительность; - =›
--inspect
: Включить подключение средств отладки; - =›
./src/shared/infra/http/server.ts
: точка входа нашего приложения; lint
: позволяет запускать ESLint через терминал;test
: запустить тесты;
Чтобы запустить любой из созданных скриптов, просто запустите:
yarn name_script
Выражать
Вот зависимости:
yarn add express dotenv cors
- экспресс: простая и гибкая микроструктура;
- cors (независимое происхождение): спецификация, определяющая средства для удаленного доступа к ресурсу сервера через Интернет/сеть; Вкратце, cors позволяет получить доступ к нашему приложению с внешнего адреса;
- dotenv: модуль без зависимостей, отвечающий за загрузку переменных среды из файла
.env
в process.env.*.
Вам нужно будет установить определения типов Express:
yarn add @types/express @types/cors -D
Теперь создайте файл .env
в корне проекта и присвойте ему следующее значение:
APP_PORT=3000
В этом файле будет храниться конфиденциальная информация о приложении, поэтому он не имеет версий. Создайте образец файла
.env.example
, он может содержать неконфиденциальную предварительно заполненную информацию. Пример:
APP_PORT=3000
Создайте файл AppError.ts в папке ./src/shared/errors/AppError.ts:
class Error { public readonly message: string; public readonly statusCode: number; constructor(message: string, statusCode: number) { this.message = message; this.statusCode = statusCode; } } export default Error;
Создайте файл маршрутов./src/shared/infra/http/routes/index.ts:
import { Router } from 'express'; const router = Router(); router.get('/', (req, res) => { res.json({ message: 'Hello world!' }); }); export default router;
Теперь создайте файл ./src/shared/infra/http/server.ts со следующим содержимым:
import 'dotenv/config'; import express, { Request, Response, NextFunction } from 'express'; import cors from 'cors'; import routes from './routes'; import AppError from '../../errors/AppError'; const app = express(); app.use(cors()); app.use(express.json()); app.use(routes); app.use((err: Error, request: Request, response: Response, _: NextFunction) => { if (err instanceof AppError) { return response.status(err.statusCode).json({ status: 'error', message: err.message, }); } console.error(err); return response.status(500).json({ status: 'error', message: 'Internal server error', }); }); const port = Number(process.env.APP_PORT) || 3000; app.listen(port, () => { console.log(`🚀 Server running on the port: ${port}`); });
Чтобы проверить результат, просто запустите в корне проекта:
yarn dev
Если все прошло хорошо, мы получим следующий вывод:
Прохладный! Наше приложение работает на порту 3000, для доступа к нему просто позвоните: http://localhost:3000 и у нас на выходе будет красивый и красивый JSON:
{ "message": "Hello World!" }
Заключение
В этом материале представлен быстрый способ настройки исходных зависимостей проекта с использованием nodejs и машинописного текста.
Спасибо, что читаете 😜 🚀