Vue структура проекта: Как структурировать крупномасштабное приложение Vue.js / Хабр

Содержание

Как структурировать крупномасштабное приложение Vue.js / Хабр

Как лучше всего структурировать приложение Vue.js, чтобы оно масштабировалось и оставалось обслуживаемым и расширяемым по мере его роста? Этот вопрос я слышал неоднократно, и думаю, что один из ответов на него кроется в принципе предсказуемости. Когда речь идет о создании масштабируемого проекта, вы хотите, чтобы все в нем было максимально предсказуемо.

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

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

Возможно, вы даже имели дело с кодовой базой в течение некоторого времени и возникала та же мысль! Предсказуемая кодовая база максимально облегчает этот опыт, делая знакомство разработчиков с проектами более простым, а продолжение работы — более эффективным.

Стоит отметить, что, хотя предсказуемость возможна, ни один проект никогда не станет предсказуемым на 100%. Каждый проект, новый или существующий, имеет хотя бы небольшую кривую обучения. Также следует знать, что предсказуемость не означает, что кодовая база или приложение будут быстро понятны в целом. Многие крупномасштабные приложения просто слишком сложны, чтобы это было возможно, и потребуется время, чтобы понять их целиком. Таким образом, предсказуемость — это не видение полной законченной картины, а скорее понимание структуры определенного фрагмента и возможность быстро понять, куда он встраивается. На самом деле, специфика хорошей кодовой базы такова, что ее можно понять по частям, и она не должна требовать от разработчиков необходимости думать обо всем сразу.

Как же добиться предсказуемости в кодовой базе? Ответ: стандарты, простые и понятные. Возможно, это не тот ответ, который вы ищете, но это правда. Лучший способ сделать что-либо предсказуемым — это следовать набору стандартов. Например, я могу почти со 100% уверенностью предсказать, что новые полноразмерные простыни, которые я купил только сегодня, подойдут к моей кровати, даже если я никогда раньше не заправлял ее ими. Почему? Потому что существует стандартная система определения размеров постельного белья.

Стандарты предсказуемости для сообщества

В связи с этим возникает вопрос, какие стандарты есть для сообщества Vue.js в целом? Я бы сказал, что существуют 4 источника.

  1. Стайлгайд Vue.js

  2. Временные платформы, сгенерированные Vue CLI

  3. Официальные библиотеки Vue.js (находятся в разделе Ecosystem > Official Projects на сайте Vue.js)

  4. и более свободные, наиболее популярные компонентные фреймворки, такие как Vuetify или Quasar.

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

Официальные библиотеки и библиотеки компонентов

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

Библиотека Vuex фактически признает и рекламирует этот факт как главную особенность, называя себя «паттерн управления состоянием + библиотека».

Это может показаться очевидным, однако в этом есть смысл. Если в Vue.js существует популярное или рекомендуемое решение проблемы (и тем более, если это официальное решение), я бы крепко задумался, прежде чем использовать что-то другое. Мне, как и любому человеку, нравится создавать свои собственные компоненты, хранилища и т.д., но часто в долгосрочной перспективе действительно целесообразно использовать проверенные и верные решения не только из-за функциональности, тестового обеспечения и документации, которые они предлагают, но и из-за стандартизации, которую они привносят. (И разве в мире JavaScript мы все не можем применить немного больше стандартизации?).

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

Основы стандартной файловой структуры

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

Большинство из нас, вероятно, знакомы с данной структурой, и это здорово! Значит, мы на шаг ближе к предсказуемости! Итак, суть заключается в том, что не стоит слишком задумываться об этом. Придерживайтесь того, что Vue дает вам из коробки, и не отклоняйтесь, пока у вас не будет действительно веской причины.

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

Рекомендуемые правила для компонентов

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

  • По возможности каждый компонент должен быть определен в собственном выделенном файле (SFC).

  • Однофайловые компоненты должны быть оформлены в формате PascalCase

  • Все базовые компоненты должны начинаться с одного и того же префикса (например, Base или App).

    • Вы можете рассматривать базовые компоненты как общие для всего приложения многократно используемые компоненты, например, кнопки или модалы.

    • Это группирует их вместе и заявляет об их глобальном, многоразовом характере.

  • Названия компонентов всегда должны быть многословными, чтобы не конфликтовать с существующими или будущими элементами HTML. Не создавайте компонент Table или Button.

  • Компоненты одного экземпляра должны начинаться с префикса The.

  • Тесно связанные дочерние компоненты должны иметь префикс с именем родительского компонента.

  • Например, TodoListItem в TodoList.

  • Имена компонентов должны начинаться со слов самого верхнего уровня (обычно общего) и заканчиваться самыми конкретными.

  • Например, SearchWidgetInput, SearchWidgetResultsList, SearchWidget

Потерпите, если это не совсем понятно, через минуту появится изображение, которое поможет вам.

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

Некоторые рекомендуемые личные/командные стандарты предсказуемости

Несмотря на то, что существует несколько отличных стандартов, установленных официальными источниками для сообщества Vue. js в целом, есть и другие паттерны, не столь широко принятые, которые, по моему опыту, могут быть столь же полезны и стать стандартами для вас или проектов вашей команды. Они необходимы, поскольку общепринятые стандарты сообщества не могут быть на 100% всеобъемлющими, но будьте осмотрительны и внимательны к тому, как принимаются и поддерживаются стандарты команды… это может быть проблемой из-за постоянно меняющихся правил, если вы не будете осторожны. Итак, вот некоторые из моих рекомендаций для стандартов вашего проекта Vue.js.

Каталог одноуровневых компонентов

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

  • Быстро и легко перейти от поиска компонента в Vue devtools к поиску файла в кодовой базе (имя файла и имя компонента совпадают).

  • Используйте функцию быстрого поиска или перехода по файлам в вашей IDE для фильтрации файлов на основе их наиболее общих атрибутов вплоть до более конкретных

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

  • Возможность видеть все компоненты сразу в одном списке

  • Избавиться от избыточности ключевых слов в именах файлов и в каталоге (это если вы следуете рекомендациям стайлгайда (а так и должно быть) и используете вложенные каталоги) (т.е. post/PostList.vue, post/PostFeature.vue и т.д.)

  • Избавьтесь от соблазна использовать короткие имена компонентов из одного слова, что проще сделать с вложенными каталогами (т.е. post/List.vue, post/Feature.vue ) и нарушает рекомендации стайлгайда.

  • Исключить перемещение по файловой структуре в каталогах и обратно в поисках компонента

  • Упростить импорт компонентов (всегда будет import SomeComponent из «@/SomeComponent»).

Как же выглядит плоская структура, которая следует стайлгайду? Вот хороший пример.

Хотя ваше крупномасштабное приложение будет иметь гораздо больше файлов, каждый из них — это просто еще одно имя компонента в одном хорошо организованном списке, поэтому, несмотря на то, что объем файловой структуры может расширяться, сложность не увеличивается.

Стандартизированное соглашение об именовании маршрутов/страниц

Еще одна методика — это стандартизированный способ именования маршрутов и компонентов страниц. В типичном CRUD-приложении у вас есть следующие различные страницы для каждого ресурса:

  1. список всех ресурсов

  2. представление отдельного ресурса

  3. форма для создания ресурса

  4. и форма для редактирования ресурса.

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

Поскольку у меня уже есть опыт работы с PHP-фреймворком Laravel, при определении имен маршрутов и их путей предсказуемым образом я интуитивно опирался на стандарты, которые были заложены в Laravel. Это облегчило моей команде, обладающей опытом работы с Laravel, более быструю и привычную работу с Vue. Используя в качестве примера ресурс «пользователь», я рекомендую следующее соглашение об именовании, предписанное Laravel и адаптированное для Vue:

Path

Route and Component Name

What it Does

/users

UsersIndex

List all the users

/users/create

UsersCreate

Form to create the user

/users/{id}

UsersShow

Display the users details

/users/{id}/edit

UsersEdit

Form to edit the user

Несмотря на соблазн назвать маршрут в более традиционном для Laravel стиле, например users. index вместо UsersIndex, я заметил, что использование стиля PascalCase работает так же хорошо и имеет дополнительное преимущество в виде соответствия имени компонента.

Для большей согласованности и гибкости необходимо всегда ссылаться на маршруты по их имени при использовании их в ссылках маршрутизатора и при программном обращении к ним. Например

<router-link :to="{name: 'UsersIndex'}">Users</router-link>

Также стоит отметить, что не все маршруты будут точно соответствовать этому шаблону, поскольку некоторые из них будут более «CRUDdy», чем другие. Для таких случаев я рекомендую продолжать использовать PascalCase в названии для обеспечения согласованности.

Более комплексная файловая структура

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

Здесь добавлены такие каталоги, как docs, helpers, layouts, mixins и plugins. Заметьте, что 4 из 5 имеют причудливую иконку Material Icon Theme рядом с ними, предоставленную расширением VS Code . Это потому, что в определенное время, для некоторых фреймворков или языков, эти соглашения о каталогах были достаточно распространены, чтобы получить свой собственный значок от разработчика расширения. Это не случайность!

Я также добавил один файл globals.js.

Итак, что стоит за этими стандартами файловой структуры? Очень рад, что вы спросили!

docs

Назначение этого файла очевидно, но важнее то, что он уже включен и при каждом открытии кодовой базы сразу предстает перед взором вашей команды. Более вероятно, что определенные аспекты проекта будут задокументированы, если разработчику никогда не придется покидать свою IDE. Я также обнаружил (и это было приятной неожиданностью), что написание документации сначала, прежде чем приступить к кодированию многократно используемого класса или компонента, обычно помогает мне лучше спроектировать интерфейс или API этого кода. Дерзайте, попробуйте!

Кроме того, помимо каталога docs, я обнаружил, что полезно помещать README.md в корень каждого стандартизированного каталога, объясняя назначение каталога и любые правила для того, что должно быть в него включено. Это особенно полезно для тех стандартов, которые не являются общими для всего сообщества.

helpers

Это общая директория во многих фреймворках для базовых функций ввода-вывода, которые можно использовать многократно в рамках всего проекта. Их обычно легко тестировать и, как правило, они используются не один раз. Мне нравится начинать с одного файла index.js, а затем, по мере роста числа хелперов, разбивать их на более сгруппированные файлы, такие как https.js, cache.js, time.js и т. д. Все в этом каталоге можно просто импортировать и использовать по требованию, а если какая-то функция в итоге вообще не будет использоваться, ее можно легко вытряхнуть из производственного пакета.

layouts

Я позаимствовал это соглашение из Nuxt, а также из Laravel. Это может быть удобно для определения не только компонентов страницы, но и компонентов макета, которые могут быть повторно использованы на нескольких страницах. Вместо того чтобы определять содержимое страницы, как следует из названия, эти компоненты определяют общий макет. Например, будет ли эта страница одноколоночной или двухколоночной? Имеет ли она левую или правую боковую панель? Включает ли макет типичные верхний и нижний колонтитулы или он совершенно пустой, возможно, с абсолютно центрированным содержимым страницы? Обычно существует всего 2 или 3 таких компонента макета, но, тем не менее, они могут быть удобной абстракцией.

mixins

Этот каталог предназначен для организации всех ваших Vue.js миксинов. Я думаю, важно по-прежнему добавлять слово Mixin в конец имени каждого файла (например, ResourceTableMixin.js) для удобства поиска в переключателе файлов. Хотя у меня еще не было возможности поработать над более масштабным проектом Vue 3, я предполагаю, что это быстро изменится на каталог composables в пользу извлечения реактивных данных/методов с помощью Composition API, а не с помощью миксинов. Или, по крайней мере, каталог composables может быть добавлен в мою стандартную файловую структуру в дополнение к каталогу mixins.

plugins

Последний каталог, который я люблю включать во все свои проекты Vue, — это plugins. В мире пакетов и библиотек мы иногда делаем больше настроек и регистрации, чем собственно кодирования. Именно для этого и предназначен этот каталог, включающий и настраивающий все сторонние материалы Vue. Хотя они называются плагинами, я не всегда использую этот термин в буквальном смысле. Другими словами, это не обязательно должна быть сторонняя библиотека, зарегистрированная через метод Vue .use(). В большинстве случаев это так, но иногда используются альтернативные методы установки библиотеки в Vue (например, .component()). Для библиотек, настройка которых занимает одну или две строки, можно использовать файл plugins/index.js. Что касается более сложной настройки, то для них я предпочитаю создать отдельный файл в каталоге plugins, а затем импортировать его в plugins/index. js.

globals.js

Это единственный стандартный файл, который я действительно когда-либо добавляю. Его цель — внести ограниченное количество глобальных переменных в приложение Vue а для SPA, которые являются только клиентской стороной, обычно это окно.

Вот комментарий, который обычно располагается в верхней части этого файла.

/**
 * Use this file to register any variables or functions that should be available globally
 * ideally you should make it available via the window object
 * as well as the Vue prototype for access throughout the app
 * (register globals with care, only when it makes since to be accessible app wide)
 */

В Vue 2 это можно было сделать таким образом:

Vue.prototype.$http = () => {}

В Vue 3 это выглядит следующим образом:

const app = createApp({})
app.config.globalProperties.$http = () => {}

Хотя меня постоянно предупреждали об опасности глобальных переменных, однажды я прочитал, что «небольшое количество глобальных переменных» — это очень удобная вещь, и с тех пор она мне уже не раз пригодилась. Благодаря этому файлу я легко узнаю, какие это глобальные переменные, и мне не нужно будет долго думать, когда захочется добавить новые.

Резюме по теме предсказуемости

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

Безусловно, стандарты предсказуемости — это большое преимущество для ваших крупномасштабных приложений Vue.js, но можно сделать еще больше. Обязательно ознакомьтесь со следующей статьей из этого цикла, в которой мы рассмотрим инструменты линтинга и форматирования, такие как ESLint и Prettier, чтобы ваш код был чистым, без ошибок и последовательным.


Материал подготовлен в рамках курса «Vue.js разработчик». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

Структура исходного кода | Vue.js

Избегайте синглтонов с состоянием

При написании кода только для клиентской стороны можно быстро привыкнуть, что каждый раз код выполняется в новом контексте. Но сервер Node.js — длительный процесс. Поэтому после того как код впервые импортируется процессом и будет выполнен один раз, он затем останется в памяти. Это значит, если создать объект синглтон, то он станет использоваться для всех входящих запросов, что чревато загрязнением состояния при перекрёстных запросах.

// НЕПРАВИЛЬНО
import app from './app.js'
server.get('*', async (req, res) => {
  // приложение стало общим для всех пользователей
  const result = await renderToString(app)
  // . ..
})

1
2
3
4
5
6
7
8

// ХОРОШО
function createApp() {
  return createSSRApp(/* ... */)
}
server.get('*', async (req, res) => {
  // каждый пользователь получит свой экземпляр приложения
  const app = createApp()
  const result = await renderToString(app)
  // ...
})

1
2
3
4
5
6
7
8
9
10
11

Поэтому требуется для каждого запроса создавать новый корневой экземпляр Vue. Чтобы сделать это, нужно написать функцию-фабрику, которая сможет многократно выполняться и создавать свежие экземпляры приложения для каждого запроса:

// server.js
const { createSSRApp } = require('vue')
const { renderToString } = require('@vue/server-renderer')
const express = require('express')
const server = express()
function createApp() {
  return createSSRApp({
    data() {
      return {
        user: 'Василий Пупкин'
      }
    },
    template: `<div>Текущий пользователь: {{ user }}</div>`
  })
}
server. get('*', async (req, res) => {
  const app = createApp()
  const appContent = await renderToString(app)
  const html = `
  <html>
    <body>
      <h2>Мой первый заголовок</h2>
      <div>${appContent}</div>
    </body>
  </html>
  `
  res.end(html)
})
server.listen(8080)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

Это правило применяется также и к экземплярам роутера (router) или хранилища (store). Вместо того, чтобы непосредственно экспортировать их из модуля и импортировать в приложении, теперь нужно создавать новый экземпляр в createApp и внедрять его из корневого экземпляра Vue каждый раз при получении нового запроса.

Добавление шага сборки

До сих пор, ещё не обсуждали каким образом доставлять клиенту такое приложение Vue. Чтобы сделать это, потребуется собрать приложение с использованием webpack.

  • Требуется обработать серверный код с помощью webpack. Например, файлы .vue нужно обработать с помощью vue-loader, а многие специфические для webpack функции, такие как импорт файлов через file-loader или импорт CSS через css-loader, не будут работать напрямую в Node.js.

  • Аналогично, нужна отдельная сборка для клиентской стороны, несмотря на то, что последняя версия Node.js полностью поддерживает возможности ES2015, для старых браузеров необходимо транспилировать код.

Основная идея в том, что webpack будет использоваться для сборки приложения как для клиента, так и для сервера. Серверная сборка будет выполняться на сервере для отрисовки статического HTML, а клиентская сборка будет отправляться в браузер для гидратации получаемой статической разметки.

Подробнее обсудим в следующих разделах — а сейчас представим, что уже разобрались с настройкой сборки и можем писать код приложения Vue с использованием webpack.

Структура кода с webpack

Используя webpack для сборки приложения как для сервера, так и для клиента, большая часть исходного кода может быть написана универсально, используя все возможности webpack. В то же время есть ряд вещей, о которых следует помнить при написании универсального кода.

Простой проект может выглядеть так:

src
├── components
│   ├── MyUser.vue
│   └── MyTable.vue
├── App.vue # корень приложения
├── entry-client.js # запускается только в браузере
└── entry-server.js # запускается только на сервере

1
2
3
4
5
6
7

App.vue

Как можно заметить, теперь есть файл App.vue в корне каталога src. Именно там будет храниться корневой компонент приложения. Теперь можно смело переносить код приложения из файла server.js в файл App.vue:

<template>
  <div>Текущий пользователь: {{ user }}</div>
</template>
<script>
export default {
  name: 'App',
  data() {
    return {
      user: 'Василий Пупкин'
    }
  }
}
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14

entry-client. js

Клиентская точка входа создаёт приложение, используя компонент App.vue, и монтирует его в DOM:

import { createSSRApp } from 'vue'
import App from './App.vue'
// логика инициализации, специфичная для клиента...
const app = createSSRApp(App)
// это предполагает, что в шаблоне App.vue будет корневой элемент с `id="app"`
app.mount('#app')

1
2
3
4
5
6
7
8
9

entry-server.js

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

import { createSSRApp } from 'vue'
import App from './App.vue'
export default function() {
  const app = createSSRApp(App)
  return {
    app
  }
}

1
2
3
4
5
6
7
8
9
10

Как структурировать крупномасштабное приложение Vue.

js

Эта статья является частью 1 из 3 в серии Как структурировать крупномасштабное приложение Vue.js

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

Что именно я имею в виду под предсказуемостью? Проще говоря, это возможность интуитивно перейти от запроса функции или отчета об ошибке к месту в кодовой базе, где может быть решена указанная задача. Кроме того, это возможность быстро узнать, к каким инструментам у вас есть доступ в этом месте кодовой базы, чтобы выполнить поставленную задачу.

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

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

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

Так как же добиться предсказуемости кодовой базы? Ответ: стандарты, простые и понятные. Может быть, это не тот ответ, который вы ищете, но это правда. Лучший способ сделать что-либо предсказуемым — заставить его следовать набору стандартов. Например, я могу почти со 100% уверенностью предсказать, что новые полноразмерные простыни, которые я купил только сегодня, подойдут к моей кровати, хотя я никогда раньше не застилал ее этими простынями. Почему? Из-за стандартной системы размеров постельного белья.

Стандарты предсказуемости для всего сообщества

Итак, возникает вопрос, какие стандарты существуют для сообщества Vue.js в целом? Я бы сказал, что доступно 4 источника стандартов.

  1. Руководство по стилю Vue.js
  2. Скаффолдинг, сгенерированный Vue CLI
  3. официальные библиотеки Vue.js (находятся в разделе «Экосистема» > «Официальные проекты» на веб-сайте Vue.js)
  4. и более свободно, самые популярные платформы компонентов, такие как Vuetify или Quasar 9. 0024

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

Официальные библиотеки и библиотеки компонентов

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

Библиотека Vuex на самом деле принимает и рекламирует этот факт как главную функцию, называя себя «шаблон управления состоянием + библиотека».

Это может показаться очевидным, но здесь есть что сказать. Если есть существующее популярное или рекомендуемое решение проблемы во Vue.js (и тем более, если это официальное решение), я бы долго думал, прежде чем использовать что-то другое. Я так же счастлив, как и любой другой парень, создавая свои собственные компоненты, магазины и т. Д., Но часто в долгосрочной перспективе действительно окупается использование проверенного и надежного решения не только из-за функциональности, покрытия тестами и документации, которую они предложения, но и из-за стандартизации, которую они приносят. (А в мире JavaScript мы все не можем просто использовать немного больше стандартизации 😆).

Когда дело доходит до выбора этих более стандартизированных решений, важно помнить, что это за здание. Вы создаете масштабируемый повторно используемый компонент? Тогда, возможно, стандартная библиотека не для вас, потому что вы пытаетесь создать новую стандартную библиотеку. Однако это, вероятно, не то, что большинство из нас строит. Большинство из нас, вероятно, создают приложение, и если это так, то, вероятно, лучше использовать стандартные (или, по крайней мере, полустандартные) части, которые уже существуют, в качестве строительных блоков.

Начало стандартной файловой структуры

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

Большинство из нас, вероятно, знакомы с этой структурой, и это здорово! Это означает, что мы на шаг ближе к предсказуемости! Итак, суть здесь в том, чтобы не переусердствовать. Придерживайтесь того, что Vue дает вам из коробки, и не отклоняйтесь от него, пока у вас не появится (действительно) веская причина.

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

Рекомендуемые правила для компонентов

Теперь, сосредоточившись на директории компонента, в руководстве по стилю Vue есть еще несколько советов, как сделать нашу файловую структуру более предсказуемой. Помимо прочего, руководство по стилю рекомендует следующее, когда дело доходит до определения компонентов:

  • По возможности каждый компонент должен быть определен в своем собственном выделенном файле (SFC)
  • Компоненты одного файла должны быть названы в PascalCase
  • Базовые компоненты должны начинаться с одного и того же префикса (например, Base или App )
    • Вы можете думать о базовых компонентах как о повторно используемых компонентах всего приложения, таких как кнопка или модальное окно
    • Это группирует их вместе и объявляет их глобальный, многоразовый характер
  • Имена компонентов всегда должны состоять из нескольких слов, чтобы не конфликтовать ни с какими существующими или будущими элементами HTML. Не создавайте Таблица или компонент Кнопка .
  • Компоненты одного экземпляра должны начинаться с префикса .
    • Например, верхний или нижний колонтитул сайта
    • Это группирует их вместе и объявляет их одноразовыми
  • Тесно связанные дочерние компоненты должны иметь префикс с именем их родительского компонента.
    • Например, TodoListItem в TodoList
    • Это группирует их вместе и объявляет связанными
  • Имена компонентов должны начинаться со слов самого верхнего уровня (обычно общего) и заканчиваться наиболее конкретными
    • Например, SearchWidgetInput , SearchWidgetResultsList , SearchWidget
    • Это группирует связанные компоненты вместе в файловой структуре

Держитесь крепче, если это не совсем понятно, через минуту появится изображение, которое может помочь 🙂

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

Некоторые рекомендуемые личные/командные стандарты предсказуемости

Несмотря на то, что официальные источники установили несколько отличных стандартов для всего сообщества Vue.js, существуют и другие шаблоны, не столь широко распространенные, которые, по моему опыту, могут быть столь же полезными и превращены в стандарты для вас или проектов вашей команды. Такие стандарты необходимы, поскольку стандарты для всего сообщества не являются всеобъемлющими на 100%, но просто будьте осторожны и будьте строги, когда дело доходит до того, как принимаются и поддерживаются командные стандарты … это может быть кроличья нора постоянно меняющихся правил, если вы не осторожный. Тем не менее, вот некоторые из моих рекомендаций по стандартам вашего проекта Vue.js.

Каталог плоских компонентов

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

  • Быстро и легко перейти от обнаружения компонента в Vue devtools к поиску файла в кодовой базе (имя файла и имя компонента совпадают)
  • Используйте функцию быстрого поиска или перехода между файлами в вашей среде IDE для фильтрации файлов на основе их наиболее общего атрибута до более конкретного
  • Устранение паралича анализа при принятии решения о том, как организовать компоненты в подкаталоги
  • Возможность видеть все компоненты сразу в одном списке
  • Избавьтесь от избыточности ключевых слов в именах файлов И в каталоге (то есть, если вы следуете руководству по стилю (и вы должны им следовать) и используете вложенные каталоги) (т.е. post/PostList.vue , post/PostFeature. vue и т. д.)
  • Удалите искушение использовать короткие имена компонентов из одного слова, что проще сделать с вложенными каталогами (например, post/List.vue , post/Feature.vue ) и нарушает руководство по стилю
  • Устранение просмотра файловой структуры в каталогах и из них для поиска компонента
  • Упрощение импорта компонентов (всегда будет import SomeComponent from "@/SomeComponent" )

Так как же выглядит плоская структура, соответствующая руководству по стилю? Вот хороший пример.

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

Стандартизированное соглашение об именах маршрутов и страниц

Еще одна практика, имеющая смысл, — стандартизированный способ именования наших маршрутов и компонентов страниц. В вашем типичном приложении CRUD у вас есть следующие разные страницы для каждого ресурса:

  1. список всех ресурсов
  2. просмотр одного ресурса
  3. форма для создания ресурса
  4. и форма для редактирования ресурса

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

Поскольку у меня есть опыт работы с PHP-фреймворком Laravel, когда дело дошло до именования маршрутов и определения их путей предсказуемым образом, я интуитивно прибегнул к стандартам, которые уже были в Laravel. Это упростило моей опытной команде Laravel более быструю и интуитивно понятную работу с Vue. Используя ресурс «user» в качестве примера, соглашение об именах, предписанное Laravel и адаптированное для Vue, которое я рекомендую, выглядит следующим образом:0003

Путь Имя маршрута и компонента Что он делает
/пользователи Индекс пользователей Список всех пользователей
/пользователи/создать пользователейСоздать Форма для создания пользователя
/пользователи/{id} ПользователейПоказать Отображение сведений о пользователях
/пользователи/{id}/редактировать пользователейПравить Форма для редактирования пользователя

Несмотря на искушение назвать маршрут в более традиционном поместье Laravel, таком как users. index вместо UsersIndex , я обнаружил, что использование PascalCase работает так же хорошо и имеет дополнительное преимущество соответствия имени компонента .

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

 Пользователи 

Также стоит отметить, что не все маршруты точно соответствуют этому шаблону, поскольку некоторые маршруты будут более «CRUDdy» чем другие. Для тех, кто не соответствует шаблону, моя единственная рекомендация состоит в том, чтобы вы продолжали использовать PascalCase для имени вашего маршрута для согласованности.

Более полная файловая структура

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

Сюда добавлены каталоги с документами, помощниками, макетами, миксинами и плагинами. Вы заметите, что 4 из 5 имеют причудливую иконку рядом с ними, предоставленную темой значка материала расширения VS Code. Это потому, что в то или иное время для некоторых фреймворков или языков эти соглашения о каталогах были достаточно распространены, чтобы получить собственный значок в глазах разработчика расширения. Это не случайно!

Я также добавил один файл globals.js.

Итак, что стоит за этими стандартами файловой структуры? Что ж, я рад, что вы спросили!

docs

Цель этого очевидна, но более важно то, что он включен и смотрит вашей команде прямо в лицо каждый раз, когда они открывают кодовую базу. Более вероятно, что некоторые аспекты проекта будут задокументированы, если разработчику никогда не придется покидать свою IDE. Я также обнаружил (это был приятный сюрприз), что написание документации перед кодированием повторно используемого класса или компонента обычно помогает мне лучше спроектировать интерфейс или API указанного кода. Давай, я смею тебя попробовать!

Кроме того, помимо каталога docs, я счел полезным предоставить файл README.md в корне каждого стандартизированного каталога, объясняющий назначение каталога и любые правила относительно того, что должно быть включено в него. Это особенно полезно для тех стандартов, которые не являются общими для всего сообщества.

помощники

Это общий каталог во многих фреймворках для базовых функций ввода-вывода, которые можно многократно использовать в рамках проекта. Как правило, их легко тестировать, и обычно они используются более одного раза. Мне нравится начинать с одного index.js , а затем, по мере роста помощников, разбивайте их на более сгруппированные файлы, такие как https.js , cache.js , time.js и т. д. Все в этом каталоге можно просто импортировать и используется по запросу, и если функция вообще никогда не используется, ее можно легко удалить из производственного пакета.

макеты

Я взял это соглашение из Nuxt, а также из Laravel. Может быть удобно не только определять компоненты страницы, но и компоненты макета, которые можно повторно использовать на нескольких страницах. Вместо того, чтобы определять содержимое страницы, как следует из названия, эти компоненты больше определяют общий макет. Например, это страница с одним столбцом или с двумя столбцами? У него есть левая боковая панель или правая боковая панель? Включает ли макет типичный верхний и нижний колонтитулы или это полностью пустой макет, возможно, с абсолютно центрированным содержимым страницы? Обычно таких компонентов макета всего 2 или 3, но, тем не менее, они могут быть удобной абстракцией.

миксины

Этот каталог предназначен для организации всех ваших миксинов Vue.js. Я думаю, что по-прежнему важно добавлять слово Mixin в конец каждого имени файла (например, ResourceTableMixin.js ) для облегчения поиска в вашем переключателе файлов. Хотя у меня еще не было возможности по-настоящему поработать над более масштабным проектом Vue 3, я предполагаю, что он, вероятно, быстро изменится на каталог composables вместо извлечения реактивных данных/методов с помощью Composition API вместо миксинов. Или хотя бы 9Каталог 0068 composables может быть добавлен в мою стандартную файловую структуру в дополнение к каталогу mixins .

plugins

Последний каталог, который мне нравится включать во все мои проекты Vue, — это каталог plugins . В мире пакетов и библиотек мы иногда больше занимаемся настройкой и регистрацией, чем собственно программированием. Вот для чего предназначен этот каталог, включая и настройку всех сторонних материалов Vue. Хотя это и называется плагинами, я не всегда использую этот термин в самом строгом смысле. Другими словами, это не должна быть сторонняя библиотека, зарегистрированная через Vue 9.0068 .use() метод. Часто это так, но в других случаях используются альтернативные методы настройки библиотеки с помощью Vue (например, . component() ). Для библиотек, которые требуют настройки в одну или две строки, я напишу их в файле plugins/index.js . Для тех, кто выполняет более сложную настройку, я создаю для них специальный файл в каталоге плагинов, а затем импортирую его в plugins/index.js .

globals.js

Это единственный стандартный файл, который я когда-либо добавлял. Его цель состоит в том, чтобы добавить ограниченное количество глобальных переменных в приложение Vue и, для SPA, которые являются только клиентскими, обычно это окно.

Это комментарий, который обычно украшает начало этого файла.

 /**
 * Используйте этот файл для регистрации любых переменных или функций, которые должны быть доступны глобально
 * в идеале вы должны сделать его доступным через объект окна
 * а также прототип Vue для доступа во всем приложении
 * (регистрируйте глобальные переменные с осторожностью, только если они доступны для всего приложения)
 */ 

В Vue 2 это можно сделать так:

 Vue. prototype.$http = () => {} 

В Vue 3 это выглядит так:

 константное приложение = createApp({})
app.config.globalProperties.$http = () => {} 

Хотя меня постоянно предупреждали об опасности глобальных переменных, я однажды прочитал, что «небольшое небольшое количество глобальных переменных» — очень удобная вещь, и она оказалась полезной для меня. с тех пор. Этот файл позволяет мне легко узнать, что представляют собой эти глобальные переменные, и позволяет мне не думать, когда я хочу добавить больше.

Краткий обзор предсказуемости

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

Хотя стандарты предсказуемости являются большим преимуществом для крупномасштабных приложений Vue.js, можно сделать еще больше. Обязательно ознакомьтесь со следующей статьей этой серии, в которой мы углубимся в инструменты линтинга и форматирования, такие как ESLint и Prettier, чтобы ваш код был чистым, безошибочным и согласованным.

Хотите повысить уровень своего бизнеса?

Мы помогаем компаниям по всему миру создавать приложения Vue более эффективно. Считаете ли вы, что вашей команде будет полезно профессиональное обучение или консультации по Vue? Или, возможно, вам нужны дополнительные руки для разработки следующего этапа?
Мы рады узнать о потребностях вашего бизнеса и понять, как мы можем вам помочь. Ознакомьтесь с нашими бизнес-ценами на командное обучение или свяжитесь с нами по деловым вопросам в любое время!

Структура каталога проекта Vue: Держите его плоским или сгруппируйте по доменам вместо?

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

В этой статье мы рассмотрим три варианта структурирования нашего проекта Vue. От очень плоского файлового дерева до создания отдельных каталогов для каждого модуля домена .

  • Плоское дерево файлов
  • Плоское дерево файлов с базовым каталогом
  • Группировать по домену

Плоское дерево файлов

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

 /мой/проект/источник
├─ компоненты
│ ├─ BaseButton.vue
│ ├─ BaseCard.vue
│ ├─ BaseLink.vue
│ ├─ ...
│ ├─ ProductCart.vue
│ ├─ ProductDetail. vue
│ ├─ ...
│ ├─ TheFooter.vue
│ ├─ TheHeader.vue
│ └─ ...
├─ услуги
│ ├─ product.js
│ └─ ...
├─ утилиты
│ ├─ as-array.js
│ ├─ format-price.js
│ └─ ...
└─ ... 

Возможно, первое, что вы почувствуете, это то, что вы никогда ничего не сможете найти, если у вас есть более 100 компонентов. Если это так, я полагаю, вы не используете функцию быстрого открытия ваших редакторов для открытия файлов. Тем не менее, я настоятельно рекомендую вам взять за привычку использовать команду быстрого открытия для открытия файлов (в macOS в Visual Studio Code сочетание клавиш — CMD+P ) вместо поиска их в дереве файлов вашего редактора. Как только вы научитесь открывать файлы с помощью быстрого открытия, вы заметите, что в любом случае почти не смотрите на дерево файлов.



Плоское дерево файлов с базовым каталогом

Когда все становится сложнее, я все же рекомендую увеличивать сложность только постепенно. Например, если совершенно плоская структура каталогов вам не подходит (больше), начните с добавления только одного дополнительного каталога: base .

 /мой/проект/источник
├─ компоненты
│ ├─ база
│ │ ├─ BaseButton.vue
│ │ ├─ BaseCard.vue
│ │ ├─ BaseLink.vue
│ │ └─ ...
│ ├─ ProductCart.vue
│ ├─ ProductDetail.vue
│ ├─ ...
│ ├─ TheFooter.vue
│ ├─ TheHeader.vue
│ └─ ...
├─ услуги
│ ├─ product.js
│ └─ ...
├─ утилиты
│ ├─ as-array.js
│ ├─ format-price.js
│ └─ ...
└─ ... 

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

Группировать по доменам

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

Но мы можем получить многие из тех же преимуществ, применяя принципы Domain-Driven Design (DDD) при планировании структуры каталогов нашего приложения.

 /мой/проект/источник
├─ компоненты
│ ├─ база
│ │ ├─ BaseCard.vue
│ │ ├─ BaseButton.vue
│ │ ├─ BaseCard.vue
│ │ ├─ BaseLink.vue
│ │ └─ ...
│ ├─ TheFooter.vue
│ ├─ TheHeader.vue
│ └─ ...
├─ модули
│ ├─ товар
│ │ ├─ компоненты
│ │ │ ├─ ProductCart.vue
│ │ │ ├─ ProductDetail.vue
│ │ │ └─ ...
│ │ ├─ услуги
│ │ │ └─ product.js
│ │ └─ утилиты
│ │ └─ формат-цена.js
│ └─ ...
├─ утилиты
│ ├─ as-array.js
│ └─ ...
└─ ... 

Теперь у нас есть отдельные каталоги для всех различных модулей (= доменов) нашего приложения. Поэтому думайте о каждом модуле как о крошечном приложении внутри нашего приложения.

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

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

Рефакторинг не только нашего кода, но и нашей структуры каталогов должен быть постоянным. Предположим, мы заметили, что несколько модулей часто меняются вместе по одной и той же причине, или нам регулярно нужно импортировать код из одного модуля в другой модуль. В таком случае это намек на то, что вместо этого мы должны объединить их в один модуль.

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

This entry was posted in Популярное