Nuxt 3: ручная маршрутизация и иерархическая структура
Nuxt 3 теперь доступен для бета-тестирования, и мне не терпится познакомиться с его новыми функциями. Интересно, как там обстоят дела с одной очень важной вещью — иерархической структурой проекта.
Конечно, стандартная структура проекта хорошо подходит для простых проектов, но когда ваш проект растет и ваша команда растет, становится сложно управлять структурой стандартным способом. Папка ваших страниц становится большой, папка вашего компонента становится грязной.
Лучший способ справиться с такими проблемами — организовать проект иерархически. Основная идея проста — каждая папка имеет дело с одной частью домена вашего приложения, удерживая его страницы и компоненты, связанные вместе. Вы можете разделить папки вашего домена (которые мы называем модулями в нашей компании) на поддомены в зависимости от того, какой уровень детализации вам нужен.
К сожалению, по умолчанию Nuxt не допускает такого поведения.
Во второй версии мы использовали раздел router в nuxt.config.js, чтобы переопределить автоматическое сопоставление папок страниц, но похоже, что эта функция была удалена в третьей версии.
Или просто немного изменился.
Беглое изучение исходного кода показывает, что интерфейс NuxtHooks в схеме конфигурации nuxt включает два подозрительных хука: build:extendRoutes и pages:extend. Похоже, что один из них именно то, что мы ищем.
Сначала я попробовал «build:extendRoutes», но безрезультатно. Похоже, его вообще не вызывали.
Затем я взломал «pages:extend». Он получает список страниц нашего приложения в качестве первого аргумента, и каждая запись включает имя маршрута, строку URL и путь к файлу с компонентом. Что, если мы попытаемся добавить в этот список дополнительные записи?
export default defineNuxtConfig({ hooks: { 'pages:extend': (pages: any) => { routes.push({ name: 'module-e-page', path: '/module-e/:id?', file: __dirname + '/modules/SomeModule/index.vue' }) } } })
И, наконец, это работает!
Теперь нам нужно кое-что сделать, чтобы сделать проект аккуратным и аккуратным.
Во-первых, я объявил интерфейс Route, так как пакет nuxt3 не имеет экспортированного члена для определения типа страниц (внутренне он использует NuxtPage).
export default interface Route { name: string, path: string, file: string }
Во-вторых, я написал изолированный маршрутизатор для каждого модуля в проекте. Например, modules/ModuleE/router.ts:
import { Route } from '@/core' export default function routes (routes: Route[]) { routes.push({ name: 'module-e-index', path: '/module-e', file: __dirname + '/index.vue' }) routes.push({ name: 'module-e-page', path: '/module-e/:id?', file: __dirname + '/index.vue' }) }
Затем я создал router.ts прямо в корневой папке моего проекта. Здесь можно импортировать и вызывать маршрутизаторы из каждого модуля^
import { Route } from './core/' import ModuleERoutes from './modules/ModuleE/router' import ModuleYRoutes from './modules/ModuleY/router' export default function router (routes: Route[]) { ModuleERoutes(routes) ModuleYRoutes(routes) }
И, наконец, вызовите их все в nuxt.config.ts.
import { defineNuxtConfig } from 'nuxt3' import { Route } from './core' import routes from './router' export default defineNuxtConfig({ hooks: { 'pages:extend': (pages: Route[]) => { routes(pages) } } })
Таким образом, мы можем получить любую структуру проекта, какую захотим, несмотря на ограничения Nuxt.