admin 管理员组

文章数量: 1184232

I have just created a simple Angular SSR application using Angular CLI: 18.2.12.

I am not using ngExpressEngine, but I am using @angular/platform-server

The application works fine with npm run build:ssr and npm run serve:ssr.

However, when I use built-in browser objects like localStorage, sessionStorage, window, location, document, or isBrowser, I encounter errors.

I understand that these objects are not accessible on the server.

In my application, these variables (e.g., localStorage and window) are used extensively. I tried using libraries like Domino and JSDOM, but they didn’t work properly.

I also referred to this post: Angular CLI - How to use window, document, or location in environment.ts.

Still, I couldn’t find a better solution.

Here is my server.ts file:

    import 'zone.js/node';
import { renderModule } from '@angular/platform-server';
import express from 'express';
import { join } from 'path';
import AppServerModule from './src/main.server';
// import { readFileSync } from 'fs';
// import { JSDOM } from 'jsdom'


const app = express();
const PORT = process.env['PORT'] || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/angular-ssr-project/browser');

// Serve static files
app.use(express.static(join(DIST_FOLDER, 'browser'), {
  maxAge: '1y',
  index: false
}));


// Serve SSR page
app.get('*', (req, res) => {
  renderModule(AppServerModule, {
    document: '<app-root></app-root>',
    url: req.url
  }).then(html => {
    res.send(html);
  }).catch(err => {
    console.error('SSR Rendering Error:', err);
    res.status(500).send('Error during SSR rendering');
  });
});

// Start the server
app.listen(PORT, () => {
  console.log(`Node Express server listening on http://localhost:${PORT}`);
});

// const dom = new JSDOM('<!doctype html><html><body></body></html>');
// global['window'] = dom.window;
// global['document'] = dom.window.document;
// ...
// ...

// const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString();
// const win = createWindow(template);
// global['window'] = win as any;
// global['document'] = win.document;
// global['navigator'] = win.navigator;

// ...
// ...

I have just created a simple Angular SSR application using Angular CLI: 18.2.12.

I am not using ngExpressEngine, but I am using @angular/platform-server

The application works fine with npm run build:ssr and npm run serve:ssr.

However, when I use built-in browser objects like localStorage, sessionStorage, window, location, document, or isBrowser, I encounter errors.

I understand that these objects are not accessible on the server.

In my application, these variables (e.g., localStorage and window) are used extensively. I tried using libraries like Domino and JSDOM, but they didn’t work properly.

I also referred to this post: Angular CLI - How to use window, document, or location in environment.ts.

Still, I couldn’t find a better solution.

Here is my server.ts file:

    import 'zone.js/node';
import { renderModule } from '@angular/platform-server';
import express from 'express';
import { join } from 'path';
import AppServerModule from './src/main.server';
// import { readFileSync } from 'fs';
// import { JSDOM } from 'jsdom'


const app = express();
const PORT = process.env['PORT'] || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/angular-ssr-project/browser');

// Serve static files
app.use(express.static(join(DIST_FOLDER, 'browser'), {
  maxAge: '1y',
  index: false
}));


// Serve SSR page
app.get('*', (req, res) => {
  renderModule(AppServerModule, {
    document: '<app-root></app-root>',
    url: req.url
  }).then(html => {
    res.send(html);
  }).catch(err => {
    console.error('SSR Rendering Error:', err);
    res.status(500).send('Error during SSR rendering');
  });
});

// Start the server
app.listen(PORT, () => {
  console.log(`Node Express server listening on http://localhost:${PORT}`);
});

// const dom = new JSDOM('<!doctype html><html><body></body></html>');
// global['window'] = dom.window;
// global['document'] = dom.window.document;
// ...
// ...

// const template = readFileSync(join(DIST_FOLDER, 'index.html')).toString();
// const win = createWindow(template);
// global['window'] = win as any;
// global['document'] = win.document;
// global['navigator'] = win.navigator;

// ...
// ...
Share Improve this question edited Dec 4, 2024 at 13:04 Naren Murali 54.5k5 gold badges40 silver badges70 bronze badges asked Dec 4, 2024 at 12:06 Kishan BholaKishan Bhola 412 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

If you want you can import document inside angular using:

DOCUMENT

A DI Token representing the main rendering context. In a browser and SSR this is the DOM Document. When using SSR, that document is created by Domino.

export class SomeComponent {
  document: DOCUMENT = inject(DOCUMENT);
  ...

Apart from this, we have the following techniques to bypass the errors arising from lack of localStorage, sessionStorage, document and window.

The below approach, does not do SSR, for the HTMLbut you can show a spinner to temporarily show until the proper screen loads.

@defer() {

} @placeholder { Loading... }

You can use isPlatformBrowser to conditionally execute code only on the browser.

import { inject, Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { isPlatformBrowser, isPlatformServer } from '@angular/common';
...

...
platformId = inject(PLATFORM_ID);
...

...
ngOnInit () {
  if(isPlatformBrowser(this.platformId)) {
    const query = this.activatedRoute.snapshot.queryParams;
    if (!query.code) {
        this.router.navigate(['/auth/login']);
    } else {
        this.checkGoogleCodeAndRedirect(query);
    }
  }
}

You can also use afterNextRender to do the same. The code inside the callback executes only on the browser.

ngOnInit () {
  afterNextRender(() => {
    const query = this.activatedRoute.snapshot.queryParams;
    if (!query.code) {
        this.router.navigate(['/auth/login']);
    } else {
        this.checkGoogleCodeAndRedirect(query);
    }
  });
}

本文标签: javascriptHow to Use window Document location in angular SSR applicationStack Overflow