Использование файлов cookie в универсальном рендеринге с использованием angular-cli

Я сделал угловое приложение, используя angular-cli и выполняя в нем универсальный рендеринг, выполнив следующие шаги, указанные здесь . Но упоминается, что я не могу использовать глобальные переменные, такие как окно и документ, в своем приложении, если я делаю универсальный рендеринг. Как я могу установить файлы cookie на внешнем интерфейсе для поддержания сеанса пользователя. Раньше я использовал JWT, но для этого мне нужно установить файлы cookie в моем браузере.


person Devesh Jadon    schedule 18.08.2017    source источник


Ответы (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 в браузере:

«Домашний Отложенный маршрут — 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 или любые другие существующие фреймворки.

person MrCroft    schedule 17.09.2017
comment
Хорошая реализация, но я получаю сообщение об ошибке: Нет провайдера для InjectionToken REQUEST У вас есть идеи по этому поводу? - person Okan Aslankan; 10.01.2018
comment
@OkanAslankan У вас где-то есть общедоступный код? С моей стороны, он все еще работает точно так же, как я разместил код выше. Единственная разница в том, что я добавил декоратор @Injectable() в класс RequestCookies (я также обновил ответ)... Но это не понадобится, если только вы не захотите напрямую внедрить этот класс в другой сервис, плюс я думаю чтобы ошибка звучала иначе. - person MrCroft; 10.01.2018
comment
Кроме того, вы можете проверить этот пример, возможно, он поможет: github.com/patrickmichalina/fusebox-angular-universal-starter/ Просмотр примеров Патрика также помог мне несколько раз и я понял некоторые вещи, которых не знал. даже не задумываясь. - person MrCroft; 10.01.2018
comment
Я решил это, вручную внедрив его в конструктор. Видел пару вопросов об этом в github по этому вопросу. Спасибо - person Okan Aslankan; 10.01.2018
comment
Я пытался, и это не работает, вот репо github.com/intergleam/universal -стартер/дерево/ - person Toolkit; 21.09.2018
comment
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. Таким образом, он будет работать в браузере и игнорироваться на стороне сервера.

person dockleryxk    schedule 22.08.2017
comment
Лично я еще не пробовал ng2-cache. Но я не думаю, что игнорирование файлов cookie на стороне сервера должно быть вариантом. Дело в том, что в большинстве случаев нам нужно получить хотя бы токен из куки, чтобы иметь авторизацию и/или отображать данные на основе пользователя, прямо в первом рендере, поступающем с сервера. - person MrCroft; 14.10.2017
comment
Итак, каков вариант токена аутентификации в настоящее время? - person Toolkit; 20.09.2018
comment
Поскольку этот вопрос задавался ранее, рендеринг на стороне сервера был значительно расширен. Есть много задокументированных решений о том, как заставить его работать, но это действительно зависит от вашего стека. - person dockleryxk; 20.09.2018
comment
не могли бы вы изменить github.com/angular/universal-starter, чтобы показать, как использовать файлы cookie? - person Toolkit; 21.09.2018