Angular + AOT + Webpack + NgTools - проблема создания ngFactory

Я пытался настроить AOT с помощью ngTools, работающего в моем приложении Angular (с использованием Webpack для загрузки модуля), и у меня был абсолютный кошмар этого времени. Я просмотрел различные ресурсы в документации здесь и здесь, а также прочтите файл readme ngTools , посмотрел на пример, скрытый внутри Angular CLI (это приложение не было построено с Angular CLI, но я подумал, что это будет по крайней мере полезная ссылка), найденный через этот ресурс на Angular + Webpack + Sass + ngTools (я использую SASS тоже, но он отлично компилируется с моим webpack.config.aot.js - хотя он блокирует мне переход на ngc, по крайней мере, насколько я обнаружил, это то, что я видел в некоторых примерах), а также все проблемы с github или сообщения stackoverflow, которые я обнаружил за последние несколько дней, и независимо от того, что я делаю, пытаясь создать, aot производит следующая ошибка:

 ERROR in window is not defined

 ERROR in /Users/nataliecoley/development/company-app-name/src/main-aot.ts (2,36): Cannot find module '../aot/src/app/app.module.ngfactory'.

 ERROR in ./src/main-aot.ts

Модуль не найден: ошибка: не удается разрешить '../aot/src/app/app.module.ngfactory' в '/ Users / nataliecoley / development / company-app-name / src' @ ./src/main- aot.ts 2: 0-73

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

Второе и третье сообщения об ошибках, хотя я думаю, являются основным источником моих проблем, поскольку довольно ясно, что app.module.ts не компилируется до main-aot.ts, поэтому к тому времени, когда main-aot.ts идет на компиляцию, он не может найти файл. Однако я настроил его в соответствии с документацией, которую я нашел специально, чтобы он был уже скомпилирован и app.module.ngfactory готов к работе, когда компилятор достигнет main-aot.ts.

Ясно, что в моей настройке чего-то не хватает, и поскольку каждое решение, которое я нахожу в Интернете, настроено немного по-другому, я не могу сузить проблему. Все, что я знаю, это то, что ничего из того, что я пробовал до сих пор, не удаляет эту ошибку (или не вызывает любую другую новую ошибку), и мне нужна помощь от любого, кто успешно установил AOT + ngTools + webpack + Angular, чтобы сузить кругозор. здесь.

Вот моя файловая структура (упрощенная):

.
+-- config/
|   +-- helpers.js
|   +-- webpack.common.js
|   +-- webpack.dev.js
|   +-- webpack.prod.js
+-- src/
|   +-- app/
|   +-- assets/
|   +-- vendor/
|   +-- index.html
|   +-- main.ts
|   +-- main-aot.ts
|   +-- polyfills.ts
|   +-- tsconfig.json
+-- package.json
+-- server.js
+-- tsconfig-aot.json
+-- webpack.config.aot.js
+-- webpack.config.js (only contains: module.exports = require('./config/webpack.dev.js');)

Команда, которую я использую для запуска моей сборки aot (которую я вытащил из настройки в первой ссылке, которую я поделился с документами angular), - это "build:aot": "webpack --config webpack.config.aot.js", в моем package.json. Что касается соответствующих версий пакетов, я использую 4.1.0 для всех пакетов angular, и я использую @ngtools/webpack v1.3.1, webpack v 2.3.3 и typescript v2.3.0

Примечание: я видел некоторые проблемы, возникающие в отношении aot и некоторых версий typescript / angular, но мы действительно хотели бы частично придерживаться их, чтобы оставаться в соответствии с нашим другим приложением Angular (в производстве уже более года и в настоящее время на v4. 1.0 без интереса к понижению), а также для таких вещей, как поддержка strictnullchecks и т. Д. Я знаю, что слышал о людях, заставляющих AOT работать с этими версиями, и кажется смешным, что кому-то пришлось бы работать со старой версией Angular просто чтобы использовать AOT, поэтому я чувствую, что должен быть способ заставить его работать.

Вот мой tsconfig-aot.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "es2015",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [ "es2015", "dom" ],
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true,
    "removeComments": false,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "strictNullChecks": true,
    "skipLibCheck": true,
    "skipCodeGeneration": false,
    "typeRoots": [
      "../node_modules/@types/"
    ]
 },
  "files": [
    "src/app/app.module.ts",
    "src/main-aot.ts"
  ],
  "compileOnSave": true,
  "angularCompilerOptions": {
    "genDir": "aot",
    "entryModule": "src/app/app.module#AppModule",
    "skipMetadataEmit": true
  }
}

Вот мой webpack.config.aot.js:

const ngtools = require('@ngtools/webpack');
const webpack = require('webpack');
const helpers = require('./config/helpers');


module.exports = {
  devtool: 'source-map',
  entry: {
    main: './src/main-aot.ts'
  },
  resolve: {
     extensions: ['.ts', '.js']
  },
  target: 'node',
  output: {
    path: helpers.root('dist'),
    filename: 'build.js'
  },
  plugins: [
    new ngtools.AotPlugin({
      tsConfigPath: helpers.root('tsconfig-aot.json'),
      entryModule: helpers.root('src', 'app', 'app.module#AppModule')
    }),
    new webpack.optimize.UglifyJsPlugin({ sourceMap: true })
  ],
  module: {
    rules: [
      {
         test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
         loader: 'file-loader?name=assets/[name].[hash].[ext]'
      },
      { test: /\.css$/, loader: 'raw-loader' },
      {
        test: /\.scss$/,
        loaders: ['to-string-loader', 'style-loader', 'css-loader', 'resolve-url-loader', 'sass-loader?sourceMap']
      },
      { test: /\.html$/, loader: 'raw-loader' },
      { test: /\.ts$/, loader: '@ngtools/webpack' }
    ]
  }
}

Замечание о файле entryModule. В некоторых ресурсах, которые я видел, говорится, что параметр entryModule должен быть в tsconfig-aot.json, а не в webpack.config.aot.js, другие примеры, которые я видел, помещают его только в webpack.config.aot.js. Я пробовал использовать его только в tsconfig-aot.json, только в webpack.config.aot.js и выше в обоих - ни один из этих вариантов, похоже, не решает проблему. Я также пробовал редактировать пути к файлам различных вещей (например, массив файлов в моем tsconfig-aot.json) на случай, если я настроил его так, чтобы он смотрел не в том месте для моих файлов и ни к чему не пришел.

Вот мой main-aot.ts:

import { platformBrowser }    from '@angular/platform-browser';
import { AppModuleNgFactory } from '../aot/src/app/app.module.ngfactory';

platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);

Я боюсь, что это будет просто глупый кусок, который я пропустил, но я пробовал все до сих пор, и кажется, что многие другие люди в Интернете также борются с этой настройкой, и, похоже, нет никаких ясная информация в Интернете о том, как это сделать правильно, поэтому я решил опубликовать здесь в надежде, что кто-то, кто действительно успешно не работает в приложении Angular + Webpack, может указать мне в правильном направлении или поделиться ресурсом, который помог им понять это из. Заранее спасибо!


person NColey    schedule 03.05.2017    source источник
comment
Привет, @Aluan Haddad, я немного не понимаю, что вы имеете в виду? Я пишу на машинописном тексте, приложение, которое я пытаюсь подготовить для AOT, - это приложение Angular + Typescript. У меня также сложилось впечатление, что AOT рекомендовали в сообществе Angular лучше согласовываться с процессом сборки Google. Мы также хотели бы использовать его для таких вещей, как производительность и уменьшенный размер пакета. Не могли бы вы прояснить, что вы имеете в виду, говоря, что моя IDE лжет мне? Я не указал, какую IDE я использовал, и, честно говоря, я не совсем понимаю ваш комментарий. Спасибо.   -  person NColey    schedule 04.05.2017
comment
AOT не следует семантике машинописного текста. TypeScript - это надмножество ECMAScript. Декораторы, реализованные в TypeScript, основаны на предложении декораторов ECMAScript. AOT нарушает смысл декораторов, что несовместимо с семантикой TS и ES.   -  person Aluan Haddad    schedule 04.05.2017
comment
Я ценю ваше продолжение @AluanHaddad, но насколько я понимаю, есть ряд людей, которые успешно заставили AOT работать с Angular и Typescript. Я собираюсь продолжить поиск решения моих проблем с установкой и, надеюсь, придет кто-нибудь, кто поможет мне отладить проблему, которая привела к моему исходному вопросу, размещенному здесь. Спасибо, в любом случае.   -  person NColey    schedule 04.05.2017
comment
Удачи вам, только помните, что это не машинописный текст   -  person Aluan Haddad    schedule 04.05.2017
comment
Удалось ли вам это исправить? У меня похожая проблема.   -  person jvhang    schedule 22.05.2017


Ответы (2)


Обратите внимание, с вашего ресурса:

У меня возникли проблемы с путем к коду ngfactory при компиляции с помощью ngc: Can't resolve './../path/to/app/app.module.ngfactory' Кажется, это связано с этой проблемой. Для меня решением было определить genDir в конфигурации webpack, а не в файле tsconfig.js.

Однако ngtools делает все это за вас, поскольку он задуман как полный механизм AOT черного ящика. Вы смешиваете ngc (т.е. поколение ngfactory) с интерфейсом AOT Angular CLI (ngtools).

Если вы хотите использовать ngfactories, вам нужно создать приложение с ngc. Лично я использую ngtools для разработки, а затем использую ngc вместе с серверным рендерером Angular Universal.

Обратите внимание, что ngtools имеет ошибку, которая делает разработку довольно болезненной - изменения не будут распознаны до второй перекомпиляции: https://github.com/angular/angular-cli/issues/5137

Как я использую это оборудование?

Мои конфигурации веб-пакетов во многом такие же, как и ваши, а затем я использую ngc в производственной сборке для создания фабрик ...

package.json:

"aot": "./node_modules/.bin/ngc -p tsconfig-aot.json",

И использовать фабрики вместе с рендерингом на стороне сервера ...

server.ts:

import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { renderModuleFactory } from '@angular/platform-server'
import { enableProdMode } from '@angular/core'
import { AppServerModuleNgFactory } from './dist/ngfactory/src/app/app.server.module.ngfactory'
import * as express from 'express';
import { readFileSync } from 'fs';
import { join } from 'path';

const PORT = process.env.PORT || 8081;

enableProdMode();

const app = express();

let template = readFileSync(join(__dirname, 'dist', 'index.html')).toString();

app.engine('html', (_, options, callback) => {
  const opts = { document: template, url: options.req.url };

  renderModuleFactory(AppServerModuleNgFactory, opts)
    .then(html => callback(null, html));
});

app.set('view engine', 'html');
app.set('views', 'src')

app.get('*.*', express.static(join(__dirname, 'dist')));

app.get('*', (req, res) => {
  res.render('index', { req });
});

app.listen(PORT, () => {
  console.log(`listening on http://localhost:${PORT}!`);
});
person William Lahti    schedule 07.05.2017

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

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

TypeScript (как и tsconfig.json) играет ключевую роль в сборках Angular ...

ПРИМЕЧАНИЕ. Только ANGULAR 4.

Вы можете посмотреть это видео Angular-CLI, но оно вам также не поможет. многое, чтобы понять настройку сборки с помощью Webpack ...

Прежде всего, несколько ключевых моментов, которые следует помнить при создании собственной системы сборки с использованием Webpack:

  • Номера версий для библиотек Typescript / Angular очень важны, проверьте Angular Upgrade, чтобы найти подходящую версию. Номера для вашей сборки. Я предлагаю использовать точные версии сборки Angular v4.4 и Typscript v2.5.3.
  • Загрузите последнюю версию @ ngtools / webpack с NPM
  • Имейте соответствующий файл конфигурации для tsconfig.json для сборок AOT ...
  • Импорт в ваших приложениях должен использовать относительные пути или использовать index.ts Бочки (хотя использование бочек очень сбивает с толку, у меня у меня ушел целый день :()

Есть два основных способа получить сборки AOT из Webpack:

  • Во-первых, с помощью командного инструмента Angular-CLI ngc -p tsconfig.json
  • Во-вторых, использовать Angulars Official @ ngtools / webpack v ^ 1.7.0. Последние версии NgTools - довольно хорошие загрузчики, но для старых сборок Angular (то есть версий Angular ниже 4) лучше использовать ngc-webpack, в качестве загрузчика (хотя я никогда не пробовал этот загрузчик, но его тщательная документация очень помогла мне понять компиляции Angular AOT) ...

ПЕРВЫЙ СПОСОБ (I):

Ознакомьтесь с этим руководством на Youtube, чтобы понять настройку ...

TL; DR; (Необходимые списки файлов можно найти здесь)

  1. Создайте bootstrap.aot.ts файл в исходном каталоге: bootstrap.aot.ts
  2. Создайте правильный tsconfig-aot.json файл: tsconfig-aot.json
  3. Настройте ur webpack.config.js для AOT, я буду показывать только образец, а не весь файл ... Следующий файл - это webpack.prod.js и объединяется в webpack.common.js
  4. Настройка ur package.json скриптов для синхронного запуска, несколько команд, которые помогут сгенерировать сборку ... package.json

    npm run start:prod:test, это команда, которая вам нужна сверху для создания сборки AOT ... Объяснение:

    1. Clean All Build Directories...
    2. Скопируйте ur src / files для сборки /
    3. Сгенерируйте CSS из SASS, это основная проблема с ngc, хотя в документах говорится, что они поддерживают SASS / LESS, но пока нет, по крайней мере, не правильно ...
    4. Измените ТЕКСТ внутреннего файла '.scss' на '.css', ./config/replace-scss.js выглядит следующим образом:
  5. Создайте файлы * .ngfactory.ts. Сгенерированные файлы переходят в папку dist /, которую решает tsconfig.json. Здесь путь к файлам ngfactory имеет решающее значение для bootstrap.aot.ts. Если здесь возникает ошибка, не забудьте проверить структуру папок ....

Мой здесь был:

/
|---src/                             // Main Source Folder
    |---bootstrap.aot.ts
|---build/                           // Copied files and Sass->Css in here
|---dist/
  1. Запустите Webpack Build с загрузчиками машинописных текстов, так как до сих пор ngc выполнил компиляцию AOT ...

ПРИМЕЧАНИЕ. Этот метод довольно хакерский и может сломаться. Второй способ больше подходит для работы.

ВТОРОЙ МЕТОД (II):

НЕОБХОДИМО не забыть установить относительный импорт пути ... Путь к *.ngfactory.ts должен быть правильным, проверьте выше 5. пункт

Для bootstrap.aot.ts, tsconfig-aot.json никаких изменений не требуется (хотя в tsconfig теперь мы можем удалить свойство files)

webpack.prod.ts

package.json

Кроме того, подтвердите свои версии Angular, ngtools и typescript ... Мои были

"@angular/animations": "~4.4.4",
"@angular/common": "~4.4.4",
"@angular/compiler": "~4.4.4",
"@angular/core": "~4.4.4",
"@angular/forms": "~4.4.4",
"@angular/http": "~4.4.4",
"@angular/platform-browser": "~4.4.4",
"@angular/platform-browser-dynamic": "~4.4.4",
"@angular/router": "~4.4.4",
"core-js": "^2.5.1",
"immutable": "^3.8.2",
"rxjs": "^5.4.3",
"zone.js": "~0.8.18"
"@angular-devkit/build-optimizer": "^0.0.32",
"@angular/cli": "^1.5.5",
"@angular/compiler-cli": "^4.4.4",
"@ngtools/webpack": "^1.7.0",
"@types/jasmine": "2.5.45",
"@types/jquery": "^3.2.15",
"@types/node": "~6.0.60",
"angular2-template-loader": "^0.6.2",
"autoprefixer": "^7.1.4",
"awesome-typescript-loader": "^3.2.3",
"chalk": "^2.3.0",
"clean-webpack-plugin": "^0.1.16",
"codelyzer": "~4.0.1",
"compodoc": "0.0.41",
"concurrently": "^3.5.1",
"copy-webpack-plugin": "^4.0.0",
"cpx": "^1.5.0",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"extract-text-webpack-plugin": "^3.0.1",
"file-loader": "^0.11.2",
"html-webpack-plugin": "^2.30.1",
"node-sass": "^4.5.3",
"npm-run-all": "^4.1.1",
"postcss": "^5.2.11",
"postcss-loader": "^1.2.2",
"progress-bar-webpack-plugin": "^1.10.0",
"raw-loader": "^0.5.1",
"replace": "^0.3.0",
"rimraf": "^2.6.2",
"sass-loader": "^6.0.6",
"source-map-loader": "^0.2.1",
"style-loader": "^0.18.2",
"to-string-loader": "^1.1.5",
"ts-node": "~3.0.4",
"tslint": "~5.3.2",
"tslint-loader": "^3.5.3",
"typescript": "~2.5.3",
"uglify-js": "^3.0.28",
"webpack": "^3.8.1",
"webpack-bundle-analyzer": "^2.9.1",
"webpack-combine-loaders": "^2.0.3",
"webpack-dev-server": "^2.9.3",
"webpack-merge": "^4.1.0",
"webpack-notifier": "^1.5.0"

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

Я надеюсь, что это помогло вам, если у вас все еще есть проблема, вы можете предоставить образец репо, чтобы воспроизвести проблему.

Дополнительные ссылки: (которые, я думаю, вы уже изучили, но могут быть полезны для кого-то еще, но все они являются репозиториями, кому-то придется просмотреть там источники, чтобы понять, что происходит)

Угловой 5

Я пробовал, но получал эту проблему, которая все еще остается открытой. Хотя есть Hack для работы над этим, но я не могу связываться с производственными сборками.

Будет обновлять ответ, когда я получу более подробную информацию.

Вышеупомянутая ссылка приведет вас к дополнительным ссылкам: P

person phoenisx    schedule 03.12.2017