Closed ashtuchkin closed 6 years ago
+1. I would even expect to continue server-side rendering afterwards, for JavaScript-disabled browsers and IEs.
Some related links: http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html https://groups.google.com/forum/#!msg/angular/mRRU489xVTQ/XQVhx0MP9BIJ
So, I made a connect middleware for server-side rendering. It's actually independent from angular.js, but angular.js is my primary target. https://github.com/dai-shi/connect-prerenderer
Interesting, I've been thinking along the same way. Do you think the timer approach is viable in production envs? Also, does it work with angular routing?
Alex
On 11.03.2013, at 7:41, Daishi Kato notifications@github.com wrote:
So, I made a connect middleware for server-side rendering. It's actually independent from angular.js, but angular.js is my primary target. https://github.com/dai-shi/connect-prerenderer
— Reply to this email directly or view it on GitHub.
I have been thinking the use of PhantomJS, but your post and https://github.com/tmpvar/jsdom/issues/380 pushed me to use jsdom. The timer approach is a fallback, and the client-side javascript code (that runs on the server-side :-) is expected to notify the end of rendering. I haven't tested with angular yet. It won't work without a modification. Some tweaks are needed.
I finally made it work with AngularJS. https://github.com/dai-shi/connect-prerenderer At this point, only basic e2e tests are available, but I see it feasible. I had to patch angular.js so that it keeps templates for interpolation after compilation and that it deletes duplicated ng-repeat elements before compilation. It's more or less a hack right now. The documentation is weak, but I can help if anybody is interested in using it.
@dai-shi thanks! this looks so very cool. i'll be looking at it for our project. I'm using ui-router (https://github.com/angular-ui/ui-router/)
Any update on this? Would be great to use Angular like you would use Jade as a view engine for Express.
My project https://github.com/dai-shi/connect-prerenderer is getting good, still not mature. It works with ng-repeat
. There's one open issue. Bigger test cases would be required.
Would be worth trying until Angular 2.0 be ready.
Hi, guys! Just stumbled over this discussion... Very intresting, as i am working on a project-setup using grunt, express, angular.. for which i also want a server-side template-rendering fallback. Exited to try your prerenderer. Many thanks
As part of our effort to clean out old issues, this issue is being automatically closed since it has been inactivite for over two months.
Please try the newest versions of Angular (1.0.8
and 1.2.0-rc.1
), and if the issue persists, comment below so we can discuss it.
Thanks!
It's still an issue.
@btford, the issue should be re-opened; it's still a valid issue in 1.0.8 and 1.2.0-rc.1.
Ideas on this topic? I assume that the purpose of running angular on a server is to serve some fallback functionality. I am using angular in combination with nodejs/expressjs server. Usually my angular views get prerendered and then combined with the wrapper directly served from a jade-template with some live-server data i use as angular no-js fallback (like navigations - with std. routes - these are replaced with angular routes, if present).
This works create for angular directives that replace the contents of tags ( ng-bind, ng-inclued etc. ). The thing is that I am running into problems when i want to do the same thing with html-attributes, because i render the attributes content from jade, not an angular-placeholder.
So i am currently playing around with these possible solutions ( a combination of those ):
All the best, Florian
I would like to reuse the complete logic of my AngularJS on the server side e.g. routers, etc. and render the whole site on the server. If the user has JavaScript activated the site gets initially rendered on the server and after that the site behaves like a SPA (no flash of content, no initially spinners, easy SEO, etc.).If the user has JavaScript deactivated the site behaves like a normal static page - except my templating engine on the server is Angular and not Jade, EJS, etc. and I describe routes in Angular and not Express. I think that would be graceful degradation.
I see... I do a similar thing with my routing... i define all my projects paths, routes, navigations in a node config module. From this i generate my express and angular routes. The outcome is similar/same to yours. The problem i encountered with reusing angular-route definitions is that i need more complex routing mechanics for the server side. Like auth plugin etc. that i can't define properly in angular routesJs-file, but i still want to define them in one place. So i went more the sharing server-resources with angular way, then the other way around. When i am back @ a stable state i would be interested in exchanging and comparing our solutions. Further i don't want to loose Jade ( but maybe the prerendering of angular-views ), as it made me addicted to it's style of html-templating in hours :)
Auth is a problem, yes. A RESTful API helps a lot to hide private data and with some additional redirecting it should be possible to prevent users from seeing private views. I would treat Jade just as a different Syntax for HTML e.g. use Jades meaningfull whitespace to avoid forgotten closing tags but don't use mixins, iterators, etc. because you can use Angulars directives for that. So it works on client, too.
btw, have you guys looked at https://github.com/dai-shi/connect-prerenderer? I've used his techniques (patched https://github.com/dai-shi/connect-prerenderer/blob/master/test/server/public/angular.js) together with ui-router and phantomJS to produce snapshots on the server for SEO purposes. the good thing is that that these could be bootstrapped a-la Rendrhttp://nerds.airbnb.com/weve-open-sourced-rendr-run-your-backbonejs-a/
On Tue, Aug 27, 2013 at 5:24 AM, donaldpipowitch notifications@github.comwrote:
Auth is a problem, yes. A RESTful API helps a lot to hide private data and with some additional redirecting it should be possible to prevent users from seeing private views. I would treat Jade just as a different Syntax for HTML e.g. use Jades meaningfull whitespace to avoid forgotten closing tags but don't use mixins, iterators, etc. because you can use Angulars directives for that. So it works on client, too.
— Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/2104#issuecomment-23323116 .
Lior Messinger 1-646-3730044 A.lgorithms.com
@donaldpipowitch You are totally right about the Jade vs. Angular thing... as with this prerenderer approach it is the only way to stay DRY. Already started to rebuild my templates...
@lmessinger Hmm... I will give that connect-prerenderer a try... plan is to use it in combination with a directive that reinserts angular placeholders to html-elements that have been prerendered, haven't found a better solution to handle this (Do you guys understand what my problem is with the attributes?)... I am still trying to wrap my head around this approach... I have a running express app-server which uses a headless-browser to create a live dom on the server side. A http-request is received via the no-js routes and forwarded to the headless-browser to call the page in it and create a snapshot of the result to return to the client. The problem i see with that is that i can only have one page/dom at a time and if a second request comes in i have to wait until the last request is finished before i can build ab the second Snapshot ( is that correct? ). Any experiences how this scales? Or am i just plain wrong.
Will try to get it running over the next few days. Enjoying the discussion! Thx guys...
Florian Hi
First the nice thing about connect-prerenderer is that it has the Angular code you mentioned, that allows to bootstrap an application from the snapshot. ( This is presented as a patch to Angular itself). Bootstrap means, that when the user clicks the link in the search engine results page, she will get an html of the snapshot. The browser will then present the html. In the background it will download the code of the app. It will then start the app and connect it to the html so that further interaction with the page will be done thru the app. The html is decorated so that Angular can know the directives. The connect-pre renderer project waits for a user click to bootstrap the app. I used a patch on ui-router, that allowed me to bootstrap without wait. In essence, I did not allow partials to be attached to the Dom, until the url has changed.
About the flow you mentioned, another approach is to pre render, using the technique above, the indexed urls ("pages") and save them as html files on the server. Once the server seemed that the request is from a search bot, it will serve these files to the bot.
Hth Lior On Aug 29, 2013 12:39 AM, "Florian Neumann" notifications@github.com wrote:
@donaldpipowitch https://github.com/donaldpipowitch You are totally right about the Jade vs. Angular thing... as with this prerenderer approach it is the only way to stay DRY. Already started to rebuild my templates...
@lmessinger https://github.com/lmessinger Hmm... I will give that connect-prerenderer a try... plan is to use it in combination with a directive that reinserts angular placeholders to html-elements that have been prerendered, haven't found a better solution to handle this (Do you guys understand what my problem is with the attributes?)... I am still trying to wrap my head around this approach... I have a running express app-server which uses a headless-browser to create a live dom on the server side. A http-request is received via the no-js routes and forwarded to the headless-browser to call the page in it and create a snapshot of the result to return to the client. The problem i see with that is that i can only have one page/dom at a time and if a second request comes in i have to wait until the last request is finished before i can build ab the second Snapshot ( is that correct? ). Any experiences how this scales? Or am i just plain w rong. **
Will try to get it running over the next few days. Enjoying the discussion! Thx guys...
— Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/2104#issuecomment-23469967 .
There is a blog where the author manages to get prerendering working with jsdom and some other library to mock JSON requests. https://github.com/ithkuil/angular-on-server/wiki/Running-AngularJS-on-the-server-with-Node.js-and-jsdom . I do not see this mentioned anywhere on the page, so here you are.
This also seams to work: https://github.com/daslicht/express-phantom (my fork to make it work with express4 )
Yes, I'd love to see server side compilation in Angular. There are some surprisingly powerful implications for progressive enhancement.
Kevin: could u elaborate on the implications? im curious
On Wednesday, May 21, 2014, Kevin Suttle notifications@github.com wrote:
Yes, I'd love to see server side compilation in Angular. There are some surprisingly powerful implications for progressive enhancement.
— Reply to this email directly or view it on GitHubhttps://github.com/angular/angular.js/issues/2104#issuecomment-43845864 .
Lior Messinger 1-646-3730044 www.Toyify.me http://www.toyify.me/ www.Lgorithms.com http://A.lgorithms.com
This module also looks promising... https://github.com/meanjs/mean-seo
Working at a large e-commerce company, I have seen us trying to use hybrid approaches like those used by Twitter and Airbnb (see http://nerds.airbnb.com/weve-launched-our-first-nodejs-app-to-product/ and https://blog.twitter.com/2012/improving-performance-on-twittercom) to ensure consumers spend less time till first interactions. Companies like these are using a hybrid approach to render SPAs: first, generate pure HTML content so that rendering time is pretty constant across all browsers and then second, use a client-side framework (in Airbnb's case, Backbone) for subsequent loads. I am curious to see if this is in Angular's development timeline as an integrated solution with Node.js or some other server side platform.
hiravgandhi: This is the perfect approach for me either.AngularJS + ExpressJS and first page rendering on server would be lovely.
Which is faster: Download App to Client Render there ~or~ Render First page call with PhantomJS on the server and any further things on the client ? ! When Rendering pages with PhantomJS on the server are we able to use the AngularJS after rendering of will that just be a static HTML Snapshot? If so, how to make the returned snapshot full functional
@daslicht - Running PhantomJS seems like unnecessary overhead. A headless browser rendering content seems like an inefficient solution when ideally, some server side platform like Node.js should be able to interpret and render a Javascript SPA built with Angular.js given some type of package.
@hiravgandhi Yeah that would be true if we could reuse Models hand Controller of AngularJS in Node :) Possible how ?
Its possible with https://github.com/rendrjs/rendr
But that's Backbone
Does this affect anything?
http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html
@kevinSuttle - It affects one of the two problems of using a client-side framework. The problem is that we can't control the speed of initial loads. It would be useful to be able to render Angular on the server side for slower clients or richer content sites, at least for the first page, to get the user engaged ASAP as opposed to waiting for content to load, especially if they have a slower computer.
I've been pondering a module converting angular to ejs. Is that a reasonable direction?
We've been working on a solution to this problem at Say Media: https://github.com/saymedia/angularjs-server
The methodology is to run Angular against jsdom and then exploit Angular's dependency injection to override certain core services to make them work better in the server environment.
As well as generating static HTML on the server it can pre-resolve the route on the server and deliver the route locals inline in the initial page view, so the first page can render without any further data round-trip. Optionally it can also do route resolution on subsequent navigation via a single HTTP call to the server.
Your average Angular app doesn't perform too well on the server (jsdom is slower than a browser, so it'll magnify any perf problems you already had) so we mitigate it by running Varnish in front. A variant of this code is running on our production sites.
So, the problem with running Angular 1.x apps on the server fundamentally is that you either need to use a headless browser or a framework built on top of a headless browser (i.e. like @apparentlymart's Angular Server project) which can be hard to make performant OR you can use something like the Jangular library I created (https://github.com/gethuman/jangular) which only supports a subset of Angular and you need to be really careful about how you implement it (but on the plus side it is extremely fast).
Fortunately, there is a much better solution that is in the works in Angular 2. I know that doesn't help with your Angular 1.x apps right now but if you are interested in learning more about what is coming, tune in to the livestream for our AngularU talk next week: https://angularu.com/ng/session/2015sf/angular-2-server-rendering
Btw, @kevinSuttle regarding the Google search crawler indexing HTML rendered on the client side, just realize that:
Just wanted to add that Google has since deprecated their AJAX crawling scheme, making server-rendered apps even more important. https://googlewebmastercentral.blogspot.com/2015/10/deprecating-our-ajax-crawling-scheme.html
I'm all for having server-rendering capabilities, but how does deprecating Google's AJAX crawling scheme make this even more important ? (In case that wasn't clear, I'm genuinely curious :smiley:)
More important if you're currently only serving up a client-rendered app with no static HTML on the server. From that post: "Since the assumptions for our 2009 proposal are no longer valid, we recommend following the principles of progressive enhancement." How often do you see progressively enhanced Angular apps?
In the same article though:
Times have changed. Today, as long as you're not blocking Googlebot from crawling your JavaScript or CSS files, we are generally able to render and understand your web pages like modern browsers.
Yes progressive enhancement is good, yes server rendering is good, but the removal of the AJAX crawling scheme from google bot shouldn't be the motivation.
Hello guys, I would like to notify you about ng1-server : https://www.npmjs.com/package/ng1-server
This is my pet project, it uses a headless browser to pre-render any angular 1 web-app.
The main functionalities are :
I'd really appreciate if you guy have a look at it, and let me know what you think.
Cheers and great new 2017 year for Angular 1 & 2 !
Very cool @a-lucas. I like that you have preboot integrated. I don't have a lot of experience with slimer.js, but the challenge with any angular 1.x SSR solution has always been that you either have to:
Option number 2 is almost certainly going to scale and perform better, but I gave up trying to make it generalized so other people can use it. There is so much custom stuff in there that in retrospect I would have been better off not even attempting to open source it. So, definitely your path is superior as an OSS solution and it looks like you added a lot of great caching options. I also like that users can take an existing app and just add this on top.
Hi @jeffwhelpley ,
Thanks for the quick answer. I had a look at angular.js server you mentionned few month ago, and it seems lile they chose JSDOM to emulate a browser environment. I went jsdom initially, but it came as very unstable and has limited functionality. I haven't tested slimer performances yet, but it seems lile a better alternative than phantomjs. It uses the latest gecko engine which supports ES6 almost completly, and the same api as phantomjs. I though of going the electron way too, but I couldn't find a way to capture all http requests.
Concerning scaling, I intentionally separated the 3 servers , making it easier to scale it in the future (if needed). A good scaling strategy would be imo to modify the bridge_pool so it can span slimer process on severall servers.
As of preboot, I haven't tested it, I am not sure if document.body is the correct way of setting the Approot. I will get this tested soon.
@jeffwhelpley pancakes seems lile a very cool concept. I am an absolute fan of code generators.
I am using angular js and phantomjs driver to crawl google careers - https://example.com I tried in the service_args = ['--ignore-ssl-errors=yes','--ignore-ssl-errors=true','--ssl-protocl=any'] Phantomjs version 2.1.1. I tried in the service_args ,but is same ssl error. google crawl not accept the https://example.com/?_escaped_fragment_= request,In https but it still working in http.Like http://example.com/?_escaped_fragment_= .i don't understand why not take request https ? please help me...
when i request the service_args:
phantomjs --disk-cache=no --ignore-ssl-errors=yes --ignore-ssl-errors=true --ssl-protocol=any /opt/bitnami/apache-tomcat/stt/ROOT/js/angular-seo.js 9090 https://example.com/
Dedicated server-side rendering support is out of scope at this point of AngularJS development.
Issue has fixed. Problem was in port and SSL. thanks
I would like to create a module that will make server-side rendering in node.js possible. I've done this before in my own project and wanted to discuss technical details.
So, the goals of the module:
How do I want to do that:
<ng-include>
and<ng-view>
in main html file.<ng-include>
-s are filled with rendered html. When ready (see below), the full DOM is serialized and sent to the browser (or crawler). In browser, the contents of<ng-include>
-s are discarded and re-rendered, creating all services and controllers, binding all needed event handlers.Problems to solve:
otherwise
clause which usually redirects to base, but in server environment it's bad practice. Preferably even on the client side if a route is unknown, we should redirect the browser to new url, as the server can have something else there (statics, etc), or 404 page.So, what do you think? Is it viable? Did you plan to do something similar?