Я сделал угловое приложение, используя angular-cli и выполняя в нем универсальный рендеринг, выполнив следующие шаги, указанные здесь . Но упоминается, что я не могу использовать глобальные переменные, такие как окно и документ, в своем приложении, если я делаю универсальный рендеринг. Как я могу установить файлы cookie на внешнем интерфейсе для поддержания сеанса пользователя. Раньше я использовал JWT, но для этого мне нужно установить файлы cookie в моем браузере.
Использование файлов cookie в универсальном рендеринге с использованием angular-cli
Ответы (2)
Примечание. вся приведенная ниже информация действительна только в том случае, если вы используете Node с Express для динамического рендеринга (во время поступления запроса на сервер) вашего приложения Angular на сервере. . Я не смотрел на предварительный рендеринг. И я не знаю, как бы вы поступили, если бы использовали другой фреймворк, кроме Express, например, Hapi или любой другой фреймворк. Я могу только предположить, что @nguniversal
должен предложить решение и для них, но не изучал его.
При этом вот как мне удалось сделать файлы cookie доступными в моем приложении, когда оно обрабатывается на стороне сервера:
app.server.module.ts
:
// ...
import { Request } from 'express';
import { REQUEST } from '@nguniversal/express-engine/tokens';
@Injectable()
export class RequestCookies {
constructor(@Inject(REQUEST) private request: Request) {}
get cookies() {
return !!this.request.headers.cookie ? this.request.headers.cookie : null;
}
}
@NgModule({
imports: [
// ...
],
providers: [
CookieService,
{ provide: 'req', useClass: RequestCookies }
],
bootstrap: [AppComponent]
})
export class AppServerModule {}
app.module.ts
: (некоторые могут назвать это app.browser.module.ts
)
@NgModule({
declarations: [
// ...
],
imports: [
// ...
],
providers: [
CookieService,
{
provide: 'req',
useValue: null
}
],
bootstrap: [AppComponent]
})
export class AppModule {}
cookie.service.ts
:
import { Inject, Injectable } from '@angular/core';
@Injectable()
export class CookieService {
private cookieStore = {};
constructor(
@Inject('req') private readonly req: any,
) {
if (this.req !== null) {
this.parseCookies(this.req.cookies);
} else {
this.parseCookies(document.cookie);
}
}
public parseCookies(cookies) {
this.cookieStore = {};
if (!!cookies === false) { return; }
let cookiesArr = cookies.split(';');
for (const cookie of cookiesArr) {
const cookieArr = cookie.split('=');
this.cookieStore[cookieArr[0]] = cookieArr[1];
}
}
get(key: string) {
return !!this.cookieStore[key] ? this.cookieStore[key] : null;
}
}
any.component.ts
:
// ...
constructor(
private cookieService: CookieService
) {}
needMyCookie() {
const userCookie = this.cookieService.get('user');
}
Убедитесь, что вы > npm install express @nguniversal/express-engine
P.S. Я начал с просмотра этого репозитория: https://github.com/angular/universal-starter/tree/master/cli для рендеринга на стороне сервера, я сам сделал только часть cookie (там не было). Это репо следует универсальной истории из вашей ссылки, но выходит за ее рамки. Если вы просто следуете универсальной истории, она гласит:
Ленивая загрузка пока не поддерживается
Но если вы попробуете репозиторий, на который я дал ссылку, вы обнаружите, что модули с ленивой загрузкой ВОССТАНАВЛИВАЮТСЯ и на сервере! Я не знаю, что это за ключ, может быть, это связано с кодом в файле server.js
и @nguniversal/module-map-ngfactory-loader
Я пробовал это с: версией CLI 1.4.2 и версией Angular: 4.4.1
Вот что я получаю с отключенным javascript в браузере:
Мои элементы карусели расположены так, потому что они на самом деле масштабируются до 90%. У меня есть анимация zoomIn для элемента в onInit. И в представлении, визуализируемом сервером, я принудительно настраиваю их на 90%, чтобы они не отображались на 100% при первой загрузке, а затем, после запуска клиента, заставляю их анимировать от 90 до 100.
Кроме того, если кто-нибудь наткнется на этот ответ и заметит ссылку на ширину области просмотра на снимке экрана, в блоке кода под основными навигационными ссылками - если им интересно - это мой WindowService
:
import { Injectable, PLATFORM_ID, Inject } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
@Injectable()
export class WindowService {
constructor(
@Inject(PLATFORM_ID) private readonly platformId: any,
) {}
get width() {
if (isPlatformBrowser(this.platformId)) {
return window.innerWidth;
} else {
return 'Not available server-side!';
// return null;
}
}
}
Просто добавьте его в массив providers: []
как в app.module.ts
, так и в app.server.module.ts
.
Еще следует отметить, что я использую Node с Express. Я не знаю, как это сделать, если вы используете другие фреймворки, такие как Hapi или любые другие существующие фреймворки.
@Injectable()
в класс RequestCookies
(я также обновил ответ)... Но это не понадобится, если только вы не захотите напрямую внедрить этот класс в другой сервис, плюс я думаю чтобы ошибка звучала иначе.
- person MrCroft; 10.01.2018
console.log('token',this.cookieService.get('token'));
дает undefined
в консоли узла, хотя файл cookie token
там есть
- person Toolkit; 21.09.2018
Мне удалось успешно использовать пакет npm ng2-cache (я использую Angular 4 и работает просто отлично). Я использую локальное хранилище, поэтому оно есть в моем массиве поставщиков модулей, например:
providers: [
CacheService,
{provide: CacheStorageAbstract, useClass: CacheLocalStorage},
...
]
Другой вариант — использовать isPlatformBrowser(), как показано здесь.
Самый уродливый вариант — просто поместить свой код, работающий с куки, в операторы try-catch. Таким образом, он будет работать в браузере и игнорироваться на стороне сервера.