У меня было две проблемы. Во-первых, мы не используем 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.
Итак, вот оно! Я надеюсь, что вы найдете это полезным, и дайте мне знать, если вы найдете еще лучший способ включения переводов.