Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add render timeout to renderModule and renderApplication functions #51549

Open
2 of 5 tasks
maxisam opened this issue Aug 11, 2021 · 6 comments
Open
2 of 5 tasks

Add render timeout to renderModule and renderApplication functions #51549

maxisam opened this issue Aug 11, 2021 · 6 comments
Labels
area: server Issues related to server-side rendering feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Milestone

Comments

@maxisam
Copy link
Contributor

maxisam commented Aug 11, 2021

馃殌 Feature request

What modules are relevant for this feature request?

  • aspnetcore-engine
  • builders
  • common
  • express-engine
  • hapi-engine

Description

Should have a way to set timeout. So if angular universal render more than certain time, it should throw a timeout error.
It is highly possible certain links in the backend are broken at some point, without timeout it will be hanging there.

I think angular/universal#863 can be handled by this feature

A clear and concise description of the problem or missing capability...

Describe the solution you'd like

Build-in a timeout function like https://github.com/expressjs/timeout/blob/master/index.js

Describe alternatives you've considered

Have you considered any alternative solutions or workarounds?
@myflowpl
Copy link

This feature will be very useful. For now I just did this simple trick to handle timeouts.

  // All regular routes use the Universal engine
  server.get('*', (req: express.Request, res: express.Response) => {

    const timeoutAfter = 1000; // timeout after 1s
    const indexFile = join(distFolder, 'index.html');

    let isActive = setTimeout(() => {
      console.error(`TIMEOUT after ${timeoutAfter}ms on `, req.url);
      isActive = null;
      const html = readFileSync(indexFile).toString() + '<!-- data-cy=error-timeout -->';
      res.status(200).send(html);
    }, timeoutAfter)

    res.render(
      indexHtml,
      {
        req,
        res,
      },
      (err: Error, html: string) => {
        if(err) console.error(err);
        if(isActive) {
          clearTimeout(isActive); // clear timeout if response comes first
        } else {
          return; // if timeout, response is already sent
        }

        if(!html) {
          // if there is error, just render index.html, it's better then 500 error
          html = readFileSync(indexFile).toString() + '<!-- data-cy=error -->';
        }
        res.status(200).send(html);
      },
    );
  });

@alan-agius4 alan-agius4 added area: common Issues related to APIs in the @angular/common package feature Issue that requests a new feature labels Feb 22, 2023
@alan-agius4 alan-agius4 removed area: common Issues related to APIs in the @angular/common package feature Issue that requests a new feature labels Aug 29, 2023
@alan-agius4 alan-agius4 transferred this issue from angular/universal Aug 29, 2023
@alan-agius4 alan-agius4 added the area: server Issues related to server-side rendering label Aug 29, 2023
@ngbot ngbot bot added this to the needsTriage milestone Aug 29, 2023
@alan-agius4
Copy link
Contributor

@AndrewKushnir do you think this should be part of @angular/platform-server or @angular/ssr?

@alan-agius4 alan-agius4 added the feature Issue that requests a new feature label Aug 29, 2023
@ngbot ngbot bot modified the milestones: needsTriage, Backlog Aug 29, 2023
@angular-robot angular-robot bot added the feature: votes required Feature request which is currently still in the voting phase label Aug 29, 2023
@angular-robot
Copy link
Contributor

angular-robot bot commented Aug 29, 2023

Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.

Find more details about Angular's feature request process in our documentation.

@AndrewKushnir
Copy link
Contributor

@alan-agius4 I think we should consider adding this config option to the renderApplication and renderModule functions (within @angular/platform-server) and potentially also expose them via APIs from @angular/ssr.

@AndrewKushnir AndrewKushnir changed the title add render timeout Add render timeout to renderModule and renderApplication functions Aug 29, 2023
@angular-robot
Copy link
Contributor

angular-robot bot commented Sep 17, 2023

Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.

We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.

You can find more details about the feature request process in our documentation.

@angular-robot angular-robot bot added feature: insufficient votes Label to add when the not a sufficient number of votes or comments from unique authors and removed feature: votes required Feature request which is currently still in the voting phase labels Sep 17, 2023
@AndrewKushnir AndrewKushnir added feature: under consideration Feature request for which voting has completed and the request is now under consideration and removed feature: insufficient votes Label to add when the not a sufficient number of votes or comments from unique authors labels Sep 17, 2023
@Platonn
Copy link
Contributor

Platonn commented May 10, 2024

Hi @alan-agius4 @AndrewKushnir
IMHO we should take care not only of rendering timeouts but also any custom error propagation from Angular app to Express in SSR (or worker in case of SSG).

Currently, when any async error happens in a custom Angular app (e.g. unhandled TypeError 'cannot use property x of undefined' or we receive a HTTP error response from the upstream backend API), we have no way OOTB in Angular to reject the rendering. Therefore even if an fatal async error happens during the rendering, OOTB we respond with 200 HTTP status from SSR to the client (or save the html file in SSG) - which is bad for SEO, because malformed HTML might be indexed by google

Instead, we should be able to reject from Angular renderModule or renderApplication and thanks to this return HTTP 500 status from SSR to the client (or don't save the html file in SSG).

Summing up, it's not only timeouts that are important for SEO, but error handling in general too.

FYI in our Angular library "Spartacus" we're building now an Angular SSR Error Handling feature - a custom wrapper over CommonEngine to be able to populate errors from Angular app to the SSR. Internally we created a custom injection token PROPAGATE_SERVER_ERROR_RESPONSE = new InjectionToken<Function> that we call in our custom ErrorHandler class in case of any unhandled exception in the app (+ in case of any HTTP error response from the backend; intercepted in HttpInterceptor).

Note: I've described this issue already in Angular repo issues here: #50829

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: server Issues related to server-side rendering feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Projects
None yet
Development

No branches or pull requests

5 participants