Ancient website:
User navigates to url via bar or href, server call is made for that particular page
The page is returned (either static html or html rendered on server by ASP.NET
MVC, etc
EVERY page reloads everything, slow, reason to go to SPA
Angular 2 SPA:
User navigates to url via bar or router
A server call is made for the component's html/javascript
ONLY the stuff within the router outlet is loaded, not the navbar, etc (main advantage of SPAs)
HOWEVER, html is not actually received from server as is, Angular 2 code/markup is - then this markup is processed on the CLIENT before it can be displayed as plain HTML, which the browser can understand - SLOW? Enter Angular Universal?
Angular Universal:
First time users of your application will instantly see a server rendered view which greatly improves perceived performance and the overall user experience.
So, in short:
User navigates to url via search bar or router
Instead of returning Angular components, Angular Universal actually turns those components into html AND then sends them to the client. This is the ONLY advantage.
TLDR:
Is my understanding of what Angular Universal does correct? (last bullet point above).
And most importantly, assuming I understand what it does, how does it achieve this? My understanding is that IIS or whatever just returns requested resources, so how does Angular Universal pre-process them (edit: I would basically running something akin to an API that returns processed html)?
This HAS to mean that the server makes all the initial API calls needed to display the initial view, for example from route resolves...correct?
Edit: Let's focus on this approach to narrow down the question:
The second approach is to dynamically re-render your application on a web server for each request. There are still several caching options available with this approach to improve scalability and performance, but you would be running your application code within the context of Angular Universal for each request.
The approach here:
The first option is to pre-render your application which means that you would use one of the Universal build tools (i.e. gulp, grunt, broccoli, webpack, etc.) to generate static HTML for all your routes at build time. Then you could deploy that static HTML to a CDN.
is beyond me. Seeing how there is a bunch of dynamic content there, yet we preload static html.
Related
I'm currently designing a MEAN.js web application, and for some reason, whenever I refresh the page on a route or window.reload, it does not rerender the page, but only returns the JSON file found at that current route.
For example, when I'm at localhost:8080/people:
If I click here from the main page, I get
But if I hit refresh or reload the page for whatever reason I get
Does anyone have any idea why this is happening and how to fix it?
Presumably you are using what Angular call's html5Mode routing.
This uses pushState and friends. These are browser features designed to allow you to build a web app which has what appear to be separate pages with unique, real URLs but when you change the page you actually modify the DOM of the current page (to State B) instead of loading a new one from scratch.
The design intention for pushState and friends is that if you request the unique, real URL that maps onto State B then the server will provide the browser with the HTML for State B directly.
This means that:
if you arrive on the site without going to the homepage first, then you
load the content you are trying to load directly (which is faster than loading the homepage and then modifying it with JavaScript).
if you arrive on the site without JavaScript working (which could be for many reasons, then everything still works. See also Progressive Enhancement and Unobtrusive JavaScript.
What you've done wrong is that your URLs are mapping onto your JSON based API instead of server side processes that generate the pages.
You need to write the server side processes. You could consider using the Accept header to allow them to share URLs with the API (so the server returns either JSON or HTML depending on what the client says it accepts).
I am looking to create an application with AngularJS that also has pages rendered on the server side with PHP/Laravel.
Essentially, I want to be able to render a static version of a view on the server side, but have the Javascript views start kicking in as soon as the page is rendered.
The idea being that when a user goes to an internal page for the first time, all of the content is rendered ahead of time on the server, yet the one page application will continue to work as soon as the page is loaded in the browser.
The backend of the application is currently written in Laravel, so I would feel comfortable writing the view logic in PHP.
What would be the best direction to go for this? I really want to avoid passing the pages to a third party service such as prerender.io or first rendering the page in phantomjs.
Essentially: having Javascript disabled on a web browser will not make any one page AngularJS app run. This is why I want to find a way to render the full page on the server, and once the page is loaded in the browser, either re-render the page (if that is the way it must be done) with my Angular application or somehow bind all of the data with the static views with my AngularJS controllers and models.
I'm trying to use react-router right now, with express.js. My final objective is:
When a URL hits the server, it will use server-side rendering to render the output.
Once in the client, future clicks on the Link component will cause react-router to render on the client (no need to do a full round trip to the server).
What I got so far:
Make server rendering like this.
Make the Link component to work properly, when I render on the client.
My problem:
Once I render on the server, the ouput is not interactive. I mean, no event handler is associated with the DOM. That's comprehensible. What I'm looking for, though, is a way to blend server and client rendering. I mean, the server renders the output but somehow it gets interactive in the client. If I get this, I'll be able to use Link on the client and that will fulfill my needs.
If you call React.render(component, element) on the client where element points to a DOM node that contains your server-rendered React markup and component is instantiated with the same props as on the server (and assuming the props/state matches all the way down), React will transparently upgrade your static markup into an interactive React app.
See this JSFiddle example that demonstrates this technique: http://jsfiddle.net/BinaryMuse/ddvdppeg/ (note that there is a 1 second delay before the markup is upgraded to an interactive app, but only for demonstration purposes).
I'd like to create a site with Angular (I'm new), but also want to be able to have different "views" be cachable in the search engines and have their own URL routes. How would I achieve this with Angular, or is best not to use it?
Enable pushState in Angular with $locationProvider.html5Mode(true); so that you have real URLs and make sure that, when the URL is requested by the client, you deliver the complete page for that URL from the server (and not a set of empty templates that you populate with JS).
When a link is followed, you'll go through an Angular view and update the existing DOM (while changing the URL with pushState) but the initial load should be a complete page.
This does mean duplicating effort (you need client and server side versions of the code for building each page). Isomorphic JS is popular for dealing with that issue.
If you want to expose Angular views to search engines and other bots, I suggest using an open source framework that we developed at Say Media. It uses node.js to render the pages on the server when it detects a bot vs a real user. You can find it here:
https://github.com/saymedia/angularjs-server
I would suggest not using different routes, however, as most search engines will penalize you for having duplicate content on multiple urls. And while you might think they would just hit the bot version of your site, they are getting more sophisticated about crawling single page app like sites. I would be cautious about duplicate routes for the same content.
Good Luck!
When NOT using AngularJS, I create a web site that responds to /mysite/users . It returns an HTML page with user records filled within a table-like display.
I wish to try an AngularJS approach. I somehow load the web page, and that page's onload() calls /mysite/users, which returns merely a JSON list of users.
The "somehow" part is what bothers me. So far I'm reduced to first calling /mysite/showUsers. This downloads the HTML page which then itself calls /mysite/users.
Likewise, when editing with AngularJS I think I'll have to call /mysite/userEdit/1 which on load calls /mysite/user/1.
I think I'm missing something. Can I get a clue?
Thanks,
Jerome.
As you've noted, the AngularJS approach is not to load pre-rendered HTML from the server, but instead load a list of JSON data and rely on AngularJS directives to populate the DOM client-side.
A concrete example in your case would be a page which loads an Angular module that fetches a JSON list of users from /api/users, and leverages the ng-repeat directive to populate the data into the page right in the visitor's browser. Here's a JSFiddle I found that illustrates how you'd accomplish this.
It's all a matter of where the data gets inserted into the HTML; It can happen on the server-side or the client-side, and Angular favors the latter. (This is not to say you can't load pre-rendered HTML from the server, but you would be working against the way AngularJS is designed to be used.)
I've had trouble describing what I want to have happen. Perhaps it is because it goes against the grain of Angular.
My server responds to /user/1 with the JSON for user #1. For the browser to deal with it, I must have a web page already there that can display this JSON. Chicken and egg style, how do I get this edit web page into the browser? My classic example is using /user to list the users and having a link on each user to edit it, such as "/SOMETHING/1".
In the meantime, I've decided to go with /user/edit/1. That will cause the server to render an HTML file, using server-side scripting to insert a phrase that on window.onload() fills the skeleton HTML with the result of /user/1.
Thanks, Collin, for replying.