У меня было две проблемы. Во-первых, мы не используем SystemJS. Во-вторых, мы использовали UpgradeAdapter для начальной загрузки углового гибридного приложения 1 + 2.

В то время как все руководства по Angular используют SystemJS, angular-cli использует Webpack, и мы выбрали именно этот инструмент. Так что getTranslationsWithSystemJS нужно переписать как что-то, что использует веб-пакет, и в итоге получится следующее:

[code lang=”javascript”]
function getTranslationFilesWithWebpack(locale: string) {
return System.import('./assets/locale/messages.' + locale + '.xlf')
>
[/код]

Не так уж и плохо, да? Но для этого также требуется поддержка webpack, поэтому в webpack.config.js мне пришлось добавить правило для обработки файлов xlf:

[code lang=”javascript”]
function webpackConfig(options) {
return {
devtool: false,
resolve: {
extensions: ['.ts' , '.js']
},
контекст: __dirname,
запись: {
main: './src/main'
},
вывод: {
путь: 'dist',
имя файла: '[имя].bundle.js',
sourceMapFilename: '[имя].map',
chunkFilename: ' [имя].chunk.js',
publicPath: '/static/teachers-site/dist/'
},
модуль: {
правила: [
/* правила html, css и ts удалены для краткости */
{
test: /\.xlf/,
loader: 'raw'
},
{
test: /\.json|\.map$/,
loader: 'ignore-loader'
}
]
}
};< br /> }
module.exports = webpackConfig;
[/code]

Есть один ключевой компонент:

[code lang="javascript"]
{
test: /\.xlf/,
loader: ‘raw’
},
[/code]

Это правило указывает веб-пакету, что любые файлы xlf, с которыми он сталкивается, должны быть вставлены как необработанный текст. Использование System.import('path...' + filename) указывает веб-пакету создать точку разделения для файлов в path и позволит импортировать их по требованию в качестве обещания. (Эта функция появилась в Webpack 2.)

В итоге мы получим что-то подобное в нашем каталоге dist:

  • main.bundle.js, содержащий наш веб-сайт
  • n.chunk.js, где n начинается с 0 и рассчитывается для каждого имеющегося xlf.

(Примечание: нам, вероятно, следует найти способ переименовать куски)

Мне пришлось сделать еще два важных, но тонких изменения:

Во-первых, мне пришлось добавить publicPath: "/static/teachers-site/dist" в раздел вывода. Без этого наше веб-приложение попыталось бы загрузить фрагменты с https://host/teachers-site/0.chunk.js, и мы получили бы запутанную страницу ошибки 404, которая отправила бы среду выполнения окружающая среда кричит.

Во-вторых, я должен был сообщить webpack, как обрабатывать другие файлы, которые он мог найти. Оказывается, когда веб-пакет находит вызов System.import, он анализирует любой файл проекта, который может быть возможным разрешением, включая конфигурации, карту и другие вещи.

Но как вы гибридизируете?

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

[code lang=”javascript”]
// ЭТО НЕ РАБОТАЛО!!!
// app.module.ts
import { NgModule, forwardRef } from '@angular/core' ;
импортировать { BrowserModule } из '@angular/platform-browser';
импортировать { UpgradeAdapter } из '@angular/upgrade';
импортировать { AppComponent } из './app.component ';
импортировать {SharedModule} из «./shared/shared.module»;

export const upgradeAdapter = new UpgradeAdapter(
forwardRef(() =› AppModule ));

объявить var angular: any;
angular
.module('rootModule')
.directive('testAngularTwo',
upgradeAdapter.downgradeNg2Component(AppComponent));

@NgModule({
импортирует: [BrowserModule, SharedModule],
объявления: [AppComponent],
начальную загрузку: [AppComponent]
})
экспортирует класс AppModule{}

// main.ts
import ‘./polyfills.ts’;

импортировать {upgradeAdapter} из ‘./app/app.module’;
объявить var document: any;
upgradeAdapter.bootstrap(document, [‘rootModule’]);
[/code]

Я просто не мог понять, как передать провайдеров перевода функции начальной загрузки angular 2! Я просмотрел документы, и, к моему большому удивлению, все они говорили что-то UpgradeModule. Очень запутанно.

Оказывается, в Angular 2.2.1 механизм обновления был полностью переработан. Или, по крайней мере, его общедоступный API. Поэтому я обновился до 2.2.1 и повторно реализовал механизм обновления, используя новые рекомендации:

[code lang="javascript"]
// app.module.ts
импортировать {NgModule} из "@angular/core";
импортировать {BrowserModule} из "@angular/platform- браузер»;
импортировать {AppComponent} из «./app.component»;
импортировать {UpgradeModule} из «@angular/upgrade/src/aot/upgrade_module»;
импортировать {downgradeComponent} из «@angular/upgrade/src/aot/downgrade_component»;

@NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
объявления: [AppComponent],
entryComponents: [AppComponent]
})
экспорт класса AppModule {
ngDoBootstrap() {}
}

объявить var angular: any;
angular
.module('slateClient')
.directive('testAngularTwo', downgradeComponent({
компонент: AppComponent
})) ;

// main.ts
импортировать "./polyfills.ts";
импортировать {AppModule} из "./app/app.module";
импортировать {getTranslationProviders} из "./i18n" -providers»;
импортировать {platformBrowserDynamic} из «@angular/platform-browser-dynamic»;
импортировать {UpgradeModule} из «@angular/upgrade/src/aot/upgrade_module»;

объявить var document: any;
объявить var console: any;
getTranslationProviders().then(providers =› {
const options = {providers};
return platformBrowserDynamic(). bootstrapModule(AppModule, options);
})
.then(ref =› {
const upgrade = ref.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap( document.body, ['slateClient'], {strictDi: true});
})
.catch(console.log.bind(console, «Ошибка начальной загрузки: «))
[ /код]

Ах-ха! Наконец, это сработало!

Но что происходит?

В app.module.ts я использовал UpgradeModule в качестве одного из импортируемых модулей, а также удалил раздел bootstrap: [AppComponent]. Этот последний бит важен! Наше приложение на самом деле загружается Angular 2, вызывая Angular 1, который, в свою очередь, использует компоненты Angular 2, поэтому Angular 2 не должен сам загружать какой-либо компонент! Вместо этого нам нужно поместить наши компоненты в entryComponents.

В main.ts мы просто запрашиваем провайдеров перевода, затем (объединение промисов, см. мой пост о промисах) загружаем Angular 2, как обычно. Этот процесс начальной загрузки также возвращает промис, поэтому мы связываемся с ним, чтобы загрузить Angular 1, используя UpgradeModule, который мы внедрили в наш AppModule.

Наконец, обратите внимание на .catch(console.log.bind(console, "Bootstrap Failed: ")) в конце main.ts. Это оказалось чрезвычайно ценным, поскольку я пытался понять, почему я не могу запустить angular.

Итак, вот оно! Я надеюсь, что вы найдете это полезным, и дайте мне знать, если вы найдете еще лучший способ включения переводов.