Как и зачем настраивать сборку, позволяющую писать компоненты .vue на TypeScript.
Хорошо, может быть, и не целый день, но настройка инструментов для нового проекта все равно занимает слишком много времени. И некоторые вещи на мой вкус все еще слишком сложны. Не хорошее "сложное", как в сложном. Скорее утомительно. Да, я говорю о webpack, TypeScript и .vue
файлах. Здесь я хочу показать, что я сделал, и почему я все же решил это сделать.
Если вы просто ищете быстрое исправление TypeScript, это относительно просто. Берите webpack-блоки и настраивайте менее чем за 5 минут. То, что я пытался сделать, было немного более экзотическим, если хотите. Я хотел использовать Vue и, в частности, .vue
файлы с TypeScript. Информация разбросана по всей сети, поэтому я подумал, что неплохо было бы собрать ее здесь в качестве краткого справочника.
ОБНОВЛЕНИЕ от 8 мая 2017 г. С тех пор, как я написал эту статью, почти выпущена версия webpack-blocks 1.0.0. Он уже доступен в NPM, поэтому я нашел время, чтобы выпустить некоторый код, обсуждаемый в этой статье. Я опубликую отдельный пост, в котором будут описаны изменения по сравнению с исходной статьей.
Прежде чем мы начнем, забудьте о том, что вы знаете о том, как писать компоненты Vue. Если вы хотите использовать .vue
файлы с TypeScript, вам нужно написать код TypeScript. Вы, конечно, можете кодировать по-старому, но тогда вы не получите никакой пользы от проверки типов, так что это просто пустая трата вашего времени. Вы были предупреждены.
Почему файлы .vue?
Прежде всего, позвольте мне объяснить, почему я хотел начать с .vue
файлов (если вы не знаете, что это такое, посмотрите здесь). Эти однофайловые многоязычные пакеты - это не просто средства для группировки того, что в противном случае было бы набором разрозненных файлов. Нет, у них есть свои навороты, которые выходят за рамки простого объединения кода.
Например, шаблоны HTML закодированы в HTML, поэтому вы получаете подсветку синтаксиса, автозаполнение с учетом контекста и / или поддержку emmet. Великих разработчиков JavaScript мало, поэтому кодирование простого HTML (в отличие от JSX и, что еще хуже, гиперкрипта) может иметь большое значение. Да, я знаю, что есть истории о дизайнерах и новичках, которые берут в руки гиперкрипт и тому подобное, и им действительно нравится, но тогда вы должны помнить, что даже опытные разработчики JavaScript иногда не сдаются без боя.
Во-вторых, CSS с областью видимости. Если вы все еще думаете, что БЭМ имеет место в правильно настроенной интерфейсной структуре, тогда хорошо, вы понимаете важность и проблемы хорошо организованного CSS. Вы можете получить удовольствие от ограниченного CSS. Я не собираюсь продавать вам CSS с ограниченной областью видимости. Это как наркотики: они продаются сами по себе. Просто попробуйте. Попробуй.
Все это, а также тот факт, что я имею дело с одним файлом, а не с тремя или четырьмя, являются достаточными аргументами, чтобы потратить дополнительное время на то, чтобы .vue
файлы работали с TypeScript.
Почему именно TypeScript?
Это то, к чему вы должны прийти самостоятельно, если вообще когда-либо. Раньше люди использовали нетипизированный JavaScript, и он действительно работает. Фактически, я пытался выбрать между TypeScript и LiveScript, который представляет собой нетипизированную функционально приправленную версию CoffeeScript с кратким и несколько странным синтаксисом.
В конце концов, все сводится к производительности. LiveScript предоставляет менее подробный синтаксис и ярлыки для многих вещей, которые я использую изо дня в день. TypeScript улавливает многие ошибки в коде, которые я могу допустить, и может предоставить дополнительную информацию о коде, которая значительно упрощает работу с незнакомыми библиотеками и фреймворками. Я предпочел последнее первому из произвольных соображений интуиции.
Если вам нужно наглядно показать, каково использовать TypeScript в производстве, есть отличная статья от команды Slack.
Хватит говорить, давайте код… а может, и нет
Прежде чем мы сможем кодировать, нам нужно настроить инструменты.
Сначала подберем webpack-блоки. Это самый простой способ настроить webpack, о котором я знаю. Что ж, проще всего после простого копирования и вставки существующей конфигурации, но вы меня поняли.
Теперь сразу же webpack-block не поддерживает .vue
файлы. Есть два сторонних пакета, которые позволяют использовать .vue
файлы.
Встроенная конфигурация TypeScript в блоках webpack использует awesome-typescript-loader. Это хороший загрузчик, но он не хорошо работает с .vue
файлами. (У него тоже странное имя, но это моя проблема.) В дополнение к пакету для настройки vue-loader
нам также нужен пакет, который будет настраивать ts-loader
, который имеет некоторые положения для работы с форматами контейнеров, такими как .vue
.
npm i -D webpack-blocks-vue webpack-blocks-ts
В итоге вы получаете что-то вроде этого webpack.config.js
файла. Важные моменты, на которые следует обратить внимание:
- Мы передаем параметр
{ appendTsSuffixTo: [/\.vue$/] }
в ts-loader, потому что в противном случае компилятор TypeScript не хочет сотрудничать. Это приводит к тому, что.vue
файлы обрабатываются как.vue.ts
, именно так, как они нравятся компилятору TypeScript. - Мы не используем Babel. Если вы хотите использовать JSX, возможно, вы захотите его использовать, но я этого не сделаю.
- Мы передаем
{ esModule: true }
в vue-loader. Эта опция указывает загрузчику испускать модули ES2015 вместо модулей CommonJS. Судя по всему, TypeScript не любит модули CommonJS.
Вам также необходимо сообщить TypeScript, что такое .vue
файлы и как с ними работать. Для этого добавляем в дерево исходных текстов vue.d.ts
файл. Это определение сообщает TypeScript, каким будет тип экспорта по умолчанию из файла .vue.
Можем ли мы сейчас кодировать?
Да мы можем. Как я уже упоминал во введении, нельзя просто писать код, как раньше, и ожидать, что все заработает. Кодирование .vue
файлов для TypeScript требует другого подхода. Но не бойтесь. Альтернативный синтаксис имеет большой смысл и, на мой взгляд, делает код более читаемым (не говоря уже о хороших качествах проверки типов).
Сначала вам нужно добавить дополнительную зависимость: vue-property-decorator.
Тогда ваш компонент будет выглядеть примерно так:
<template> <div class="hello">Hello, {{ name }}</div> </template> <script lang="ts"> import Vue from 'vue' import { Component, Prop } from 'vue-property-decorator' @Component export default class Hello extends Vue { @Prop name: string } </script> <style scoped> .hello { font-size: 200px; font-family: sans-serif; } </style>
Я не буду вдаваться в подробности здесь, потому что и vue-property-decorator, и vue-class-component, на котором он основан, довольно хорошо документированы и просты в использовании.
Главное, на что следует обратить внимание, это то, что этот стиль удаляет большую часть магии / шаблона (или, по крайней мере, скрывает его). Вместо того, чтобы определять наблюдателей и методы во вложенных объектах, а затем использовать this
для обозначения внешнего объекта (который по праву запускает проверку типов TypeScript), все методы определены для объекта, с которым привязан this
. Это делает все немного проще для понимания и следования, делает вещи немного ближе к тому, как обычно работает JavaScript.
Вы найдете полный пример в моем репозитории vue-ts-sandbox.
В качестве примечания: даже если вас не волнует TypeScript, вы можете использовать эти декораторы с Babel.
Стоит ли оно того?
Как видите, заставить его работать очень сложно. Даже сейчас, оглядываясь назад, с преимуществом документированных накопленных знаний, все еще требуется время, чтобы все наладить. Тогда вопрос в том, стоит ли оно того.
Как я уже сказал в разделе Почему именно TypeScript, вы должны достичь этого самостоятельно.
Я считаю, что все хлопоты, связанные с аннотациями типов и конфигурацией сборки, того стоят, когда средство проверки типов сообщает вам, что вы передали неправильный аргумент, или забыли присвоить что-то свойству, или что тип возвращаемого значения какой-либо функции не является то, что вы думали, это будет. Вы уловили идею. Необходимость явного объявления интерфейсов также помогает мне немного лучше понять кодовую базу и замедляет меня ровно настолько, чтобы избежать поспешных ошибок.
Прямо сейчас для этого требуются дополнительные усилия, но подумайте об этом: модульное тестирование требует немного дополнительных усилий (гораздо больше, чем это!), И никто не будет спорить, что модульное тестирование того не стоит. В том же духе это просто еще один уровень, который способствует качеству кода. Во всяком случае, я так на это смотрю.