11

Currently, my application is deployed and all the js have the timestamp version. Now when I again build my angular app the js will have a new timestamp version.

enter image description here

Is there a way where I can compare the version of my build and if it does not match then allow the user to logout from the application?

Ritesh Maharjan
  • 315
  • 1
  • 4
  • 11
  • I wanted to do something like this on the blog https://blog.nodeswat.com/automagic-reload-for-clients-after-deploy-with-angular-4-8440c9fdd96c But there is an issue while creating a hash in version file. – Ritesh Maharjan Jan 06 '21 at 12:48
  • This question is a duplicate and not worth 500 bounty. With a little effort, you'll be surprised there are a lot of answers already. For example - https://stackoverflow.com/q/42411789/3503019 – Akash Jul 30 '21 at 11:09
  • @RiteshMaharjan is your server serving up only static files or would you be able to add an endpoint that returns the last version available? – maxime1992 Aug 03 '21 at 08:46

4 Answers4

5

While service worker works on the fly, there is a more generic solution that can be used here. @Amirhossein has suggested a good way of implementation and a practical way of implementing is possible. Also, no need to call any API or make one for this purpose. We can ping the server for the latest index.html available in the server and compare it with the current one in the client.

An alternate working approach

Once you have generated the build for the Angular application, add the following support in the index.html file. Use the script I have added in the body section and replace the live URL instead of example.com and replace the latest main-es5 javascript the application build has generated.

<html>
    <head>
        <script src='https://code.jquery.com/jquery-3.6.0.min.js'></script>
    </head>
    <body>
        <script>
            $.get("https://example.com/?v=" + Date.now(), data => {
                if (!(String(data).includes('main-es5.014e7f2ada629a9a485a.js'))) {
                    localStorage.clear();
                }
            }, 'text');
        </script>
    </body>
</html>

How does this work?

The script pings your URL and fetches the current index.html file and compares the file with the currently used main-es5 file.

If it matches, then the user is running the latest version of your app. Else, the user is not using the latest version of the app and the user can be logged out based on the auth type used. 99% of the time, either localStorage, sessionStorage or a cookie is used. This can be cleared to remove the user data.

Based on the requirement, the user can be made to log in with the latest version of your app by implementing any of these methods.

Time to reload the contents with any of the options:

  1. window.location.reload(true); deprecated
  2. Show a popup to notify the user a new version is available.
  3. Ask the user to force reload the website with instructions.
  4. If you have a CloudFront based environment, invalidate cache there.

Is it a better approach than service workers / PWA?

No, honestly speaking, service workers are the best in business to solve your use case. However, certain legacy devices, old iPhones and many devices still don't seamlessly work with the concept of PWA. Also, there are certain APIs facing difficulties like with NFCs, Bluetooth, etc. Always do thorough research before launching on production.

Can I prevent the browser from caching my Angular application?

Yes, it's possible in many ways. It's the server (literally you) that instructs the browser to cache and don't cache. Check out an example of cache bursting/setting cache headers in AWS CloudFront. Based on your hosting provider, it's possible to set cache-headers to instruct browsers. Cache-Control and Expires are the key here.

Praveen Thirumurugan
  • 977
  • 1
  • 12
  • 27
3

With 'SwUpdate' of '@angular/service-worker' package, you can check the current version and available version of your application and can perform the action you want perform by checking the version.

Example:

import { SwUpdate } from '@angular/service-worker';

constructor(private swUpdate: SwUpdate) {}

//Here you can check the versions
this.swUpdate.available.subscribe((event) => {
   console.log('current version: ', event.current);
   console.log('available version: ', event.available);
   if (confirm('Software update avaialble.')) {
       this.swUpdate.activateUpdate().then(() => {
          //Perform your action here
          window.location.reload()
       });
   }
});
Tushar
  • 1,948
  • 1
  • 13
  • 32
2

Unlike the others' opinions, this is a good question and I want to suggest a new solution to meet your purpose.

In my opinion, don't use a new dependency inside your client scripts (Angular) since this is a browser specific issue and sometimes, clients may have ISP catching too. Both prevent the client being aware of new resources (different hashes). Simply, you need a helper to check whether a new version exists or not. So, why don't you create an API to check it if necessary and perform a hard reload on the client browser after his acceptance?

For example, you check and find out a new version is available, then you show a dialog with the text like below and an acceptance button to perform the hard reload :

A new version is available, Would you like to have it?
Changes are : blob blob blob

In this way, you can store the current version number on server side perhaps inside a json file.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70
  • really appreciate your perspective here. im not clear on one thing. i understand your idea of pinging an API endpoint on an interval. are you suggesting if i've built a new version of index,html i still prompt the users who are on contact.html to refresh? or will it work some how to notify the users of ONLY the resource that has been updated? – Alex Gordon Aug 01 '21 at 02:30
  • In SPA projects, the *index.html* is where we address the necessary resources, so updating that file makes sense here, even if the client browses the other pages. If you mean *how can I update some (or one) of the resources on a client browser?* Answer is, this is not doable on the **production** environment as you don't have a complete control over client browsers the same as the **development** environment. – Amirhossein Mehrvarzi Aug 01 '21 at 07:58
  • @AlexGordon Please let me know if I understood your question correctly. – Amirhossein Mehrvarzi Aug 02 '21 at 10:20
1

Keywords here are PWA and ServiceWorker. Just follow instructions on angular guide:

https://angular.io/guide/service-worker-getting-started

https://angular.io/guide/service-worker-communications

Vilmantas Baranauskas
  • 6,596
  • 3
  • 38
  • 50