AngularJS best practice - Templates vs Javascript - javascript

Per default, Angular fetches the HTML templates from the server when the user navigates to a route. With that in mind, imagine this scenario:
User loads the Angular app. The main view has a subpage called "Order".
While the user is studying the main view a new version of the app is rolled out in production. The new version has a complete rewrite of the Order page with new Javscript and HTML.
The user navigates to the Order page. The Javascript is already loaded by the browser in step 1, so the user is on the old version until app is reloaded. But the new template gets fetched from the server on navigation. So now the Javascript and template are our of sync!
Is my assumption that the Javascript/HTML is out of sync, correct?
If so, are there any best practices related to this issue?
I guess one solution is the make Angular fetch all the templates on app initialization. But this could be a performance penalty if the app has hundreds of HTML views.

I've never wondered about that issue myself. One possible idea would be to reuse the pattern known as assets versioning, where upon new release, you rename all your assets.
For instance, instead of login.html you'd use login-xyz.html as a name of a template. xyz could be a random value, or a checksum of the file. Checksum might be a slightly better option because if the new release is small (i.e. you fixed just some small bug in one file), if user loads any page but the fixed one, he/she will not be bothered with a reload - all other files will have the same checksums, they'll work with no interruptions.
This way, when an outdated Anguar app tries to fetch a template, it'd get a HTTP 404 error. As an addition to that, you could write a simple $http interceptor, which would detect a 404 response, and reload page automatically (or offer user an option of doing so).
There are modules which are capable of renaming assets, such as gulp-rev - but I never heard of using that for Angular templates. You might implement something like that on your own, though.
Of course you might want to keep both the new and old versions of files to allow users to work without interrupting them with a refresh. Depends on what your requirements are. I assume you're trying to avoid that, though.
Sample 404 interceptor (CoffeScript, as I have it handy now):
m.factory 'notFoundInterceptor', ($q) ->
return {
responseError: (response) ->
if response?.status == 404
# Reload, or warn user
return $q.defer()
# Not a 404, so handle it elsewhere
$q.reject response
}
m.config ($httpProvider) ->
$httpProvider.interceptors.push 'notFoundInterceptor'

Thanks for good answers.
It turned out that this problem solved itself for us. Every time we roll out a new release all the users sessions gets deleted and users will be sent to the login page. This will trigger a page load and fresh JavaScript/HTML gets loaded.

I've read about this issue long time ago, and one option is to do versioning on changed pages and application.js file.
For example on your version 1 of your application you can on your html file use something like:
<script src="js/angular_app_v1.js"></script>
Inside your routes also version the templateURL
templateUrl: 'templates/view_product_v1.html'
So when you roll out a new version you won't be overwriting templates and users already working will have the old version until they reload the browser but won't have version inconsistences.

Versioning of the assets using the file names would become unmaintainable for even a medium sided app.
Although it is a heavy weight approach for web assets you could look into content negotiation. This is where the call for a resource, generally a REST api returns the version of the resource, Content-Type: application/vnd.contentful.delivery.v1+json.. On the client you can check that the version matches what it expects. So if the client only knows how to load v1.1 and the resource responses with v1.2 the UI would know it cannot process that and should reload the page.
Another possibility is to load all templates up front in the UI. There are build processes in Grunt you can run such as https://github.com/ericclemmons/grunt-angular-templates that will combine all of your templates into a single file for delivery and then load them into $templateCache so no requests ever get to the server.

If you have some sort of server-side language you can build a filter in (.NET, Rails, Java or whatever), and pass along a version number with your template requests. If the version requested by the client is older than what's deployed, you'd send an error to the client. Your client would watch for that error ($http interceptor) and force a page-refresh to pull down the newer javascript code. (Maybe show an alert to the user first so they know what's going on).

You can preload all your templates into a $templateCache and serve them as one templates.js file. There is a gulp task for this https://www.npmjs.com/package/gulp-angular-templatecache. Then your application will load all templates in a single request together with application scripts on start up, thus they will be in sync. Read http://www.johnpapa.net/angular-and-gulp/ for more info.

It always makes sense to have a version number and use it when syncing resources. It's not only a good practice for the use case you described, but also for other situation, such as rolling back to a specific version or having two versions live and usable (for example in order to let some users preview the next version)

Related

What is SSG (Nuxt.js, Gatsby) doing?

I have heard SSG generates static sites.
Then I thought SSG generates pure HTML that didn't include React, but I think it may not be true now.
I think:
SSG generates a usual React App and rendered HTMLs for initialization.
As it is a usual React App, if I click a button and trigger a side effect, client-side rendering will be triggered and the page will be updated.
When routing using router is triggered, next page's js file and data obtained when build will be downloaded, and then client-side rendering will be triggered.
The next page's rendered HTML for initialization isn't used here.
Is it true?
SSG (Static Site Generators) like Gatsby and Next, what they do is to create an output HTML based on a React environment code. This doesn't mean that the site is "static" in terms of interaction. This means that the page you are requesting is already created so you are avoiding response and compilation time in the server.
Summarizing, given a "traditional"/"old-fashioned" PHP site. When you request the homepage, for example, your requests go to the server, the server transpiles the PHP into HTML (what the browser can parse and print) and then you get the page. That processing time is omitted in Gatsby/Next because the HTML is already created.
When you build your site in Gatsby/Next, the data is being retrieved from the sources (using GraphQL from markdowns, CMSs, APIs, JSONs, etc) and creates the output (that's why there's a /public folder generated). All your JavaScript and React is bundled into the output HTML so your website will be "dynamic" in terms of user interactivity, React is part of the ecosystem so your side-effects (triggered by useEffect hook for example) or your rehydration process (useState hook for example) will be part of your site.
Explained as:
When you navigate into another page, you are requesting a page that is already built and generated, that's why is so blazingly fast.
I've answered this question few weeks ago on the Nuxt discussions: https://github.com/nuxt/nuxt.js/discussions/9493#discussioncomment-948643
Let's say that SSG bring several things:
SEO
speed
ecology
[probably some other things]
There are several ways of doing SSG and all of them have their pro/cons and their use-cases. For the most part, and if you're using Nuxt.js, you will probably go the target: static, ssr: true route.
This will:
generate fully static pages during build time and you'll be able to host it on Netlify, Vercel or alike
hydrate the static content with some JS after you have fetched the static files
have the Vue behavior afterwards, as a classic SPA (hence managing the routing without further server calls)
This behavior is called Isomorphic or Universal, more info in the linked discussion.
Gatsby and Next.js do work in somewhat similar ways. There are some minor differences but the general is globally the same across those 3 AFAIK.
SvelteKit and Astro handle this a bit differently. May be interesting to give it a look!

AngularJS with ui-router lost the concept of SPA?

My question is just conceptual.
When you use the ui-router (docs) in your application, then you have a system built of multiple views. Right?
I was thinking about that, because looking at the network log of Chrome, every change to another view, the client-side makes a request to server to get the HTML files.
Well, the definition of SPA might vary, but basically it has nothing to do with making requests to a backend. It is a matter if the browser needs to do a full page reload to make that request.
Traditionally
Fill out a form, submit it and the browser is redirected to a new url. A full page request
SPA
The application makes an AJAX request in the background. On its response it changes the URL manually and then changes the state of the application. There is no full page request, just JavaScript running in the background
But you are right about suspecting something wrong when there are lots of HTTP requests for templates. You do not want your application to do all these requests to the server. To avoid that you actually have to precompile your templates using a tool like grunt or gulp. Example: grunt-angular-templates. This will insert the templates in your JavaScript code and Angular just grabs them from there, instead of making a backend request. During development though it is no problem.
With modern frameworks you need a tool to "compile" your project for production. You want to concatenate all JavaScript files into one file, bring in precompiled templates and uglify the code. This is not something frameworks give you, you have to set it up yourself using tools like grunt or gulp.
Hope this was of help :-)

Ember best practices for loading javascript/app only after authentication

Starting a new Ember app and was prepared to follow token authentication type structure for authentication in the restricted API routes but was then told we need to not show any of the javascript (or as absolute little as possible) before authentication. This has me a little puzzled given single page javascript apps.
I'm using the, very helpful, ember-app-kit which has great tools that compile everything down to a minified and obfuscated single javascript file, which I thought was good enough for security, but apparently its not.
Having the entire app loaded once, and even in a single compiled/minified js file, what is best practice for "hiding" some of the javascript and only loading after authentication?
I had one thought of my own and have found another potential:
A ) coming from rails, I thought I could just build a very thin rails app that handles authentication in a server side view that doesnt load any of the app js. Then on successful authentication, transition the user to a view that loads all of the JS for the app and go from there.
B ) I found some talk of new functionality in ember-data that allows you to async load javascript files in the models. This seems like it could work but also seems very complex and I'm not sure if It'll totally work cause they want to hide not only models but things like app routes (basically everything but login)
I have done option A in rails: authenticate the user on the server and then forward them to a page containing the actual client Ember application. It will be far simpler than trying to dynamically load the app on the client side. Simple is usually best.

Problems refreshing angularjs changes on production server

I have a recurring issue that occurs when I make changes to my angularjs app. The problem is that I have to refresh the page if I want to seed the changes that I have made. This is a problem, because I don't want my users to have to refresh the page (they may not know to do this). They may think the site is broken. Is there some kind of angular directive or process that I can follow that will allow my UI changes to be reflected on my production server without my users having to refresh the page?
There are a couple of solutions you could look at,
There is a similar answer to your question here:
AngularJS disable partial caching on dev machine
To quote the accepted answer on that post:
"here's one way to always automatically clear the cache whenever the
ng-view content changes"
myApp.run(function($rootScope, $templateCache) {
$rootScope.$on('$viewContentLoaded', function() {
$templateCache.removeAll();
});
});
A non angular solution may also be found here:
Force browser to clear cache
To quote the best answer on that post (Fermin's answer):
If it's to view css or js changes one way is to append _versionNo to
the css/js file for each release. E.g.
script_1.0.css script_1.1.css script_1.2.css etc.
You can check out this link to see how it could work.
I hope these help.
EDIT.
To respond to your comment, I'm sorry the above hasn't worked.
Perhaps you could try implementing a websockets based approach, similar to Trello, whereby after a certain amount of time you ask the user to update their page to receive new updates to the system or to refresh if their socket connection has timed out? Depending on your setup you may find this tutorial useful: http://www.html5rocks.com/en/tutorials/frameworks/angular-websockets/
Using html2js you can more easily manage versioning of templates. It is a grunt plugin that will load all of your templates into a js file. Downside is all your templates get loaded regardless of need, upside is you have all your templates loaded ready to use on one http call and one point of caching for them. This way you can set up to rename your js file on new releases and bust the cache for templates on production. As for dev, the other answer here is sufficient.

ExtJS file load approach

I have an application that have more than 7 tabs at home page and each tab is very comprehensive in itself with nested tabs/windows.
I am using EXTJS 4.2 MVC architecture. My question is what approach should I use to load all views/controllers/stores. This does not include proxy calls to web servers as those are only user request based.
First Approach: Load all files on application first load by including all controllers in app.js file and those controllers will load all tab specific files. I do have one person resource who is working with ExtJs for long time and suggested that it is OK to load all at once. EXTJS build process will combine all these files in one single file and it will be like ext.js file that is very big in itself and takes very less time to load.
Second approach: Only load tab views/controllers when user select that tab. That will require invoking controllers dynamically.
As I am new to ExtJS and have lazy loading mentality. Not sure how it fits in EXTJS world. Please advice me based on your experiences.
As long as you concatenate and minify your files into a single bundle your resource loading time should be reasonable. If you also include a version number at the end of your resource loading url you will get the benefit of browser caching and refresh on demand when you want to update the bundle. You just rev the version and the browse will reload your bundle from the server the next time.
Processing 7 controllers and setting up listeners is an overhead but I doubt you will see a major performance improvement here. Do be mindful of multiple round trips to the server to fetch resources and data. This is where you will see negative impact.

Categories