Как заставить Vue.js2, TypeScript, webpack, ESLint и VSC работать вместе

Введение

Сколько времени средний разработчик JavaScript вкладывает в настройку нового проекта? Примерно вечность. Вот почему я считаю очень важным получить представление о том, как на самом деле работает наш пояс для инструментов. В этой статье я рассмотрю типичную настройку клиентского приложения, созданного с помощью Vue.js2 и TypeScript. Используемый инструментарий будет:

  • ESLint + Prettier + stylelint для линтинга + форматирования
  • webpack + зависимости для нашего процесса сборки
  • Мокко + Чай + Синон на тестирование.

Если вы не согласны с некоторыми из моих вариантов, я буду рад услышать ваши идеи и, возможно, обновить эту статью.

Prerequesites

В этом руководстве предполагается, что у вас есть следующее:

Запустить проект

Я опишу отдельные шаги, которые я прохожу при создании нового проекта. Если вы ищете информацию по определенной теме, просто пропустите ее.

TL; DR: Вы также можете просто клонировать это репозиторий GitHub.

Код Visual Studio

Начнем с настройки VS Code. Создайте папку проекта и откройте ее в VS Code. Затем сохраните его как рабочую область в этой папке (Файл ›Сохранить рабочую область как›…). Это приведет к созданию xx.code-workspace файла, который позволит нам указать конфигурации для этого рабочего пространства. Открытие этого файла также откроет вашу рабочую область в VS Code.

Наша окончательная конфигурация рабочего пространства будет выглядеть так:

Затем мы установим несколько (я бы даже сказал, важных) расширений:

  • ESLint интегрирует нашу линковку в наш редактор кода и сообщит вам, когда вы нарушите правила стиля своего кода или совершите еще более ужасные злодеяния.
  • stylelint интегрирует линтинг для файлов стилей в редактор и поддерживает автоисправление.
  • GitLens интегрируется с системой контроля версий Git. Он позволяет вам делать большинство удивительных вещей, которые может делать Git, но прямо в редакторе кода.
  • Vetur предлагает множество инструментов, специфичных для Vue, от выделения синтаксиса до фрагментов кода.
  • Отладчик для Chrome позволяет нам отлаживать исходный код нашего приложения в VS Code при запуске приложения в Chrome.

.editorconfig

Этот короткий файл конфигурации используется для передачи основных стилей редактора различным редакторам - например, tab-size. Вы можете прочитать больше об этом здесь".

Обычно я использую одни и те же настройки для всех типов файлов:

.nvmrc

Это почти тривиально, но если вы используете разные версии Node.js в своих проектах, это очень удобно. Наличие файла .nvmrc в корневом каталоге позволяет заблокировать версию Node.js, которую вы используете. Он содержит одну строку с номером версии - например, 12.14.1. Глянь сюда".

package.json

Затем мы создадим package.json файл нашего проекта. Этот файл принадлежит экосистеме диспетчера пакетов Node (npm). Он содержит некоторую конфигурацию вашего проекта, используется для управления сторонним кодом, используемым вашим приложением (зависимостями), и позволяет вам определять простые сценарии, которые обычно используются для запуска инструментов командной строки с правильными параметрами.

Обычно он создается с помощью команды npm init, но вы также можете просто создать файл client / package.json вручную. Если вы использовали npm init и приняли все значения по умолчанию, ваш файл будет выглядеть так:

Мы будем постепенно обновлять этот файл - пока мы можем оставить его в таком виде. Я призываю вас узнать об этом подробнее здесь.

Git

Если вы никогда о нем не слышали, Git - наиболее широко используемая система контроля версий (и с большим отрывом). Проще говоря, Git позволяет копировать, вставлять, возвращать и объединять код. Это помогает разработчикам работать с одной и той же кодовой базой, не мешая друг другу (в основном), и одновременно предоставляет подробную историю изменений всего проекта. Скажем так, это круто.

Создаем новый репозиторий Git с помощью команды git init.

Если вы хотите поделиться своим кодом, очень полезно добавить в проект удаленный репозиторий (например, на GitHub). Это позволяет вам push ваш код на общедоступном сервере. Вы добавляете удаленный репозиторий с помощью команды:

git remote add <remoteName> <remoteURL>

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

TypeScript

TypeScript - это надмножество JavaScript (он содержит все функциональные возможности JavaScript, но добавляет некоторые функциональные возможности поверх - например, статическая типизация). Он стал чрезвычайно популярным для создания производственных приложений с использованием JavaScript и, вероятно, вскоре станет стандартным способом написания JavaScript. Если вы хотите узнать о преимуществах (недостатках) TypeScript, я рекомендую эту статью.

Чтобы запустить TypeScript, нам просто нужно установить глобальный пакет npm:

npm install -g typescript

Этот пакет позволяет нам компилировать .ts файлов в .js с помощью команды tsc - например, tsc index.ts Эта команда создаст .js файл с тем же именем в той же папке, что и исходный файл .ts. (Мы не будем использовать эту команду, поскольку используем webpack.)

Затем запустите tsc --init в корневой папке (Client). Это создаст файл tsconfig.json, заполненный аккуратной сводкой доступных параметров компилятора (что отлично подходит для людей с памятью типа мусорной панды, таких как я).

Мы добавим в него еще несколько конфигов - посмотрите, пожалуйста:

Вы можете прочитать более подробное описание всех опций на официальном сайте TypeScript.

Линия / форматирование

Чистый код выглядит так, как будто его написал один человек. Линтеры позволяют нам применять определенные правила, чтобы сделать наш код в целом более читабельным. Как правило, линтеры состоят из правил двух типов, обеспечивающих единообразный стиль кодирования: правила форматирования (например, строки не могут быть длиннее 100 символов) и правила качества кода (например, избегать использования let в пользу const).

Наиболее часто используемый линтер в JavaScript - это ESLint. Мы будем использовать его, а также его замечательное сообщество, которое уже создало несколько полезных плагинов - например, тот, который применяет стили Vue к отдельным файловым компонентам.

Примечание. До выпуска typescript-eslint вам приходилось полагаться на TSLint для линтинга кода TypeScript. Однако использовать дополнительные инструменты в экосистеме ESLint с TSLint невозможно. Вот почему я рекомендую всем использовать typescript-eslint, хотя его конфигурация немного сложнее.

Установим все необходимые зависимости:

  • eslint: базовый пакет ESLint
  • vue-eslint-parser: настраиваемый парсер, позволяющий ESLint анализировать .vue файлы. Результатом этого парсера будет .js файл с импортированными зависимостями, представляющими блоки вашего файла (например, <template> или <style>).
  • @typescript-eslint/parser: Мы скажем vue-eslint-parser использовать этот синтаксический анализатор для интерпретации <script> блока, записанного в наших .vue файлах.
  • @typescript-eslint/eslint-plugin: плагин ESLint, который применяет специфичные для TypeScript правила.
  • eslint-plugin-vue: применяет специфичные для Vue правила линтинга к однофайловым компонентам - например, упорядочивает параметры компонентов или атрибуты элементов.
  • prettier && eslint-config-prettier && eslint-plugin-prettier: Эти пакеты позволяют использовать Prettier вместе с ESLint. Prettier - это мощный инструмент для форматирования кода с отличными возможностями автофиксации.
npm i -D eslint vue-eslint-parser @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-vue prettier eslint-config-pretter eslint-plugin-prettier

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

Конечно, вы можете изменить правила по своему усмотрению - главное - придерживаться одного набора правил. Подробнее про ESLint можно прочитать здесь.

Примечание. Мы также добавляем конфигурацию Prettier в файл .prettierrc.

{
  "arrowParens": "always",
  "trailingComma": "all",
  "singleQuote": true,
  "printWidth": 120,
  "tabWidth": 2
}

stylelint

Вы, наверное, догадались - stylelint позволяет вам применять правила для ваших различных файлов стилей. Это не так важно, как линтинг JavaScript; тем не менее, мне нравятся мои файлы аккуратными.

npm i -D stylelint stylelint-webpack-plugin stylelint-config-sass-guidelines stylelint-config-standard

Добавьте файл .stylelintrc в корневую папку и добавьте свою конфигурацию:

Примечание. Отключите правило no-empty-source - в противном случае stylelint выдаст ошибки для .vue файлов без блоков стилей.

Автоисправление

Замечательной особенностью ESLint, Prettier и stylelint является автоматическое исправление общих проблем путем выполнения команд с флагом --fix. Еще лучше: расширения VS Code, которые мы установили ранее, предоставляют нашему редактору кода возможности автоисправления. Ответственная конфигурация находится в конфигурации нашей рабочей области (<projectname>.code-workspace), которую мы создали выше.

Примечание. Не забудьте отключить программу форматирования кода, принадлежащую редактору, чтобы избежать конфликтов.

Хуки Git

На этом этапе я также хотел бы познакомить вас с некоторыми инструментами. Библиотека Husky предоставляет нам простой способ установить хуки Git, позволяя запускать некоторый код каждый раз, когда вы отправляете действие Git (например, commit).

Ответственный фрагмент кода находится на корневом уровне нашего package.json файла. Мы используем хук pre-commit, чтобы проверить наш проект на наличие ошибок линтинга и запустить наши модульные тесты. Если ESLint сообщает об ошибке, фиксация прерывается.

“husky”: {
  “hooks”: {
    “pre-commit”: “npm run lint && npm run test”
  }
},

Узнать больше о Хаски.

webpack 4

Webpack - это сборщик модулей с открытым исходным кодом для JavaScript, который также хорошо работает с TypeScript. Webpack позволяет нам в основном просматривать все файлы нашего проекта и объединять их в один выходной файл (или несколько выходных файлов) и обрабатывать все файлы, пока мы работаем. Таким образом, webpack служит отправной точкой для целого мира инструментов. Ты сможешь:

  • Напишите код с новейшими функциями ES2020 и автоматически перенесите его в ES5, понятный каждому тостеру
  • Автоматически минимизировать ваш код, чтобы сохранить размер файла
  • Легко интегрируйте препроцессоры CSS, такие как SASS
  • При необходимости автоматически применять префиксы CSS с PostCSS
  • Используйте большой набор инструментов, предназначенных для анализа вашего кода
  • Легко применять разделение кода

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

Прежде чем мы углубимся в файл конфигурации, давайте установим все зависимости:

  • webpack: базовый пакет
  • webpack-cli: интерфейс командной строки (мы используем его со сценарием npm)
  • webpack-dev-server: сервер разработки, позволяющий выполнять горячую перезагрузку при изменении файлов и обслуживающий наше приложение в режиме разработки.
  • clean-webpack-plugin: используется для очистки / удаления нашей выходной папки
  • html-webpack-plugin: создает HTML-файл для обслуживания нашего набора приложений. Он динамически вставляет теги ссылок с соответствующими хешами и работает вместе с другими плагинами, поддерживая разумную стратегию предварительной загрузки.
  • copy-webpack-plugin: копирует отдельные файлы или целые каталоги в папку сборки
  • optimize-css-assets-webpack-plugin: оптимизирует / минимизирует ресурсы CSS
  • mini-css-extract-plugin: загружает CSS наших однофайловых компонентов в отдельные файлы
  • terser-webpack-plugin: используется для минимизации JavaScript
  • critters-webpack-plugin: используется для встраивания критического CSS и отложенной загрузки остального (документация здесь)
  • stylelint-webpack-plugin: позволяет нам интегрировать линтинг стилей в наш процесс сборки.
  • webpack-node-externals: позволяет нам легко указать веб-пакету, что он не должен включать node_modules в наш пакет. Мы будем использовать это для наших модульных тестов - нет необходимости включать их туда.
npm install -D webpack webpack-cli webpack-dev-server clean-webpack-plugin html-webpack-plugin copy-webpack-plugin optimize-css-assets-webpack-plugin mini-css-extract-plugin terser-webpack-plugin critters-webpack-plugin stylelint-webpack-plugin webpack-node-externals

webpack преобразует все файлы с помощью так называемых загрузчиков.

Упрощенно, это функции, которые Webpack вызывает для каждого файла, который соответствует определенному условию. Затем загрузчики анализируют / интерпретируют / преобразовывают файл и передают его следующему загрузчику или обратно в webpack. Затем webpack записывает файл в свою выходную папку.

Мы будем использовать целый набор загрузчиков (и некоторые зависимости). Установим их:

npm install -D vue-loader vue-template-compiler url-loader ts-loader style-loader sass-loader node-sass raw-loader file-loader css-loader postcss-loader autoprefixer babel-loader @babel/core @babel/preset-env core-js thread-loader cache-loader eslint-loader
  • url-loader: делает то, что говорит
  • ts-loader: загрузчик TypeScript для webpack
  • style-loader: вставляет CSS в DOM / HTML с помощью тегов <style>
  • vue-loader && vue-template-compiler: загружает .vue файлов и позволяет использовать отдельные загрузчики для всех блоков (включая пользовательские блоки). Компилятор шаблонов необходим для предварительной компиляции HTML-шаблонов.
  • sass-loader && node-sass: загружает Sass / SCSS и компилирует его в CSS. Примечание. Если вы используете Sass в своем проекте, вам также необходимо установить node-sass, который позволяет узлу понимать Sass (подробнее).
  • raw-loader: позволяет нам импортировать файлы в виде строки
  • file-loader: преобразует импортированные файлы в URL (используется для файлов, таких как изображения)
  • css-loader: интерпретирует и разрешает импорт CSS
  • postcss-loader && autoprefixer: загрузчик для обработки вашего CSS с помощью PostCSS. autoprefixer - это модуль, используемый PostCSS, который ставит префикс CSS для обеспечения кросс-браузерной совместимости. Вы можете настроить PostCSS (для использования autoprefixer) либо в конфигурации вашего веб-пакета, либо в отдельном файле postcss.config.js.
module.exports = {
  plugins: [
    require(‘autoprefixer’),
  ],
}
  • babel-loader && @babel/core && @babel/preset-env && core-js: позволяет использовать Babel вместе с webpack. Babel переносит вывод JavaScript ts-loader в более раннюю версию JavaScript и добавляет core-js полифиллы для обеспечения совместимости с браузером.

Для работы Babel требуется некоторая базовая конфигурация. Создайте .babelrc файл в корне вашего проекта со следующим содержимым:

{
  “presets”: [
    [
      “@babel/preset-env”,
      {
        “targets”: {
          “ie”: “11”
        },
        “useBuiltIns”: “usage”,
        “corejs”: “3”
      }
    ]
  ]
}

Мы просто говорим Babel использовать конфигурацию preset-env, преобразовать наш JavaScript в целевой Internet Explorer 11 и выполнить полифил, используя core-js @ 3.

  • thread-loader: позволяет следующим загрузчикам в этой цепочке загрузчиков использовать несколько потоков. Это ускорит работу тяжелых погрузчиков, таких как babel-loader.
  • cache-loader: кэширует вывод загрузчиков, что ускоряет последовательные сборки
  • eslint-loader: позволяет нам линтовать все файлы перед их обработкой

Наконец, давайте добавим еще один аддон, который анализирует размер пакета нашего приложения:

npm install -D webpack-bundle-analyzer

Конфигурация, которая собирает все вместе, выглядит так:

Эта конфигурация также будет нашей конфигурацией для webpack-dev-server, удобного инструмента, обслуживающего наше приложение во время разработки и предлагающего горячую перезагрузку модуля. Для запуска и сборки нашего приложения мы используем указанный выше npm scripts:

// Client/package.json
{
  ...
  "scripts": {
    "start": "webpack-dev-server --host 0.0.0.0 --hot",
    "build": "webpack -p --progress",
    ...
  },
  ...
}

Флаг --hot включает горячую перезагрузку, -p устанавливает env.mode на production, а --progress указывает webpack отображать прогресс сборки в процентах.

Тестирование (Мокко, Синон, Чай)

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

Мы используем библиотеку-оболочку вокруг Mocha для запуска наших тестов с Mochapack. Это позволяет нам сначала собрать наш проект с помощью webpack, а затем запустить наши модульные тесты с нашим созданным проектом.

Установим все зависимости:

npm install -D mocha mochapack jsdom jsdom-global @types/mocha chai @types/chai sinon @types/sinon @vue/test-utils
  • mocha && @types/mocha: наш тестовый исполнитель (процесс, в котором выполняются наши тесты)
  • moochapack: оболочка вокруг Mocha, чтобы мы могли собрать наш проект с помощью webpack, прежде чем запускать на нем тесты
  • chai && @types/chai: библиотека утверждений. Он дает нам вспомогательные функции для удобного синтаксического сравнения значений.
  • sinon && @types/sinon: библиотека заглушек. Он позволяет нам легко заменять свойства / методы объектов и содержит множество полезных вспомогательных функций для проверки их поведения.
  • @vue/test-utils: служебные функции для тестирования компонентов Vue
  • jsdom && jsdom-global: реализация на JavaScript многих веб-стандартов (HTML5 / веб-API), обычно используемых для имитации поведения браузера. jsdom-global внедряет эту реализацию DOM в среду выполнения Node.

Обычно вы создаете setup.ts файл в своей client/tests папке, в котором инициализируете среду, которая может понадобиться для запуска тестов. В базовой настройке это может быть просто jsdom:

// client/tests/setup.ts
require('jsdom-global')();

Теперь мы можем просто создавать наши модульные тесты - как тестировать Vue, их команда хорошо задокументировала.

Наконец, давайте настроим npm script для их запуска:

"scripts": {
  ...
  “test”: “mochapack”,
  “test:watch”: “mochapack --watch”
}

Флаг --watch указывает Mocha не выходить из процесса, а вместо этого следить за изменениями файлов и повторно запускать тесты в файлах изменений (удобно для разработки).

При выполнении mochapack автоматически ищет mochapack.opts файл в папке вашего package.json. Мы используем этот файл для определения некоторых параметров командной строки:

// mochapack.opts
--colors
--webpack-config webpack.config.js
--webpack-env test
--require test/unit/setup.ts
--recursive
'test/**/*.spec.{js,ts}'
  • --colors: заставляет Mocha использовать цвета при выводе через терминал.
  • --webpack-config: указывает конфигурацию веб-пакета, которую мы хотим использовать.
  • --webpack-env: указывает среду веб-пакета. Если вы посмотрите на конфигурацию нашего веб-пакета, то заметите, что в тестовом режиме у нас немного другое поведение.
  • --require: указывает Mocha запустить и выполнить файл перед запуском тестов.
  • --recursive: Ищите тесты в подкаталогах
  • ’test/**/*.spec.{js,ts}': Глобус для сопоставления файлов, которые должны быть включены, объединены веб-пакетом и запущены Mocha. В этом случае все наши модульные тесты расположены в каталоге test и оканчиваются на .spec.ts или .spec.js.

Подсказка: я обычно не слишком беспокоюсь о полном тестировании, поскольку я тестирую только код, который, вероятно, вызовет проблемы в будущем. Однако, если вы это сделаете, я предлагаю вам взглянуть на инструмент тестового покрытия Istanbul, точнее, их CLI-инструмент nyc (ссылка).

Отладка

К счастью, отладка в VS Code довольно проста. Просто добавьте папку Client/.vscode и создайте внутри файл launch.json.

Мы настроим три конфигурации запуска для нашего приложения:

Наши первые конфигурации позволяют нам отлаживать наши модульные тесты. Просто установите точки останова, выберите эту конфигурацию и запустите отладчик (F5).

Во втором конфиге используется расширение VS Code под названием Отладчик для Chrome. Это позволяет нам запускать наше приложение в Chrome, используя точки останова в исходном коде. Просто установите точки останова (например, в ловушке mounted()), запустите приложение (npm run start), а затем запустите отладчик, выбрав конфигурацию и нажав F5.

Настройка Vue

Наконец, пришло время поработать над вашим настоящим проектом! Я предполагаю, что все, кто дошел до этого, уже знакомы с самим Vue (у них также есть отличная документация). Поэтому я упомяну только несколько общих проблем при работе с TypeScript и назову несколько отличных модулей, которые я использую для конкретных случаев использования.

vue-property-decorator

Самый простой способ написать компоненты Vue с помощью TypeScript - это синтаксис на основе классов. Этот синтаксис требует для работы нескольких декораторов TypeScript. Возможно, вы слышали о vue-class-component в этом контексте. Однако эта библиотека предназначена для поддержки пользователей Babel рядом с пользователями TypeScript - и Babel конфликтует с некоторыми декораторами, содержащимися в vue-property-decorator.

Поскольку мы компилируем все наши декораторы с помощью TypeScript, мы можем без проблем использовать эту библиотеку. Подробнее об этом выпуске GitHub.

Объявление модулей * .vue

Чтобы TypeScript мог импортировать *.vue файлы, мы должны объявить их как модули. Интерфейс командной строки делает это в shims.vue.d.ts файле со следующим содержимым:

declare module ‘*.vue’ {
  import Vue from ‘vue’;
  export default Vue;
}

Если вы хотите расширить интерфейсы Vue, я рекомендую создать папку types на корневом уровне вашего проекта. В этой папке вы можете создавать подпапки, содержащие index.d.ts файлы. В этих файлах вы можете импортировать модуль, который хотите расширить. Например:

// client/types/vue/index.d.ts
import Vue from ‘vue’;
declare module ‘vue/types/vue’ {
  interface Vue {
    $myProp: string; // allows this.$myProp or vm.$myProp
  }
}

Вы можете найти больше информации о том, как расширить типы Vue здесь.

Чтобы сообщить TypeScript, что он должен включать наши определения типов в types/*, мы уже включили следующую строку в наш tsconfig.json.

“typeRoots”: [“./types”, “./node_modules/@types”]

Примечание. Важно поставить "./types" перед "./node_module/@types".

Последние мысли

Вот несколько модулей и плагинов, которые я настоятельно рекомендую:

  • Управление состоянием: vuex предлагает управление состоянием для vue, вдохновленное Redux. Совет: используйте vuex-smart-module для типизированного магазина. Подробнее здесь.
  • Управление URL-адресами: vue-router - это модуль, который позволяет нам управлять URL-адресами для нашего приложения Vue. Это сравнимо с React Router.
  • Мета-информация страницы: vue-meta - небольшая библиотека, позволяющая нам устанавливать метаданные страницы с параметрами компонентов (заголовок, метатеги и т. д.)
  • Переводы: vue-i18n позволяет легко переводить весь текст на разные языки.
  • WebWorker s: comlink - отличная крошечная библиотека (1,1 КБ), которая охватывает ваши WebWorkers и позволяет вам получать к ним доступ, как к обычным импортированным модулям.
  • IndexedDB: Dexie - это небольшая оболочка (18 КБ в сжатом виде) вокруг ужасного API IndexedDB. Он довольно производительный и имеет простой API.
  • AJAX. Честно говоря, я предпочитаю использовать нативный fetch. Но axios, как и vue-apollo, - отличные библиотеки для загрузки REST / GraphQL соответственно.
  • SSR. Самый простой способ использовать SSR с VueJS - это, без сомнения, NuxtJS. Тем не менее, он очень думает о том, как вы должны строить свой проект.

Что ж, спасибо за чтение! Надеюсь, эта статья кому-то поможет.