Угловой универсальный ssr использует навигатор (окно или другие собственные объекты только для браузера)

Из документов:

Например, ваша серверная страница не может ссылаться на собственные объекты браузера, такие как окно, документ, навигатор или местоположение. Если они вам не нужны на странице, отображаемой сервером, вы можете обойти их с помощью условной логики. В качестве альтернативы вы можете найти внедряемую абстракцию Angular для нужного вам объекта, такого как Location или Document; он может адекватно заменить конкретный API, который вы вызываете. Если Angular его не предоставляет, вы можете написать свою собственную абстракцию, делегирующую API браузера в браузере и удовлетворительную альтернативную реализацию на сервере.

Имеет смысл, что сервер не может получить доступ к объектам браузера. Но этого можно добиться:

В качестве альтернативы вы можете найти внедряемую абстракцию Angular для нужного вам объекта, такого как Location или Document; он может адекватно заменить конкретный API, который вы вызываете.

Следующий:

Если Angular его не предоставляет, вы можете написать свою собственную абстракцию, делегирующую API браузера в браузере и удовлетворительную альтернативную реализацию на сервере.

Где я могу найти, какие из них предоставляет Angular и как их использовать? Я специально ищу навигатор.

Если навигатор не предоставляется Angular, как я могу написать свою собственную абстракцию?

Боковой узел: я использовал ng add @nguniversal/express-engine --clientProject angular.io-example, чтобы начать работу с ssr.


person Robin Dijkhof    schedule 24.10.2018    source источник
comment
Этот ответ и эта статья содержит процедуры для внедрения глобальных объектов. См. этот stackblitz для демонстрации, адаптированной к объекту navigator.   -  person ConnorsFan    schedule 24.10.2018
comment
Только это заставит его работать с ssr?   -  person Robin Dijkhof    schedule 25.10.2018


Ответы (1)


Хотя я бы не рекомендовал этот подход, если вам нужен объект navigator в Angular Universal, вы можете проверить Домино проект.

Затем в вашем файле server.ts вы должны сделать что-то вроде этого:

const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString();
const win = domino.createWindow(template);

global['window'] = win;
global['Node'] = win.Node;
global['navigator'] = win.navigator;
global['Event'] = win.Event;
global['Event']['prototype'] = win.Event.prototype;
global['document'] = win.document;

И в обработчике вы можете сделать:

app.engine('html', (_, options, callback) => {
  renderModuleFactory(AppServerModuleNgFactory, {
    // Our index.html
    document: template,
    url: options.req.url,
    // DI so that we can get lazy-loading to work differently (since we need it to just instantly render it)
    extraProviders: [
      provideModuleMap(LAZY_MODULE_MAP)
    ]
  }).then(html => {
    callback(null, html);
  });
});

См.: https://mdbootstrap.com/angular/angular-universal/.

person Pablo Alejandro Costesich    schedule 24.10.2018
comment
Почему бы вам не порекомендовать это? - person Robin Dijkhof; 25.10.2018
comment
У нас были некоторые проблемы с объектом window в прошлом (Angular 5 и Universal), и вы должны знать, что это не полная реализация браузера. В итоге мы просто добавили проверки большей части нашего кода для условного запуска в браузере. - person Pablo Alejandro Costesich; 25.10.2018