Javascriptservices: Angular 2.4.5 template nested html/head/body duplicates

Created on 9 Feb 2017  路  11Comments  路  Source: aspnet/JavaScriptServices

I'm not sure if it's an issue, but when I look at static source of the page that gets prerendered on server I see structure like this

<html>
    <head>
        <title></title>
    </head>
    <body>
        <app>
            <html>
                <head>
                    <title></title>
                </head>
                <body>
                    <app></app>
                </body>
            </html>
        </app>
        <script>
    </body>
</html>

Which seems odd. Could it be bug?

Most helpful comment

So far I got them successfully integrated and server-rendering 馃樃
I need to do some more testing to make sure everything is working, we're still in beta with Angular 4.0 at the moment, but I'm working on cleaning up retrieving Title/Meta & style data right now.

image

@derricksimpson @SteveSandersonMS @hheexx

All 11 comments

That doesn't happen when I try it (with the current template and Angular 2.4.7). I get a structure like the following:

html
    body
        app
            title
            app

There's no nested html or body. There is a nested app element, which is irritating but not really a major problem. This is a limitation of Angular Universal (it doesn't completely respect the document template you supply to it, if it's only a document fragment and not a complete HTML page). If it bothers you, you can replace the outer app element in your cshtml with a div or similar (the only drawback to doing so is that then you must leave server-side rendering enabled, or you'd have to change it back to an app element manually).

If you can provide repro instructions for getting the nested html document, please let us know.

I'm not doing anything special just

  1. yo aspnetcore-spa [0.8.4] > Angular 2.4.5 (Experimental) > No > Angular2Spa
  2. dotnet run

Make sure you are looking at the static source of the page (CTRL + U), browser's Developer Tools won't show it, maybe because it's invalid html?

image

Ah yes, I see what you mean.

Currently this is a limitation of Angular's server-side rendering (it only understands the idea of returning a complete HTML page, not a document fragment). It's also a regression - they used to handle this better until recently.

If avoiding the oddly-shaped document matters to you (and I agree it should) then please tell the Angular Universal people that you want it to support returning document fragments. I'd suggest posting to https://github.com/angular/angular/issues/13822

@SteveSandersonMS
Does the fact that you linked to that thread means this will not work even with angular4 or you don't know?

It is kind of big deal. SEO is primary use case for Universal and we are not sure how Google would treat html like this.

@hheexx I haven't yet heard the Angular team confirm for sure whether they are going to put back the support for returning document fragments in Angular 4. Again, if this is important to you (and I know it is to many people), then please lobby the Angular folks about it directly.

Here is hacky code that fixes this:
return requestZone.run<Promise<string>>(() => platform.serializeModule(AppModule)).then(html => { resolve({ html: html.slice(27, html.length - 14).replace('</head><body>', '') }); }, reject);

Also in index.cshtml I advice changing app to div because we already have app tag returned from Universal.

<div asp-prerender-module="ClientApp/dist/main-server">Loading...</div>

:) very interesting hack. But hey, it works. :)

b.t.w. Couldn't one use @SteveSandersonMS sample code here https://github.com/aspnet/JavaScriptServices/issues/607 to prevent any markup from being written out from the C# side of things, then move all the js/css includes into the primary app.component.html and use only the output from Angular Universal?

The goal is to have code setup like in #607 (since otherwise we don't get to set any of the SEO must-have's like Title / Meta tags). I'm working on getting all of that going right now, hopefully have it up and running so we can test out a few scenarios.
@derricksimpson @SteveSandersonMS @hheexx

So far I got them successfully integrated and server-rendering 馃樃
I need to do some more testing to make sure everything is working, we're still in beta with Angular 4.0 at the moment, but I'm working on cleaning up retrieving Title/Meta & style data right now.

image

@derricksimpson @SteveSandersonMS @hheexx

In addition to @hheexx answer, here is the hacky code for angular 5 in asp.net core,

in boot.server.ts file change the code to this:

resolve({
html: (() => {
    let apphtml = state.renderToString();
    apphtml = apphtml.replace('<html><head><style>', '<style>').replace('</head><body><app', '<app').replace('</app></body></html>', '</app>');
    return apphtml;
})()});

and don't use <app change it to div
<div asp-prerender-module="ClientApp/dist/main-server">Loading...</div>

Was this page helpful?
0 / 5 - 0 ratings