Эта статья впервые появилась на blog.rangle.io.

Vue.js — это универсальный и доступный фреймворк для создания современных приложений JavaScript. Вы можете начать с простого добавления тега script с помощью ванильного JS. Или вы можете пойти ва-банк и создать современное приложение JavaScript со всеми настройками, используя систему сборки, такую ​​как Webpack. Однако последнее требует определенных знаний о конфигурации, поэтому оно не совсем соответствует мантре легкодоступности, особенно для людей, которые только начинают изучать мир современных приложений JavaScript.

В этой статье мы собираемся исследовать новую тенденцию систем сборки JavaScript с нулевой конфигурацией (она же #0CJS) в экосистеме Vue.

Приложение Vue

Чтобы начать это путешествие, мы собираемся создать чрезвычайно простое приложение Vue. Затем мы увидим, как эта же структура будет работать под разными сборщиками. Поскольку мы изучаем системы сборки с нулевой конфигурацией, мы сосредоточимся на использовании канонического подхода Vue Single-File Components (SFC).

# Make a new directory for our sample app
mkdir /path/to/vue-app
cd /path/to/vue-app

# Initialize a package.json
yarn init -y

# Add the vue npm package dependency
yarn add vue

Начнем с создания App.vue корневого компонента (по соглашению) для нашего приложения.

// src/App.vue
<template>
  <h1>{{ title }}</h1>
</template>

<script>
import Vue from 'vue'

export default {
  name: 'app',
  data() {
    return { title: 'Hello Vue!' }
  },
}
</script>

Затем мы добавляем типичную точку входа для начальной загрузки приложения Vue.

// src/index.js
import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App),
});

Наконец, давайте создадим файл index.html, чтобы мы могли увидеть, как работает наше приложение Vue.

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hello Vue!</title>
</head>
<body>
  <div id="app"></div>
  <script src="./src/index.js"></script>
</body>
</html>

На данный момент у нас есть оболочка нашего простого приложения Vue. Давайте посмотрим на приложение, используя простой локальный веб-сервер.

# yarn global add lite-server
#  - or use equivalent (e.g. `serve`, etc.)
lite-server

Если вы проверите свой браузер, вы ничего не увидите, но консоль JavaScript покажет такую ​​ошибку:

# In Chrome
Uncaught SyntaxError: Unexpected identifier ()

# In Firefox
SyntaxError: import declarations may only appear at top level of a module

Вы, наверное, уже догадались, что это потому, что мы пытаемся запустить приложение Vue без установленной системы сборки. Одна из приятных особенностей Vue заключается в том, что вы могли бы так же легко создать эквивалентное приложение, используя Vue CDN и vanilla JS. Однако эта статья посвящена использованию однофайловых компонентов Vue (SFC), для которых требуется какой-либо инструмент сборки или объединения.

Итак, вопрос в том, как заставить это работать? Ответ в том, что есть несколько способов с разными инструментами (с которыми вы, возможно, уже знакомы). Именно здесь вам обычно нужно потратить дополнительное время и усилия, чтобы привести вещи в состояние, в котором вы действительно можете запустить свое приложение. Стоит ли затрачивать такое простое приложение? Может есть более простой способ?

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

Vue с Webpack

Экосистема Vue включает в себя независимые инструменты. Это означает, что его можно легко использовать с большинством сборщиков и систем сборки (или вообще без них). Тем не менее, канонический способ создания приложений Vue — это использование Webpack. В настоящее время Webpack, вероятно, является самым популярным инструментом для создания современных приложений JavaScript. Тем не менее, одна из распространенных жалоб заключается в том, что это может быть похоже на выбор собственного приключения, чтобы все настроить.

Подключаемый модуль Webpack vue-loader отвечает за волшебство однофайловых компонентов Vue (SFC) в Webpack.

Недавно был выпущен Webpack 4 с первоначальной поддержкой сборок с нулевой конфигурацией. Давайте рассмотрим, что нужно для того, чтобы наше простое приложение Vue работало с Webpack.

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

# Install webpack dev dependencies
yarn add -D webpack webpack-cli webpack-dev-server

# Install webpack vue plugins
yarn add -D vue-loader vue-template-compiler

Теперь добавьте несколько npm скриптов, чтобы упростить выполнение команд Webpack. Webpack 4 добавляет опцию --mode, которая включает поведение по умолчанию как для разработки, так и для производственной сборки.

{
  "..."
  "scripts": {
    "start": "webpack-dev-server --mode development --open",
    "build:dev": "webpack --mode development",
    "build:prod": "webpack --mode production"
  }
  "..."
}

В этот момент, если вы попытаетесь запустить yarn start, вы увидите следующую ошибку:

ERROR in ./src/App.vue
Module parse failed: Unexpected token

Это потому, что Webpack еще не знает, как обрабатывать файлы .vue. Для этого нам действительно нужно нарушить наш завет нулевой конфигурации и добавить файл webpack.config.js и зарегистрировать плагин vue-loader для обработки файлов .vue.

Давайте продолжим и сделаем это сейчас. Пока мы этим занимаемся, давайте также настроим популярный html-webpack-plugin для автоматической вставки встроенного тега скрипта JavaScript для нас.

// webpack.config.js
const HtmlWebPackPlugin = require('html-webpack-plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
      }
    ],
  },
  plugins: [
    new HtmlWebPackPlugin({
      template: './index.html',
      filename: 'index.html',
    }),
  ]
}

Наконец, мы удаляем тег script в нашем шаблоне index.html и используем тег html-webpack-plugin.

<!-- index.html -->
<html>
<body>
  <div id="app"></div>
  <!-- Remove or comment out script since built files will be auto injected -->
  <!-- <script src="./src/index.js"></script> -->
</body>
</html>

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

yarn start

Здорово! Давайте добавим немного style в наше приложение, инвертировав цвета фона и переднего плана.

// src/App.vue
<template>...</template>
<script>...</script>

<style>
html {
  background: black;
  color: white;
}
</style>

Если вы наблюдаете за своей командной оболочкой, вы, вероятно, заметили, что Webpack завершился со следующей ошибкой:

ERROR in ./src/App.vue
Module not found: Error: Can't resolve 'css-loader'

Мы начинаем видеть, что текущее состояние нулевой конфигурации в Webpack не так уж и #0CJS. Чтобы исправить это, нам нужно добавить css-loader в качестве зависимости от разработчиков и настроить ее в файле webpack.config.js. То же самое применимо, если мы хотим использовать SCSS, TypeScript или различные другие загрузчики и плагины Webpack. В этом нет ничего особенного по сравнению с предыдущей настройкой Webpack, но в настоящее время это не совсем та мечта с нулевой конфигурацией, на которую мы надеялись.

Хорошей новостью является то, что команда Webpack указала, что их подход заключается в том, чтобы позволить «другим расширять», а не встраивать все это в ядро. В настоящее время они работают над завершением дизайна своих новых пресетов, что должно позволить сообществу расширить #OCJS дальше. Со временем я подозреваю, что настоящая нулевая конфигурация с Webpack станет реальностью (или приблизится к ней).

Vue с посылкой

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

Обновление: только что выпущена версия Parcel v1.7, которая включает встроенную поддержку Vue. Я быстро пробежался по новому релизу, и, похоже, он снял некоторые опасения, которые у меня возникли из-за следующей настройки. Он больше похож на серьезного соперника в среде с нулевой конфигурацией.

Parcel — относительно новый альтернативный сборщик, целью которого является упрощение создания веб-приложений. Parcel работает, читая файл точки входа (например, index.html), а затем преобразовывая и объединяя весь необходимый HTML и различные типы ресурсов в каталог dist. Он также имеет встроенную поддержку общих типов активов и преобразователей, таких как SCSS, Babel, TypeScript и PostCSS. Кроме того, он включает в себя удобные функции разработки, такие как перезагрузка в реальном времени, горячая замена модуля (HMR) и разделение кода.

Ничего себе, может ли это быть чистым блаженством нулевой конфигурации? Давайте посмотрим, преобразовав наше приложение Vue из Webpack в посылку.

Поскольку поддержка Vue для ядра Parcel все еще находится в стадии разработки, мы будем использовать неофициальный плагин parcel-plugin-vue (например, vue-loader для Webpack).

# Install parcel, vue plugin, and required babel dependencies
yarn add -D parcel-bundler parcel-plugin-vue babel-plugin-module-resolver babel-plugin-transform-runtime babel-preset-es2015

# Add the parcel bundler as a global command (note: you could also use the dev dependency and create an npm script)
yarn gobal add parcel-bundler

Обязательно ознакомьтесь с документацией для этого плагина, так как могут быть некоторые дополнительные настройки и неподдерживаемые функции, на которые следует обратить внимание (в настоящее время).

В настоящее время открыт запрос функции на добавление встроенной поддержки Vue в Parcel, что сделает плагин parcel-plugin-vue устаревшим и еще больше упростит этот подход.

После того, как мы установили наши зависимости, нам нужно снова обновить наш файл index.html. На этот раз мы добавим тег script, который мы удалили для Webpack. Однако в этом случае вместе с плагином parcel-plugin-vue у нас не будет никакой дополнительной настройки (т.е. webpack.config.js). Это связано с тем, что Parcel проанализирует индексный файл, установит все необходимые дополнительные зависимости для разработчиков и соберет все для нас в каталог dist.

<!-- index.html -->
<html>
<body>
  <div id="app"></div>
  <!-- Parcel will use this to build your app -->
  <script src="./src/index.js"></script>
</body>
</html>

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

parcel index.html --open

Как видите, это было чрезвычайно просто по сравнению с подходом Webpack. Мы также получили некоторые дополнительные функции, такие как хешированные имена файлов для очистки кеша. На этом этапе мы также можем добавить файл SCSS и ссылку на него в файле индекса, чтобы автоматически получить поддержку SASS (среди других типов активов). Parcel позаботится о том, чтобы выяснить, на чем основано ваше намерение, исходя из типов активов и общих соглашений!

Однако… есть вероятность, что если вы начнете расширять это приложение Vue (как это сделали бы вы), вы можете столкнуться с некоторыми раздражающими проблемами на этом пути. Parcel довольно удобен, но полезная в настоящее время библиотека parcel-plugin-vue — скорее временная мера, пока в Parcel не будет добавлена ​​нативная поддержка Vue. Это работает, когда вы остаетесь в рамках поддерживаемого набора функций, но будьте осторожны, если вы немного отклонитесь от пути.

Исходя из этого, я бы не стал рекомендовать этот путь для чего-либо, кроме простого игрушечного приложения, подобного этому. Однако, когда Parcel наконец-то получил встроенную поддержку Vue, я увидел, что это жизнеспособный вариант для очень быстрого создания приложений Vue. Потенциал нулевой конфигурации не за горами, и здоровая конкуренция с Webpack всегда (или, по крайней мере, вероятно) хороша.

Команда Vue работает над vue-component-compiler, который представляет собой независимый от сборщиков API для централизации основной логики обработки для однофайловых компонентов Vue. Это должно улучшить поддержку различных инструментов объединения (Webpack, Parcel, Rollup и т. д.).

Эй, а как насчет…?

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

До сих пор у нас было только наше простое приложение Vue, связанное и работающее в браузере. На самом деле это только часть того, что составляет типичное современное приложение JavaScript. В большинстве проектов также используются linters, unit tests, e2e tests, code coverage и т. д. Все эти важные вещи требуют дополнительных зависимостей, настройки и настройки.

Оба продемонстрированных подхода Webpack и Parcel потребуют дополнительной настройки для добавления поддержки этих дополнительных вещей. Здесь мы вступаем в область другой тенденции фреймворка — интерфейса командной строки (CLI). Идея этих удобных инструментов состоит в том, чтобы быть чем-то вроде командного центра для вашего приложения JavaScript. Единое объединяющее место для создания и запуска ваших приложений — подход с включенными батареями.

Одним из пионеров в этой области стал Ember CLI. Теперь у большинства интерфейсных фреймворков есть какой-то CLI, помогающий разработчикам быстро начать работу в своем фреймворке (например, create-react-app, @angular/cli и т. д.).

Интерфейс командной строки Vue

Vue CLI (наряду с другими) помогает устранить накладные расходы и усилия, связанные с настройкой современного приложения JavaScript. Это делается путем создания всех необходимых файлов, чтобы получить каркас приложения со всеми прибамбасами. Тем не менее, как правило, у вас остаются различные файлы конфигурации, которые нужно поддерживать и обновлять вместе с приложением.

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

Vue CLI v3 (в настоящее время находится в стадии бета-тестирования) обеспечивает официальную нулевую конфигурацию Vue. Часть обоснования заключается в том, чтобы упростить обновление приложений, созданных с помощью CLI. Другой, я подозреваю, состоит в том, чтобы еще раз подчеркнуть и без того доступный характер Vue. Давайте протестируем новый интерфейс командной строки и посмотрим, что он может предложить в нашем стремлении к нулевой конфигурации.

# Install vue-cli v3+ globally
yarn global add @vue/cli

# Create a new project (prompts for preset options)
# For this article we chose the default settings
vue create /path/to/vue-cli-project

# Now open the project
cd /path/to/vue-cli-project

В итоге получаем структуру ниже. Если вы присмотритесь, вы увидите очень мало файлов конфигурации. Отчасти это связано с тем, что мы решили хранить общие файлы конфигурации (.babelrc, .eslintrc, .postcss.json и т. д.) в файле package.json.

Обратите внимание, что нигде нет Webpack файлов конфигурации. Это связано с тем, что интерфейс командной строки абстрагирует от разработчика все сложности многофункциональной конфигурации Webpack. На самом деле это ничем не отличается от других CLI. Вы можете спорить за или против этого подхода, но факт в том, что это нулевая конфигурация.

├── package.json
├── public
│   ├── favicon.ico
│   └── index.html
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   │   └── HelloWorld.vue
│   └── main.js
└── yarn.lock

«Подождите минутку», — говорите вы, тестов нет. Да, это правда. В данном случае это было намеренно. Я хотел показать, как вы можете легко добавить их впоследствии. Для этого выполните следующие команды:

# Add mocha/chai for unit tests (note: you can also use Jest if you like)
vue add @vue/cli-plugin-unit-mocha

# Add cypress for e2e tests
@vue/cli-plugin-e2e-cypress

Это добавляет соответствующие зависимости и вызывает их соответствующие генераторы для добавления сценариев npm в файл package.json и формирования шаблонов соответствующих файлов в новом каталоге tests.

├── tests
│   ├── e2e
│   │   ├── plugins
│   │   │   └── index.js
│   │   ├── specs
│   │   │   └── test.js
│   │   └── support
│   │       ├── commands.js
│   │       └── index.js
│   └── unit
│       └── HelloWorld.spec.js

Вы можете сделать то же самое для многих других доступных предустановленных параметров. Теперь у нас есть npm скриптов в package.json для управления многими базовыми задачами, необходимыми для разработки.

{
  "..."
  "scripts": {
    "serve": "vue-cli-service serve --open",
    "build": "vue-cli-service build",
    "test": "vue-cli-service test",
    "e2e": "vue-cli-service e2e",
    "lint": "vue-cli-service lint",
    "e2e:open": "vue-cli-service e2e:open"
  },
  "..."
}

Проект Vue CLI также можно дополнительно настроить с помощью специального файла vue.config.js. Например, добавление произвольных подключаемых модулей Webpack поверх базовой настройки CLI позволяет избежать использования eject только для получения доступа к нестандартным функциям. Эта гибкость в настоящее время невозможна с некоторыми другими доступными интерфейсами командной строки фреймворка.

Команда vue inspect позволяет просмотреть базовую конфигурацию веб-пакета. Если вам когда-нибудь понадобится eject, вы можете просто запустить vue inspect > webpack.config.js.

Что еще поддерживает новый Vue CLI? Оказывается, они много думали о том, чего хотят разработчики. Вот краткий список того, что включено:

  • PostCSS, Autoprefixer и CSS Modules (по умолчанию)
  • Поддержка TypeScript и компонентов Class-Style
  • Поддержка прогрессивных веб-приложений (PWA)
  • Поддержка переменных среды с файлами .env (dotenv)
  • Поддержка прокси для HTTP-сервера
  • Расширение и поддержка плагинов через @vue/cli-service
  • Настройка с использованием файла vue.config.js

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

Вывод

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

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

Первоначально опубликовано на blog.rangle.io.