Angel — это полнофункциональный серверный фреймворк с полным стеком для языка Dart, версия 1 которого существует с начала 2017 года. Одна из его основных целей — предоставить широкий спектр функциональности из коробки. . Таким образом, Angel поставляет плагин для обслуживания статических файлов, который присутствует с самого начала проекта. package:angel_static настраивается, поддерживает кэширование в браузере и хорошо взаимодействует с маршрутизацией с отправкой состояния.

Основы

Чтобы обслуживать файлы из каталога в вашей файловой системе, просто используйте связанный VirtualDirectory API:

configureServer(Angel app) async {
  await app.configure(new VirtualDirectory());
}

По умолчанию VirtualDirectory добавляет содержимое файла в буфер ответа, что хорошо сочетается с функциями сжатия, предоставляемыми package:angel_compress:

// Serve compressed files out of a directory!!!
configureServer(Angel app) async {
  await app.configure(new VirtualDirectory());
  // Add GZIP compression to `responseFinalizers`, so that it
  // runs *after* every request:
  app.responseFinalizers.add(gzip());
}

С аргументами по умолчанию VirtualDirectory предполагает, что вы обслуживаете проект Dart, и угадываете, из какого каталога обслуживать файлы. Если в вашей среде для ANGEL_ENV установлено значение production, то по умолчанию будет использоваться папка по пути build/web. Если нет, то подается из web. Преимущество здесь в том, что вы можете обслуживать активы разработки во время разработки, а при работе в рабочей среде обслуживать оптимизированные активы (созданные с помощью pub build) без какой-либо дополнительной настройки приложения.

Конечно, если вы обслуживаете из другого каталога, вы можете просто указать аргумент source:

new VirtualDirectory(source: new Directory('<path>');

Поддержка кэширования браузера

Заголовки Cache-Control используются, чтобы сообщить браузерам, как кэшировать статические ресурсы и сократить время загрузки страницы при повторном посещении вашего веб-сайта. Чтобы добиться этого с помощью package:angel_static, все, что вам нужно сделать, это заменить VirtualDirectory на CachingVirtualDirectory:

new CachingVirtualDirectory(same args...);

Если вы также хотели кэшировать ответы на стороне сервера, загляните в cacheResponses, экспортированный package:angel_multiserver:

configureServer(Angel app) async {
  await app.configure(new CachingVirtualDirectory(...));
  
  // Cache static assets server-side
  var rgxStatic = new RegExp(r'\.(html|js|jpg|png)$');
  await app.configure(cacheResponses(filters: [rgxStatic]));
}

Поддержка маршрутизации push-state

Вам повезло, если вы используете Angel в качестве бэкенда для одностраничного приложения. Даже если подключаемый модуль статического сервера автоматически выбрал для вас ваш веб-корневой каталог, вы все равно можете получить к нему доступ через свойство source и найти резервную страницу для обслуживания пользователей приложения с поддержкой push-состояния:

configureServer(Angel app) async {
  var vDir = new CachingVirtualDirectory();
  await app.configure(vDir);
  var indexPage = new File.fromUri(vDir.source.uri.resolve('index.html'));
  
  // Serve index.html instead of 404 page...
  app.after.add((req, res) => res.sendFile(indexPage);
}

Расширенные опции

И VirtualDirectory, и CachingVirtualDirectory поддерживают ряд дополнительных параметров в своих конструкторах, в том числе следующие три наиболее часто используемых:

Виртуальный корень

Во многих случаях вы захотите смонтировать статический сервер по другому пути. Например, если пользователь посещает assets/photos/logo.png, вы можете обслуживать web/photos/logo.png. В этом случае ваш статический сервер должен быть смонтирован по адресу /assets, а не по адресу /.

Чтобы справиться с этим относительно распространенным вариантом использования, используйте параметр publicPath:

new VirtualDirectory(publicPath: '/assets');

Разрешение индексного файла

По умолчанию, если пользователь запрашивает корень каталога, package:angel_static попытается обслужить файл index.html в этом каталоге и выдаст ошибку 404, если он не будет найден. Используйте параметр indexFileNames, чтобы переопределить это:

new VirtualDirectory(indexFileNames: ['index.txt', 'index.php']);

Потоковые ответы и обратные вызовы файлов

Как упоминалось выше, VirtualDirectory записывает содержимое обслуживаемых файлов в буфер ответа. Это прекрасно подходит для большинства сценариев, но для больших файлов вы часто можете столкнуться с этой ошибкой:

Unhandled exception:
  HttpException: Headers size exceeded the of '8192' bytes

Бороться с этим можно, заставив package:angel_static транслировать файлы в ответ вместо буферизации всего содержимого сразу:

new VirtualDirectory(streamToIO: true);

Потоковая передача файлов на IO пропустит все responseFinalizers, подключенные к вашему приложению, а это значит, что он не будет работать с package:angel_compress. Однако если streamToIO равно true, то все файлы будут автоматически сжаты с помощью GZIP.

Вывод

Благодаря расширенной поддержке статических файлов Angel, безусловно, является хорошим выбором для вашего следующего проекта на стороне сервера или полного стека. Однако не следуйте за ним — во фреймворке гораздо больше, чем просто package:angel_static. Идите вперед и исследуйте его для себя. Обратная связь очень ценится!

Ангел Вики

Документация по API

Общайтесь на Gitter!