Компиляция Angular 2 AoT с помощью Webpack

В этой статье я собираюсь объяснить, как включить компиляцию шаблона Angular 2 Ahead-of-Time (AoT) с Webpack 2, используя загрузчик @ngtools/webpack.

Компиляция шаблонов с опережением времени (AoT, также называемая автономной) приводит к меньшему размеру кода приложения и более быстрой начальной визуализации по сравнению с компиляцией шаблонов точно в срок (JiT, также называемой динамической). Если вы хотите получить более подробную информацию об этих двух параметрах, посмотрите Документацию по Angular. Кроме того, Тобиас Бош в этом докладе Компилятор Angular 2 дал очень интересное объяснение того, почему был представлен компилятор AoT.

Пакет @angular/compiler-cli предоставляет инструмент командной строки под названием ngc, который может выполнять компиляцию шаблонов, однако использование его с Webpack немного громоздко.

К счастью, теперь доступен загрузчик Webpack в виде пакета @ngtools/webpack, что значительно упрощает интеграцию с Webpack. Он был разработан для использования в Angular CLI, поэтому он является частью того же репозитория, но мы также можем использовать его для наших собственных проектов Webpack.

В качестве примера у меня есть очень простой проект Angular 2 Webpack в моем репозитории angular2-course-webpack-starter. Он основан на Webpack 1, текущей стабильной версии и не поддерживает компиляцию шаблонов AoT.

Для нетерпеливых, типа просто покажи мне код, тот же проект, но с поддержкой AoT, доступен в ветке webpack2-aot, и вот разница, показывающая соответствующие изменения, внесенные для включения AoT.

Теперь позвольте мне пройтись по этим изменениям. Прежде всего, нам нужно использовать Webpack 2, который сейчас находится в стадии бета-тестирования. В отличие от Webpack 1, Webpack 2 поддерживает модули ES2015 (также известные как модули ES6 или сокращенно ESM), и нам нужна эта функция, потому что компилятор шаблонов Angular выдает код с модулями es2015.

Вы можете установить бета-версию Webpack и его сервер разработки с помощью

npm install --save-dev webpack@beta webpack-dev-server@beta

Для обновления до Webpack 2 требуется несколько изменений в конфигурации Webpack в webpack.config.js. Например, resolve.extensions больше не требует и фактически отклонит, передав пустую строку. Также вы можете получить странное предупреждение о том, что Критическая зависимость: запрос зависимости является выражением, если только вы не добавите не менее непонятную конфигурацию модуля ContextReplacementPlugin. (Я уверен, что этому есть правильное объяснение, я просто не уверен, что это стоит моего времени, чтобы попытаться полностью понять это.)

Как только Webpack 2 снова заработает, мы можем добавить загрузчик @ngtools/webpack, а для этого также потребуются пакеты Angular compiler-cli и platform-server для выполнения компиляции шаблона:

npm install --save-dev @ngtools/webpack @angular/compiler-cli @angular/platform-server

Обратите внимание, что на момент написания этой статьи @ngtools/webpack имеет версию 1.1.2. Если вы используете более позднюю версию, всегда возможно, что что-то изменилось. (Если это так, дайте мне знать, и я обновлю приведенные ниже инструкции.)

Затем мы можем использовать @ngtools/webpack в webpack.config.js в качестве загрузчика для .ts файлов, заменив существующий загрузчик TypeScript, в моем случае ts-loader:

module: {
  loaders: [
    { test: /\.ts$/, loader: '@ngtools/webpack' },

Таким образом, загрузчик @ngtools/webpack также занимается компиляцией кода TypeScript (фактически он является оболочкой для компилятора TypeScript) при компиляции шаблона. Поскольку компиляция шаблонов Angular в любом случае требует синтаксического анализа кода TypeScript, более эффективно выполнять компиляцию TypeScript также в том же проходе.

Загрузчик также позаботится об автоматической перезаписи нашего кода начальной загрузки в main.ts, чтобы он вызывал bootstrapModuleFactory и не использовал platformBrowserDynamic, поэтому нет необходимости хранить два отдельных основных файла, один для JiT и один для AoT.

Однако, чтобы все это работало, нам также нужно добавить AotPlugin, экспортируемый пакетом @ngtools/webpack, в наш массив плагинов:

var ngToolsWebpack = require('@ngtools/webpack');
// ...
  plugins: [
    // ...
    new ngToolsWebpack.AotPlugin({
      tsConfigPath: './tsconfig.json',
      entryModule: './src/app/app.module#AppModule'
    })

AotPlugin ожидает параметр tsConfig, указывающий на файл конфигурации TypeScript, и хорошо также указать entryModule, то есть основной @NgModule для нашего приложения.

На этом этапе нам нужно немного изменить нашу конфигурацию tsconfig.json, указав компилятору TypeScript создавать код, включающий модули es2015. Такие модули могут быть лучше оптимизированы с помощью Webpack 2.

"compilerOptions": {
  "target": "es5",
  "module": "es2015",
  "moduleResolution": "node",
  "sourceMap": true

Может показаться странным ориентироваться на код es5, но с модулями es2015, однако это комбинация, поддерживаемая компилятором TypeScript. Затем Webpack позаботится о преобразовании модулей es2015 в код, который работает в любом веб-браузере, совместимом с es5.

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

На этом этапе вы должны быть в состоянии создать свое приложение с помощью AoT, например. используя производственные настройки

npm run build:prod

В моих тестах размер app.bundle.js увеличился с 524 КБ с Webpack 1 и JiT до 253 КБ с Webpack 2 и AoT. После сжатия gzip это становится 53 КБ, что довольно хорошо.

Это все очень хорошо, однако на данном этапе webpack-dev-server уже не будет работать должным образом. Я не смог найти способ заставить загрузчик @ngtools/webpack нормально работать с автоматическим обновлением. Я думаю, это связано с тем, что компиляция AoT происходит в два этапа: сначала он генерирует *.ngfactory.ts файла для каждого шаблона Angular, а затем компилирует весь код.

Суть в том, что мне пришлось настроить конфигурацию Webpack, чтобы использовать AoT только для производственных сборок и придерживаться JiT для сборок разработки, в том числе для сервера разработки. Я использую переменную среды с именем APP_ENVIRONMENT, чтобы указать, какой это тип сборки, поэтому я использую ту же переменную, чтобы решить, использовать ли загрузчик @ngtools/webpack и AotPlugin или ts-loader вместе с angular2-template-loader для Сборка шаблона JiT.

В очередной раз вы можете найти полный рабочий пример в этом репозитории.

Нравится:

Нравится Загрузка…

Связанный

Первоначально опубликовано на labs.encoded.io 24 октября 2016 г.