Angular: Server-side rendering of AngularDart

Created on 4 Dec 2016  路  19Comments  路  Source: angulardart/angular

As discussed in Gitter with @matanlurey and @kevmoo, I would suggest to introduce some sort of server side rendering.
A lot of developers do not use angular2dart because it lacks support for proper SEO (to support Twitter, Facebook etc.), server side rendering would be the solution to that. Sure, for a lot of normal web applications SEO is not that important, but for websites it is.

Server side rendering like with angular universal would be awesome, but the most important point would be to be able to prerender the meta tags and put them into the html before sending it the client. So in the simplest form we would only have to be able to run one service with angular2 on the server to get the meta tags and then copy the output into the response of our dart server.

It would be probably enough to lay the ground for thirtd party developers to finish it.

compiler 鈿ew feature blocked

Most helpful comment

Small update:

I have some (preview) support for parsing an Angular Dart template:
https://github.com/dart-lang/angular_ast

I know it's not server-side rendering, but I imagine it would be a nice starting point for a motivated member of the community.

All 19 comments

That would be awesome. And with DartVM, it would be blazing fast.

Thanks

If all you really need is services, you can do this without any work from us.

@matanlurey I would prefer to have something to build upon. It doesn't have to be complete but any means, just something that we can use to get started.

What exactly do you need? i.e. here is a "service" that produces meta tags:

class MetaTagService {
  String produceMetaTags() {
    return '''
      <meta ...>
      <meta ...>
    ''';
  }
}

Stick this in a meta_tags.dart, and it will work in both Angular and on the server.

@matanlurey I meant a base for complete server side rendering not just services.

As far as I can see SSR with Dart and angular2 is not practical right now, even though that Dart would be the perfect fit for it. Dart already has an abstraction for the DOM which is being used by all libs, Dart has lazy loading as a language feature, Dart has async/await and alot of other features which would be great for SSR/General development.
Dart could easily replace Typescript or js for this exact purpose and a lot of people would appreciate it.

Right, I think I already explained why we won't have complete server-side rendering.

Your original post at the top states:

So in the simplest form we would only have to be able to run one service with angular2 on the server to get the meta tags and then copy the output into the response of our dart server

(i.e. what I have above)

What I could offer is that we are working on an Angular template parser that is platform agnostic (i.e. it will be used to inform things like lint tools). Someone could take the result and use it to built a server-side rendering version of Angular.

The other option would be use something like package:mustache to get a simple HTML page.

Small update:

I have some (preview) support for parsing an Angular Dart template:
https://github.com/dart-lang/angular_ast

I know it's not server-side rendering, but I imagine it would be a nice starting point for a motivated member of the community.

What would be involved in having the angular2 components become "inflated" on the client side from the server side rendered HTML? Is this even possible?

I looked in the generated .template.dart files and it appears that all of the binding of events and behaviors happens at the time that angular2 creates the components. Is there code somewhere that can do all of this binding on an existing DOM tree?

Now that angular 4 has isomorphic, do you guys plan to implement an isomorphic equivalent for Dart ? I am a Dart n00b and I am sorry if this has already been implemented.
Also, did you go v3 for this reason?

I wonder if headless chrome could be used as a stopgap here:

$ chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/

@matanlurey I've been working on a side project https://github.com/ng-consult/ng1-server which does exactly this, using gecko, and packed with aggressive caching (external URL and rest caching) to speed up the thing. It also packs an extensive regexes URL rules engine, to determine what to cache and for how long. Unfortunately I had to stop it before the final release, because of lack of free time. The whole thing is written in typescript, I guess go would be a better candidate if someone want to take it over (because of good parallelism support) . Also after though , I think it is better to keep the headless browser instances opened instead of spawning it everytime.

I imagine a good way of doing this would be to take a snapshot with a cron-job, and cache it on disk, versus doing this "live", and using something like nginx as a reverse proxy. I guess it depends on the application though.

@matanlurey
Also keep it mind that if you want to pre-render, you need to know when the app finish rendering.
ng1-server is for angular 1 apps. I had to dig into angular source code and decorate the Angular Promise library as well as the $digest cycle to trigger an event when the page finishes rendering ( no more $http pending, all $digests done as well as every heavy computation finished. Then I can snapshot the HTML. You will have to cache every REST result so the client can replay them instantly.

Angular ships with something called "testability" that gives hooks into JS for exactly that. I'm sure we could pull it off if someone is motivated.

This is a complex project, that needs to take care of errors/exception/logging on the server.
I used https://slimerjs.org/ as an headless browser, and injected socket.io inside the slimer.js script to be able to communicate with the SSR layer.

Please have a look at https://github.com/ng-consult/ng1-server readme - I am the only maintainer, and I hope to get few weeks in October to finish it.

By then, Angular1 will probably be almost obsolete - but I'll be open to make a complete rewrite of it in Go - and make it framework agnostic.

Also, to provide good SSR performances, and want to do caching, you have to dive deep on which URL to cache, to be able to replay them instantly on the server and the browser.
So for example, if you have a page that does few public REST calls before rendering fully, and a couple of authenticated ones, and want to cache it, depending on what rendering strategy you need, you would need to implement several scenario. So for example, if you go to pre-render everything before it gets requested, in the previous page example,
You'd first cache the HTML, then cache every public REST queries (in redis for example)
Then when the browser ask for the page, it gets the HTML + the REST results serialised for instant replay.
Now if some of these REST queries get invalidated (because some record have been updated), this would also invalidate the pre-rendered HTML, and on each change, you would need to pre-render this HTML file, as well as the corresponding REST call - it can become difficult to keep track on which REST ressources gets invalidated, as well as the dependencies between URL and REST.
That is why I believe that Live SSR + caching is a good compromise for simplicity + good performances.

Realistically this isn't planned in AngularDart right now.

There are some potential options, for example you could run your application in NodeJS using jsdom, but we don't expect to provide this functionality inside of AngularDart.

Any news on Dart2 about SSR?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zoechi picture zoechi  路  5Comments

AndreyChernykh picture AndreyChernykh  路  4Comments

luisvt picture luisvt  路  5Comments

Adamovskiy picture Adamovskiy  路  6Comments

matanlurey picture matanlurey  路  3Comments