У меня проблемы с твио.
Во-первых, я не могу передать queryParam из server.ts в AppCompoment.ts.
Во-вторых, служба translateService выдает ОШИБКУ [Ошибка] без сообщения, когда выполняется на сервере, но работает нормально, когда выполняется в браузере.
Вот код частей проекта:
server.ts
// These are important and needed before anything else
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
import { renderModuleFactory } from '@angular/platform-server';
import { enableProdMode } from '@angular/core';
import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
(global as any).WebSocket = require('ws');
(global as any).XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
//app.urlencoded({extended: false});
const PORT = process.env.PORT || 4000;
const HTTPS_PORT = process.env.HTTPS_PORT || 4443;
const KEY_CERTIFICATE = process.env.KEY_CERTIFICATE;
const CRT_CERTIFICATE = process.env.CRT_CERTIFICATE;
const PASSWORD_CERTIFICATE = process.env.PASSWORD_CERTIFICATE;
const DIST_FOLDER = join(process.cwd(), 'dist');
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
// Express Engine
import { ngExpressEngine } from '@nguniversal/express-engine';
// Import module map for lazy loading
import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Our page routes
export const routes: string[] = [
'main',
'dashboard',
'dashboard/contact',
'dashboard/blog'
];
// All regular routes use the Universal engine
app.get('/', (req, res) => {
console.time(`GET: ${req.originalUrl}`);
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req, res } );
console.timeEnd(`GET: ${req.originalUrl}`);
});
routes.forEach(route => {
app.get(`/${route}`, (req, res) => {
//res.json({'lang': req.query.lang});
console.log(req.query.lang);
console.time(`GET: ${req.originalUrl}`);
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req, res } );
console.timeEnd(`GET: ${req.originalUrl}`);
});
app.get(`/${route}/*`, (req, res) => {
//res.json({'lang': req.query.lang});
console.log(req.query.lang);
console.time(`GET: ${req.originalUrl}`);
res.render(join(DIST_FOLDER, 'browser', 'index.html'), { req, res } );
console.timeEnd(`GET: ${req.originalUrl}`);
});
});
// Server static files from /browser
app.get('/web', express.static(join(DIST_FOLDER, 'browser'), { 'index': false }));
app.get('/**', express.static(join(DIST_FOLDER, 'browser')));
// All other routes must be resolved if exist
/*
app.get('*', function(req, res) {
res.render(join(req.url), { req });
});
*/
var http = require('http');
var httpServer = http.createServer(app);
// Start up the Node server at PORT
httpServer.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
if(KEY_CERTIFICATE && CRT_CERTIFICATE && PASSWORD_CERTIFICATE) {
var fs = require('fs');
var https = require('https');
var privateKey = fs.readFileSync(KEY_CERTIFICATE, 'utf8');
var certificate = fs.readFileSync(CRT_CERTIFICATE, 'utf8');
var credentials = {
key: privateKey,
cert: certificate,
passphrase: PASSWORD_CERTIFICATE
};
var httpsServer = https.createServer(credentials, app);
// Start up the Node server at HTTP_PORT
httpsServer.listen(HTTPS_PORT, () => {
console.log(`Node server listening on http://localhost:${HTTPS_PORT}`);
});
}
AppServerModule.ts
import { NgModule } from '@angular/core';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
import { AppModule } from './app.module';
import { TemplateComponent } from '../template/template.component';
@NgModule({
imports: [
// The AppServerModule should import your AppModule followed
// by the ServerModule from @angular/platform-server.
AppModule,
ServerModule,
ModuleMapLoaderModule, // <-- *Important* to have lazy-loaded routes work
ServerTransferStateModule,
],
// Since the bootstrapped component is not inherited from your
// imported AppModule, it needs to be repeated here.
bootstrap: [TemplateComponent],
})
export class AppServerModule {
constructor() {
console.log('AppServerModule');
}
}
AppModule:
import { NgModule } from '@angular/core';
import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { enableProdMode } from '@angular/core';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
// Routing
import { Router } from '@angular/router';
import { RouterModule, Routes } from '@angular/router';
// Firebase
import { AngularFireModule } from 'angularfire2';
import { environment } from '../../environments/environment';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuthModule } from 'angularfire2/auth';
import { AuthService } from '../firebase-auth/auth.service';
import { FirebaseAuthComponent } from '../firebase-auth/firebase-auth.component';
// My Components
import { TemplateComponent } from '../template/template.component';
import { MainComponent } from '../main/main.component';
import { BlogComponent } from '../blog/blog.component';
import { ProjectsComponent } from '../projects/projects.component';
import { ProjectComponent } from '../project/project.component';
import { FormComponent } from '../form/form.component';
import { DashboardComponent } from '../dashboard/dashboard.component';
import { DashboardBlogComponent } from '../dashboard/dashboard-blog.component';
import { DashboardContactComponent } from '../dashboard/dashboard-contact.component';
import { ExperienceComponent } from '../experience/experience.component';
import { ProjectService } from '../projects/project.service';
import { ExperienceService } from '../experience/experience.service';
import { PipesModule } from '../pipes/pipes.module';
import { LanguageService } from '../template/language.service';
const appRoutes: Routes = [
{
path: 'main',
component: MainComponent
},
{
path: 'blog',
component: BlogComponent
},
{
path: 'dashboard',
component: DashboardComponent,
children: [
{
path: '',
redirectTo: 'blog',
pathMatch: 'full'
},
{
path: 'blog',
component: DashboardBlogComponent
},
{
path: 'contact',
component: DashboardContactComponent
}
]
},
{
path: '',
redirectTo: '/main',
pathMatch: 'prefix'
},
{
path: '**',
redirectTo: '/main',
pathMatch: 'prefix'
}
];
@NgModule({
declarations: [
FirebaseAuthComponent,
MainComponent,
BlogComponent,
TemplateComponent,
ProjectsComponent,
ProjectComponent,
FormComponent,
DashboardComponent,
DashboardBlogComponent,
DashboardContactComponent,
ExperienceComponent,
],
imports: [
BrowserModule.withServerTransition({appId: 'davidmartinezros.com'}),
BrowserTransferStateModule,
FormsModule,
ReactiveFormsModule,
HttpModule,
HttpClientModule,
RouterModule.forRoot(appRoutes),
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
PipesModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
providers: [AuthService, AngularFireDatabase, BlogComponent, DashboardContactComponent, ProjectService, ExperienceService, LanguageService],
bootstrap: [TemplateComponent] // main (first) component
})
export class AppModule {
constructor() {
console.log('AppModule');
}
}
/*
if (!/localhost/.test(document.location.host)) {
enableProdMode();
}
*/
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
TemplateComponent.ts:
import { Component, ViewChild, ElementRef, Inject } from '@angular/core';
import { ActivatedRoute, RouterModule } from '@angular/router';
import { AuthService } from '../firebase-auth/auth.service';
import { TranslateService } from '@ngx-translate/core';
import { ProjectsComponent } from '../projects/projects.component';
import { ExperienceComponent } from '../experience/experience.component';
import { LanguageService } from './language.service';
import { Pipe } from '@angular/core';
import { Language } from './language';
import { Title, Meta } from '@angular/platform-browser';
import { PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
@Component({
selector: 'app-template',
templateUrl: '../template/template.component.html'
})
export class TemplateComponent {
objectKeys = Object.keys;
languages: Language[];
language;
loaded: boolean = false;
playing: boolean = false;
sound: any;
constructor(@Inject(PLATFORM_ID) private platformId: Object,
public authService: AuthService,
private translate: TranslateService,
private route: ActivatedRoute,
private languageService: LanguageService,
private titleService: Title,
private metaService: Meta) {
this.getLanguanges();
}
ngOnInit() {
if (isPlatformBrowser(this.platformId)) {
// Client only code.
this.loadLanguage();
this.loadMusic();
}
if (isPlatformServer(this.platformId)) {
// Server only code.
this.loadServerLanguage();
}
}
loadMusic() {
this.sound = new Audio();
this.sound.autoplay = false;
this.sound.preload = 'auto';
this.sound.autobuffer = true;
let parent = this;
this.sound.addEventListener('loadeddata', function() {
parent.loaded = true;
}, false);
this.sound.addEventListener('play', function() {
parent.playing = true;
}, false);
this.sound.addEventListener('pause', function() {
parent.playing = false;
}, false);
this.sound.src = './assets/audio/Rhodesia_MkII.mp3';
this.sound.load();
}
loadLanguage() {
var userLang = "";
//console.log(this.route);
console.log(this.route.queryParams);
this.route.queryParams.subscribe(params => {
if(!params['lang'] || params['lang'] == "") {
userLang = this.language;
} else {
userLang = params['lang'];
}
console.log("queryParams:" + userLang);
if(!userLang || userLang == "") {
userLang = navigator.language;
if(userLang.startsWith("zh")) {
userLang = "zh";
}
}
if(userLang) {
userLang = userLang.toLowerCase();
}
if(userLang && userLang.length > 2) {
userLang = userLang.substring(0,2);
}
if(userLang == "es" || userLang == "en" || userLang == "zh") {
this.changeLanguage(userLang);
} else {
this.changeLanguage("en");
}
console.log('complete loadLanguage');
});
}
loadServerLanguage() {
var userLang = "";
//console.log(this.route);
console.log(this.route.queryParams);
this.route.queryParams.subscribe(params => {
if(!params['lang'] || params['lang'] == "") {
userLang = this.language;
} else {
userLang = params['lang'];
}
console.log("queryParams:" + userLang);
if(userLang) {
userLang = userLang.toLowerCase();
}
if(userLang && userLang.length > 2) {
userLang = userLang.substring(0,2);
}
if(userLang == "es" || userLang == "en" || userLang == "zh") {
this.changeLanguage(userLang);
} else {
this.changeLanguage("en");
}
console.log('complete loadLanguage');
});
}
isLoadedTrack() {
return this.loaded;
}
isPlayingTrack() {
return this.playing;
}
playTrack() {
if(this.sound) {
this.sound.play();
}
}
pauseTrack() {
if(this.sound) {
this.sound.pause();
}
}
public changeServerLanguage(language) {
console.log(language);
console.log("Ara anem a cridar a this.translate.setDefaultLang(language); que al servidor dona error.");
// this language will be used as a fallback when a translation isn't found in the current language
this.translate.setDefaultLang(language);
// the lang to use, if the lang isn't available, it will use the current loader to get them
this.translate.use(language);
this.language = language;
// Sets the <title></title>
this.translate.get("TitleIndex")
.toPromise()
.then(title => this.titleService.setTitle(title))
.catch(this.handleError);
// Sets the <meta> tag author
this.translate.get("TagAuthorIndex")
.toPromise()
.then(author => this.metaService.updateTag({ name: 'author', content: author }))
.catch(this.handleError);
// Sets the <meta> tag keywords
this.translate.get("TagKeywordsIndex")
.toPromise()
.then(keywords => this.metaService.updateTag({ name: 'keywords', content: keywords }))
.catch(this.handleError);
// Sets the <meta> tag description
this.translate.get("TagDescriptionIndex")
.toPromise()
.then(description => this.metaService.updateTag({ name: 'description', content: description }))
.catch(this.handleError);
console.log('changeServerLanguage');
}
public changeLanguage(language) {
console.log(language);
// this language will be used as a fallback when a translation isn't found in the current language
this.translate.setDefaultLang(language);
// the lang to use, if the lang isn't available, it will use the current loader to get them
this.translate.use(language);
this.language = language;
ProjectsComponent.updateStuff.next(false);
ExperienceComponent.updateStuff.next(false);
this.getLanguanges();
// Sets the <title></title>
this.translate.get("TitleIndex")
.toPromise()
.then(title => this.titleService.setTitle(title))
.catch(this.handleError);
// Sets the <meta> tag author
this.translate.get("TagAuthorIndex")
.toPromise()
.then(author => this.metaService.updateTag({ name: 'author', content: author }))
.catch(this.handleError);
// Sets the <meta> tag keywords
this.translate.get("TagKeywordsIndex")
.toPromise()
.then(keywords => this.metaService.updateTag({ name: 'keywords', content: keywords }))
.catch(this.handleError);
// Sets the <meta> tag description
this.translate.get("TagDescriptionIndex")
.toPromise()
.then(description => this.metaService.updateTag({ name: 'description', content: description }))
.catch(this.handleError);
}
getLanguanges(): void {
this.languageService.getLanguages()
.then(languages =>
{ this.languages = languages }
);
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}