Is there any noticable performance difference between:
Rendering template completely on the server side and just delivering it as a static html to the client.
VS
Rendering template on the client using frameworks like AngularJS which loads data via ajax call.
A sample use case can be loading list of 100 comments for a blog. (I'm not sure if this is the best use case for this question). This can be done in Angular by fetching JSON data and then passing it to the controller which then renders the view with data-binding. For a static page, this can be rendered completely on the server and served directly on the client.
I'm considering following things to consider performance difference:
Time taken to insert new nodes on the DOM tree. (in case of Angular)
Time taken to apply css styles.
Please add anything else I've missed out.
I'd say the main differences between the two approaches are:
(Server-side rendering)
All content are available to the person browsing the page when rendering at server-side, but the page takes longer to load
(Angular / Client-side rendering)
Faster initial loading time of the page, but wait a few secs for content fetched with ajax.
The time it takes for angular to render the data i'd say is neglectable. Once the data is loaded though, AngularJS will probably be faster to e.g. get new data, since you don't have to refresh the whole page etc.
Applying CSS is done on client-side either way
Related
I have been told it is 'bad practice' to return data from a Django view and use those returned items in Javascript that is loaded on the page.
For example: if I was writing an app that needed some extra data to load/display a javascript based graph, I was told it's wrong to pass that data directly into the javascript on the page from a template variable passed from the Django view.
My first thought:
Just get the data the graph needs in the django view and return it in a context variable to be used in the template. Then just reference that context variable directly in the javascript in the template.
It should load the data fine - but I was told that is the wrong way.
So how is it best achieved?
My second thought:
Spin up Django Rest Framework and create an endpoint where you pass any required data to and make an AJAX request when the page loads - then load the data and do the JS stuff needed.
This works, except for one thing, how do I get the variables required for the AJAX request into the AJAX request itself?
I'd have to get them either from the context (which is the 'wrong way') or get the parameters from the URL. Is there any easy way to parse the data out of the URL in JS? It seems like a pain in the neck just to get around not utilizing the view for the data needed and accessing those variables directly in the JS.
So, is it really 'bad practice' to pass data from the Django view and use it directly in the Javascript?
Are both methods acceptable?
What is the Django appropriate way to get data like that into the Javascript on a given page/template?
Passing data directly is not always the wrong way to go. JS is there so you can execute code when everything else is ready. So when they tell you it's the wrong way to pass data directly, it's because there is no point in making the page and data heavier than it should be before JS kicks in.
BUT it's okay to pass the essential data so your JS codes knows what it has to do. To make it more clear, let's look into your case:
You want to render a graph. And graphs are sometimes heavy to render and it can make the first render slow. And most of the time, graphs are not so useful without the extra context that your page provides. So in order to make your web page load faster, you let JS load your graph after your webpage has been rendered. And if you're going to wait, then there is no point in passing the extra data needed because it makes the page heavier and slows down the initial render and it takes time to parse and convert those data to JSON objects.
By removing the data and letting JS load them in the background, you make your page smaller and faster to render. So while a user is reading the context needed for your graph, JS will fetch the data needed and renders the graph. This will cause your web page to have a faster initial render.
So in general:
When to pass data directly:
When the initial data is necessary for JS to do what it has to (configs, defaults, etc).
When the time difference matters a lot and you can't wait too much for an extra request to complete the render.
When data is very small.
When not to pass data directly:
When rendering the extra data takes time anyway, so why not get the data latter too?
When the data size is big.
When you need to render something as fast as possible.
When there are some heavy processes needed for those data.
When JS can make your data size smaller (Decide what kind of data should be passed exactly using options that are only accessible by JS.)
Coming from some classic server-side template languages (php, jsp), I have a general architectural question on React.js:
Can I limit certain components of a page to be rendered server-side only? And reduce the client-side javascript bundle accordingly?
*I find that often ridiculously large. One reason (afaik): Every component must have the capability to be re-rendered on state changes and SPA-(aka soft, virtual..) page navigation, since all changes come in as data, not as prerendered html chunks (afaik).
Basically, I see 2 different types of content sections in almost all of my web projects:
1) highly dynamic “facebook-ish” interactive sections
Personal greetings, messages and message counters, likes and replies… here default React behavior is at its best: new data comes in, global state (redux store) changes and all affected components get re-rendered. Which would be a daunting task without react and redux sound principles. And certainly client-side rendering/updates are the way to go.
That's often the user-login area at top ("Hello Joe, 5 unread messages"), some live data (stock, weather,…) in the middle and said comments closer to the bottom.
2) SSR “static” content (think PHP)
However, for many sections I know for sure, nothing is client-side dynamic. Footer Menus for example, might stem from a database, but are certain to not change for the duration of the session. (Even if John Doe decides to like, comment or change his name…)
Rendering them only server-side would be enough. Often the main content block can also do with SSR-only. (And all the layout-ish sub-components needed to render its html)
Still, I have to give all components to the client bundle, so that also virtual/soft page navigation works... (which transmits new data, but not pre-rendered sections)
You could tell me as a workaround to simply keep the footer out of the react container mounting point, but that's not my point... "static" aka sections that can do with pure SSR might be elsewhere, too, between dynamic header and lower response/feedback/liking sections…
I would like to mark Type-2-components as "SSR-is-enough" (and also their sub-components – unless webpack dependency tree figures out, they are used in Type1-CSR-components, too…).
So send it as a single html blob. Also receiving it "pre-rendered" on SPA-ish virtual page navigation would be needed afaik. (since the component knowledge will be missing from the client bundle)
Is there a way to do this? Has someone thought of this general, imho common problem before...?
Hydrating only certain components is definitely a problem that is being thought about.
One web framework that solves is problem is Astro. It only hydrates components which are actually interactive.
Another is Fresh, which has a concept called "islands." The entire page is server-side generated and when you need interactivity, you create an "island" which is a component which is hydrated on the client.
My question is about server-side rendering and the React client-side check process it performs in the HTML markup when using SSR.
If server produced HTML does not match with client-side virtual representation for the same content, React ditches the HTML received from the server a re-renders the client-side version.
In my case, I have some parts of the main content page that gets rendered dynamically in the server based on some internal data that I know for sure won't change client-side.
Right now, I must pass the internal data in the initial payload so React can create a virtual representation in the reconciliation process so it check is ok and it does not re-render the content.
I would like to avoid sending data to the browser that it doesn't need.
Is there any way I can set a component (tree) to be static so reconciliation process just ignores it and avoid re-render the content?
Thanks!
In Backbone.js, model loading and saving is done via ajax calls. However, are there any best practices to loading the initial collection on page load without having to pull this down via ajax? I'm trying to do as much server side rendering as possible up front.
In the past, I've seeded the html with a javascript variable containing a json string of the initial data state so it can be rendered server side, but I'm not sure if this is a good practice.
Don't know if it's necessarily the best practice, but this method of seeding the html with a json object (not a json string as you described it, right?) is certainly my preferred way of doing initial loading. Not only for the (obvious) reason that it removes the delay of waiting for the initial AJAX call to return, but also because the one less open connection frees the browser to load something else instead (like an img src or whatnot), getting you to document.onLoad slightly sooner.
It's recommended that, when using this method, you put the said variable in a script tag at the bottom of the body (i.e. not in the head section), in order to give the static html elements on the page a chance to load and render first. The json data is ready when document.onLoad fires.
From Backbone docs, initialising models in script tag is not a bad practice. In my current project I decided to set only plain objects inside window.projectData, to be able to init Backbone models in external javascripts.
<script>
;(window.projectData || (window.projectData = {})).modelName = {/* value */};
</script>
The approach you select will probably depend on how much data you're planning to load and how that data will be used within the page.
If most of the required data will not ultimately end up rendered on the page, bootstrapping the initial state into a javascript variable might not be a bad route.
If the data is directly related to the presentation of the page, however, you might prefer to parse a pre-rendered DOM for the initial state of the backbone application. The obligatory word of caution is that this kind of parsing will be somewhat slower, especially for large data sets.
If you do end up opting to parse pre-rendered content, I put together a small jQuery DOM parser a while back that might prove useful for mapping the presented content into a Backbone-ready form.
I'm building an AJAX 'web application' where, once the UI is loaded, calls to the server are for 'data exchange' only. As a result a lot of UI manipulation will be done using Javascript. Lets say the Javascript retrieves some data consisting of multiple fields from the server using AJAX. To put it on the screen I can think of multiple approaches -
Call methods like createElement() and appendChild() to build an interface to display the retrieved data
Populate the .innerHTML for the container element then for every data field lookup a container in the newly added HTML and populate it. The data that goes into .innerHTML could be stored in a JS variable or contained in a hidden node, or fetched using a seperate AJAX call.
Have the interface stored in a hidden node. Clone it (using cloneNode()) and put it in the actual container (using appendChild()) and then populate it with fields like in method 2.
and there are probably more ways.
Could you share pros, cons and possible gotachas in these approaches from cross-browser support, performance and coding complexity point of views?
Somewhat related question: Is client-side UI rendering via Javascript a good idea?
Thanks.
ok, let's start off:
Use toolkits
First you would want to invest time learning a JS toolkit. While others suggest native JS is good (which it really is), but you would not want to waste time on building apps that don't work cross-browser or spend too much time testing it. People in the community have invested their time in doing that for you. Show some love to the open community and use their product. I personally use jQuery, but there are others like Dojo and YUI.
But still use native JS whenever possible. It's still faster.
Structure your code
After a toolkit, you need some structure. BackboneJS will take care of that. It's to structure your code so that your code is reusable and well.. won't end up as spaghetti on your screen. Other tools like RequireJS are also useful for those scripts that need other scripts to run.
Templates: From strings to elements
Then, with that, you now have a toolkit but you still need to build the interface. It's better if you use a templating engine like Mustache or Handlebars. These render templates for your UI from strings (yes, plain strings of HTML). Just send over your template data from the server, store it in your app (in a variable or browser localstorage), and reuse it as necessary. No need for cloning hidden nodes!
Don't touch that DOM
As for approaching the DOM, you should touch the DOM only when necessary. DOM is slow, manipulating it is he** slow! that means you should avoid unnecessary animations, avoid excessive element append and remove, as well as changing styles. Check this article about avoiding too much reflow and repaints. Face it, the user won't event notice the round corners of your boxes, or the gradient background and don't even care if you did a slide animation or a fade-out. What they want is to get the job done and not adore the fireworks display.
Also, remove anything that isn't on screen. You might end up having 20% content on screen, and 80% off screen - a waste of memory.
Cache: fetch once, store, use infinitely for later
Now, your app is getting heavy and you want to shave off some HTTP requests. You can do this by caching. I usually use caching mostly on the templates so that every new UI, you don't need to load again from the server. You can do this by storing stuff in an object. you can go a little further and use the browser's localStorage when available.
Caching isn't all for the network. Let's say you have some complex calculations you want to use later, or some text from an unfinished form, use the cache for that too.
Avoid HTTP requests (or at least lighten them up)
While lightening up your app by using AJAX, you will inevitably be tempted to use AJAX just about anywhere - don't abuse it. Often times i see people who aggressively poll the server (every half-second or less). This not only strains the server (too many requests), but also the browser (wasting processing cycles) and the network (bandwidth). There are several practices done these days to avoid added HTTP requests:
Image Spriting - The art of placing a lot of images into one image and using background-position to change the image. Surely beats 100 individual HTTP requests
Use JSON for textual data - AJAX was meant to use XML.. then came along JSON that was a fat-free, platform-independent format of strucured data.
Do not return HTML-formatted data - With exemption of templates, which are HTML strings, you should never return HTML-formatted data over the wire. Have JS do JSON+templates on the client-side instead.
I'm building a similar app (Lightweight CMS)
In my view the approach you take will be dependent on the complexity of data that you are sending from the server > manipulating on the client side > and returning back to the server and db.
The cms that I'm working on is very basic and does not require heavy-duty manupulation on the client side. TinyMCE is as far as it will go.
Initially I was building the client admin area by echoing <input> from php and then collecting the data by parsing the DOM, converting to JSON and AJAX it back to the server (I found this code very helpful)
That of course required the user to hit "save" after editing or adding new data.
I later on decided that I needed something even more responsive and simpler than that so I'm now re-implementing everything for Jeditable which AJAXes the data as soon as the client hits "OK" on that particular field. No "main save" required.
To conclude it's really an area that is pretty uncharted. I mean, it appears to me that people in the industry do not like to blur that line between back-end and front-end and find "one solution" that will do the entire DB>SERVER>CLIENT>SERVER>DB operation.
I'd love to see how you solved your problem.
Just my 2 cents.