Просмотреть все уроки из серии Let’s Learn Adonis 5 здесь.
Теперь, когда у нас есть приложение Adonis создано и мы убедились, что оно работает нормально, давайте продолжим и начнем погружаться в наш проект и изучать фактическую структуру проекта.
Итак, продолжайте и откройте свой только что созданный проект в выбранном вами текстовом редакторе, я использую Visual Studio Code, и слева вы можете увидеть, что мы начали с нескольких каталогов. и файлы. С некоторыми из них вы, возможно, уже знакомы, если нет, мы потратим некоторое время в этом уроке на просмотр каждой из этих разных папок и файлов, чтобы вы всегда точно знали, где вы находитесь в структуре вашего проекта.
Для начала у нас будет два каталога, в которых мы будем проводить большую часть времени. Каталог app и каталог resources.
Каталог приложений
Каталог приложения будет содержать почти всю нашу бизнес-логику, если не всю. Он будет содержать наши контроллеры, модели, сервисы, исключения, промежуточное ПО и так далее.
Каждый из них получит свой собственный подкаталог в каталоге приложения. Adonis фактически запускает нас с каталогом исключений, который содержит один файл с именем Handler.ts. Этот файл отвечает за обработку исключений нашего приложения во время HTTP-запроса.
По умолчанию файл Handler.ts выглядит так:
// app/Exceptions/Handler.ts/* |-------------------------------------------------------------------------- | Http Exception Handler |-------------------------------------------------------------------------- | | AdonisJs will forward all exceptions occurred during an HTTP request to | the following class. You can learn more about exception handling by | reading docs. | | The exception handler extends a base `HttpExceptionHandler` which is not | mandatory, however it can do lot of heavy lifting to handle the errors | properly. | */import Logger from '@ioc:Adonis/Core/Logger' import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'export default class ExceptionHandler extends HttpExceptionHandler { protected statusPages = { '403': 'errors/unauthorized', '404': 'errors/not-found', '500..599': 'errors/server-error', }constructor () { super(Logger) } }
Adonis начинает с пары определенных страниц состояния, которые используются для обработки наших исключений, возникающих в производственной среде. Когда мы будем в разработке, Adonis будет использовать пакет под названием Youch для отображения полезной информации об исключении, которое было создано, чтобы помочь нам в отладке нашего приложения.
Таким образом, в рабочей среде, когда возникает исключение, если статус исключения соответствует одному из этих определенных statusPages статусов, Adonis будет искать представление, определенное как значение, и отображать эту страницу, чтобы уведомить пользователя об ошибке. Если возникнет исключение 403, Adonis отобразит представление в resources/views/errors/unauthorized.edge. Для 404 Adonis отобразит resources/views/errors/not-found.edge. А для значений от 500 до 599 Adonis будет отображать resources/views/errors/server-error.edge. Adonis также запускает нас с этими страницами ошибок в нашем каталоге resources/views/errors.
Каталог ресурсов
Каталог ресурсов будет содержать все наши нескомпилированные интерфейсные ресурсы. Итак, он будет содержать наш JavaScript, каскадную таблицу стилей (CSS) и файлы просмотра. Он также может содержать необработанные изображения, если вам нужно обработать изображения до того, как они станут общедоступными для пользователей, и любые другие ресурсы, которые должны быть обработаны нашим интерфейсом.
Когда мы говорим о страницах, страницах рендеринга или представлениях рендеринга (например, с нашим обработчиком исключений), Adonis по умолчанию будет искать эти файлы в нашем каталоге resources/views. Вы могли заметить, что эти файлы заканчиваются расширением .edge. Если мы взглянем на наш файл welcome.edge, который называется Это работает! страницу, которую мы видели, когда запускали наш сервер, вы увидите следующее.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>AdonisJS - A fully featured web framework for Node.js</title> @entryPointStyles('app') @entryPointScripts('app') </head> <body><main> <div> <h1 class="title"> It Works! </h1> <p class="subtitle"> Congratulations, you have just created your first AdonisJS app. </p><ul> <li> The route for this page is defined inside <code>start/routes.ts</code> file </li><li> You can update this page by editing <code>resources/views/welcome.edge</code> file </li><li> If you run into problems, you can reach us on <a href="https://discord.gg/vDcEjq6?">Discord</a> or the <a href="<https://forum.adonisjs.com/>">Forum</a>. </li> </ul> </div> </main> </body> </html>
На первый взгляд это не более чем стандартный язык гипертекстовой разметки (HTML), однако это полноценный механизм шаблонов. Он поддерживает условия, циклы, частицы, компоненты, макеты, локальные переменные и, конечно же, внедрение данных прямо на страницу.
Edge также не привязан конкретно к HTML, вы можете использовать его для рендеринга других типов файлов, таких как TXT, PDF, XML и т. д. Мы также можем использовать его для создания нашей разметки электронной почты.
Edge и текстовые редакторы
Теперь по умолчанию ваш текстовый редактор, скорее всего, не поддерживает Edge. Однако для Visual Studio Code, Sublime Text, Atom и Vim есть плагин, который добавит поддержку Edge.
- Код Visual Studio: поддержка шаблонов Edge
- Возвышенный текст: Edge Sublime
- Atom: Синтаксис Edge Atom
- Vim: Шаблон Vim Edge
Актуальный список можно найти в этом разделе документации.
Публичный каталог
Публичный каталог предназначен для скомпилированных, обработанных и статических ресурсов, готовых к использованию для просмотра нашими пользователями. Таким образом, для наших нескомпилированных файлов JavaScript и CSS в нашем каталоге ресурсов общедоступный каталог будет содержать скомпилированные версии этих ресурсов. Скомпилированные версии — это то, что будет использовать наше приложение.
@entryPointStyles('app') и @entryPointScripts('app'), которые вы видите в нашем файле welcome.edge, на самом деле являются помощниками Edge, которые вводят элемент <link> для нашего скомпилированного CSS. Предоставленный аргумент 'app' указывает, что нужно специально искать компилируемый файл CSS с именем app.css. То же самое относится и к нашему JavaScript, он вставит элемент <script> для нашей компиляции JavaScript.
Причина, по которой эти два помощника настолько выгодны, по сравнению с простым добавлением элементов и источников, заключается в том, что эти помощники добавят суффикс версии к источникам с хешированной версией файлов. Затем суффикс версии меняется каждый раз при изменении этих файлов. Таким образом, в производственной среде, когда это произойдет, кешированная версия файлов будет пропущена для наших пользователей, и пользователи получат обновленную версию. Таким образом, это помогает гарантировать, что наши пользователи используют последние версии наших файлов ресурсов.
Каталог команд
Adonis поставляется с собственным Интерфейсом командной строки (CLI), называемым Ace CLI. На самом деле вы также можете создавать свои собственные команды для использования с Ace CLI. Эти пользовательские команды — это то, для чего предназначен каталог команд. В нем будут размещены все наши пользовательские команды, специфичные для нашего приложения.
Adonis начинает нас с файла index.ts в каталоге команд. Этот файл отвечает за чтение любых пользовательских команд, которые мы добавляем в этот каталог, и предоставление этих команд обратно в Ace CLI.
import { listDirectoryFiles } from '@adonisjs/core/build/standalone' import Application from '@ioc:Adonis/Core/Application'/* |-------------------------------------------------------------------------- | Exporting an array of commands |-------------------------------------------------------------------------- | | Instead of manually exporting each file from this directory, we use the | helper `listDirectoryFiles` to recursively collect and export an array | of filenames. | | Couple of things to note: | | 1. The file path must be relative from the project root and not this directory. | 2. We must ignore this file to avoid getting into an infinite loop | */ export default listDirectoryFiles(__dirname, Application.appRoot, ['./commands/index'])
Каталог конфигурации
Каталог config содержит все наши конфигурации приложения. Они удобно разделены на разные файлы, сгруппированные по теме конфигурации.
У нас есть конкретная конфигурация для нашего
- Приложение
- Анализатор тела
- КОРС
- Хеширование
- Сессия
- Безопасность под названием Щит
- Статический
По мере того, как мы добавляем в наше приложение больше модулей Adonis, также будет добавлено больше файлов конфигурации. Полную информацию о конфигурациях Adonis от сторонних производителей см. на этой странице документации.
Вы также можете редактировать их по мере необходимости и добавлять новые файлы конфигурации по мере необходимости. Затем они будут легко использоваться во всем нашем приложении, например:
import sessionConfig from 'Config/session'sessionConfig.cookieName
Каталог контрактов и переменные среды
На протяжении всего Adonis вы будете часто видеть термины контрактов. Теперь я признаю, что я не мастер TypeScript, я не использую его активно. С учетом этой оговорки мое понимание контрактов состоит в том, что это, по сути, строгие определения типов TypeScript.
Adonis начинает нас с парой контрактов в нашем каталоге контрактов. Если мы посмотрим на наш файл contracts/env.ts, то увидим следующее.
/** * Contract source: <https://git.io/JTm6U> * * Feel free to let us know via PR, if you find something broken in this contract * file. */declare module '@ioc:Adonis/Core/Env' { /* |-------------------------------------------------------------------------- | Getting types for validated environment variables |-------------------------------------------------------------------------- | | The `default` export from the "../env.ts" file exports types for the | validated environment variables. Here we merge them with the `EnvTypes` | interface so that you can enjoy intellisense when using the "Env" | module. | */type CustomTypes = typeof import("../env").default; interface EnvTypes extends CustomTypes { } }
Итак, это объявление модуля @ioc:Adonis/Core/Env, который мы можем импортировать по всему нашему проекту и иметь доступ к нашим переменным среды. Внутри объявления модуля он импортирует CustomTypes из нашего файла env.ts. Этот файл env.ts выглядит так:
/* |-------------------------------------------------------------------------- | Validating Environment Variables |-------------------------------------------------------------------------- | | In this file we define the rules for validating environment variables. | By performing validation we ensure that your application is running in | a stable environment with correct configuration values. | | This file is read automatically by the framework during the boot lifecycle | and hence do not rename or move this file to a different location. | */import Env from '@ioc:Adonis/Core/Env'export default Env.rules({ HOST: Env.schema.string({ format: 'host' }), PORT: Env.schema.number(), APP_KEY: Env.schema.string(), APP_NAME: Env.schema.string(), CACHE_VIEWS: Env.schema.boolean(), SESSION_DRIVER: Env.schema.string(), NODE_ENV: Env.schema.enum(['development', 'production', 'testing'] as const), })
Этот файл используется для предоставления IntelliSense и определения необходимых переменных среды, которые фактически находятся в нашем файле .env. Это безопасные переменные, которые не должны быть общедоступными. Используя файл env.ts, мы определяем, какие ключи должны быть в нашем файле .env и какими должны быть типы этих ключей, а также дополнительные ограничения для файла.
Например, наш тип NODE_ENV указывает, что значение NODE_ENV в нашем .env является обязательным, и это значение должно быть либо разработкой, производством, либо тестированием. Ничего другого не разрешено, иначе наш сервер откажется запускаться.
Эти типы применяются EnvContract. Вы можете просмотреть полную декларацию Env здесь, я просто вытащу отсюда EnvContract, чтобы мы могли ее изучить.
declare module '@ioc:Adonis/Core/Env' { // ... other stuff/** * Env contract */ export interface EnvContract { /** * Get value for a given environment variable */ get<K extends keyof EnvTypes>(key: K): EnvTypes[K] get<K extends keyof EnvTypes>( key: K, defaultValue: Exclude<EnvTypes[K], undefined> ): Exclude<EnvTypes[K], undefined> get(key: string, defaultValue?: any): any/** * Update/set value for a given environment variable. Ideally one should * avoid updating values during runtime */ set<K extends keyof EnvTypes>(key: K, value: EnvTypes[K]): void set(key: string, value: any): void/** * Validate environment variables */ rules<T extends { [key: string]: ValidateFn<unknown> }>( values: T ): { [K in keyof T]: ReturnType<T[K]> }/** * Processes environment variables and performs the registered * validations */ process(): void/** * Reference to the schema object for defining validation * rules */ schema: EnvSchema }const Env: EnvContract export default Env }
Итак, EnvContract специально определяет методы и свойства, которые будут доступны в Env, когда мы import Env from '@ioc:Adonis/Core/Env'. Кроме того, он также обеспечивает проверку этих типов, делая эти типы строгими.
Пожалуйста, отнеситесь к моему пониманию контрактов с долей скепсиса, я, вероятно, не лучший человек, чтобы объяснить контракты, потому что я не активный пользователь TypeScript. Этот README от пользователя GitHub bigslycat — вот откуда я почерпнул свое понимание.
Справочник поставщиков
Каталог провайдеров по умолчанию содержит файл AppProvider. Провайдеры имеют множество применений: от предоставления дополнительных глобальных переменных или функций нашим представлениям до расширения Adonis с помощью пользовательских пакетов или сторонних пакетов.
Провайдеры загружаются один раз во время цикла загрузки нашего приложения и предоставляют нам доступ для запуска кода на определенных хуках жизненного цикла нашего приложения.
AppProvider, с которого мы начали, выглядит так, как показано ниже.
import { ApplicationContract } from '@ioc:Adonis/Core/Application'export default class AppProvider { constructor (protected app: ApplicationContract) { }public register () { // Register your own bindings }public async boot () { // IoC container is ready }public async ready () { // App is ready }public async shutdown () { // Cleanup, since app is going down } }
Итак, как вы можете видеть, провайдеры — это классы, которым предоставляется экземпляр ApplicationContract нашего приложения, который содержит такие вещи, как наш регистратор, переменные среды, конфигурации, помощники, окружение узла и т. д.
В нашем крючке жизненного цикла загрузки мы также можем импортировать дополнительные модули, которые нам могут понадобиться для расширения, например модуль View.
Вы можете добавить столько файлов провайдеров, сколько вам нужно, просто обратите внимание, что когда вы добавляете дополнительных провайдеров в свое приложение, эти провайдеры также должны быть зарегистрированы в вашем файле adonisrc.json.
Начальный каталог
Стартовый каталог содержит то, что определено только один раз в крючке жизненного цикла загрузки нашего приложения. Это будут такие вещи, как наши маршруты, регистрация промежуточного ПО, события и т. д.
По умолчанию Adonis запускает нас с файлом routes.ts и kernel.ts. routes.ts — это место, где мы будем регистрировать наши маршруты для нашего приложения. kernel.ts — это место, где мы будем регистрировать промежуточное программное обеспечение нашего приложения.
Вы можете добавить столько файлов, сколько вам нужно, в свой стартовый каталог, просто обратите внимание, что они будут выполняться один раз при загрузке вашего приложения. Любые дополнительные файлы, которые вы создадите, также должны быть зарегистрированы в массиве preloads в вашем файле adonisrc.json.
adonisrc.json
Файл adonisrc.json используется для регистрации файлов и настройки нашего приложения Adonis. Здесь вам нужно будет добавить любые дополнительные провайдеры и начальные файлы, которые вы добавляете в свой проект, чтобы Adonis мог их подобрать.
Если вы собираетесь изменить что-либо в файле adonisrc.json, не входящее в массив preloads или provider, я бы рекомендовал вам ознакомиться с документацией того, что вы изменяете, чтобы лучше понять, что вы делаете.
server.ts
По сути, это место, где загружается наш сервер приложений. Если вы не занимаетесь более сложными делами, вам, скорее всего, никогда не понадобится прикасаться к этому файлу.
tsconfig.json
Этот файл предназначен специально для настройки TypeScript в нашем приложении. Скорее всего, вы прикоснетесь к этому файлу, только если вам нужно исключить TypeScript из чтения определенных файлов или каталогов, если вам нужно определить дополнительные пути или типы для компилятора TypeScript. Если вы измените какие-либо псевдонимы в вашем файле adonisrc.json, их также необходимо будет обновить в объекте путей вашего файла tsconfig.json.
webpack.config.js
Это включается только в том случае, если вы решили включить Webpack Encore в свое приложение. Здесь мы собираемся указать, какие ресурсы ресурсов мы хотим скомпилировать, и как эти файлы должны быть скомпилированы. Когда мы запустим наш сервер, эти файлы будут затем скомпилированы и помещены туда, где мы укажем, что должно быть нашим общедоступным каталогом.
Следующий урок:
Просмотр серии Let’s Learn Adonis 5: