Force updates on installed PWA when changing index.html (prevent caching) - reactjs

I am building a react app, which consists in a Single Page Application, hosted on Amazon S3.
Sometimes, I deploy a change to the back-end and to the front-end at the same time, and I need all the browser sessions to start running the new version, or at least those whose sessions start after the last front-end deploy.
What happens is that many of my users still running the old front-end version on their phones for weeks, which is not compatible with the new version of the back-end anymore, but some of them get the updates by the time they start the next session.
As I use Webpack to build the app, it generates bundles with hashes in their names, while the index.html file, which defines the bundles that should be used, is uploaded with the following cache-control property: "no-cache, no-store, must-revalidate". The service worker file has the same cache policy.
The idea is that the user's browser can cache everything, execpt for the first files they need. The plan was good, but I'm replacing the index.html file with a newer version and my users are not refetching this file when they restart the app.
Is there a definitive guide or a way to workaround that problem?
I also know that a PWA should work offline, so it has to have the ability to cache to reuse, but this idea doesn't help me to perform a massive and instantaneous update as well, right?
What are the best options I have to do it?

You've got the basic idea correct. Why your index.html is not updated is a tough question to answer to since you're not providing any code – please include your Service Worker code. Keep in mind that depending on the logic implemented in the Service Worker, it doesn't necessarily honor the HTTP caching headers and will cache everything including the index.html file, as it seems now is happening.
In order to have the app work also in offline mode, you would probably want to use a network-first SW strategy. Using network-first the browser tries to load files from the web but if it doesn't succeed it falls back to the latest cached version of the particular file it tried to get. Another option would be to choose what is called a stale-while-revalidate strategy. That first gives the user the old file (which is super fast) and then updates the file in the background. There are other strategies as well, I suggest you read through the documentation of the most widely used SW library Workbox (https://developers.google.com/web/tools/workbox/modules/workbox-strategies).
One thing to keep in mind:
In all other strategies except "skip SW and go to the network", you cannot really ensure the user gets the latest version of the index.html. It is not possible. If the SW gives something back from the cache, it could be an old version and that's that. In these situations what is usually done is a notification to the user that a new version of the app has been donwloaded in the background. Basically user would load the app, see the version that was available in the cache, and SW would then check for updates. If an update was found (there was a new index.html and, because of that, new service-worker.js), the user would see a notification telling that the page should be refreshed. You can also trigger the SW to check for an update from the server manually from your own JS code if you want. In that situation, too, you would show a notification to the user.
Does this help you?

Related

Delete old react build files in S3

I am deploying my react app in AWS S3 using AWS code build and caching through AWS CloudFront, But the bucket size is increased to more than 10GB within a month due to frequent deployment.
I tried to delete old build files while deploying but it is causing issues to users who has the old code cached in their browser. As the old files trying to get the previous version build but those are deleted, So it throws 404.
I tried to set no-cache for index.html file but that does not resolve this issue.
Does anyone face this issue?
#Nilanth here is what I do for the similar case:
My stack is also a React app (not so business critical) (it is used to offer article selection possibility for main content management flow..) app is build via CodeCommit - Codebuild to s3 Bucket using CodePipeline & buildspec.yml file. Build it triggered by commit of the repository. I faced a similar problem, that Cloudfront didn't "offer" the newest JS files for the browser (html) so it started to feel like Cache-issue.
I make pretty good solution like this:
Update Cloudfront Cache settings (edit behaviour, set to use "Use legacy cache settings") and set min / max TTLs to 0. (this helps for cache, so user should get newest versions immediately)
For JS / CSS file issue, I add "aws cli remove command" lines to buildspec.yml file like:
aws s3 rm s3://<s3_bucket>/static/js/ --recursive
aws s3 rm s3://<s3_bucket>/static/css/ --recursive
Set those as pre_build commands
Note: See that by removing JS files your application can not be used before new ones are offered again from folders /js & /css. I your application is business critical then u could think beyond this, since there will be 30 - 60s time that app can not be used. And what if build fails, then there is no js/css assets at all, well then you can trigger old build from Codebuild. This will require some effort to do business critical app's Devops work here..
To allow "remove" executions to S3 Bucket, you need to give Codebuild additional permissions. Go to build projects, see the environment's service role. Then go to IAM / roles / pick up the correct role name, and give more S3 permissions, e.g. AmazonS3FullAccess, its enough for sure..
I am not sure, that this is 99% correct solution from Cloudfront side, but it seems to avoid caching-problem and also the bucket size stays small.
-MM
There are many elements there that could throw 404 you'll need to prove one-by-one if they are working to find the root cause(s).
First I'd try the bucket itself, use <s3-bucket-url>/index.html and see if the file (in this case index.html ) exists.
Second the cloudfront, I'll assume the cloudfront distribution is configured correctly (i.e. / path redirects to /index.html). Also, every time you edit the bucket files, create an invalidation to speed up propagation.
Third, you'll need to tell your users to constantly hard reload the page, or use incognito, specially if your site is in constant development.

Reduce initial server response time with Netlify and Gatsby

I'm running PageSpeed Insights on my website and one big error that I get sometimes is
Reduce initial server response time
Keep the server response time for the main document short because all
other requests depend on it. Learn more.
React If you are server-side rendering any React components, consider
using renderToNodeStream() or renderToStaticNodeStream() to allow
the client to receive and hydrate different parts of the markup
instead of all at once. Learn more.
I looked up renderToNodeStream() and renderToStaticNodeStream() but I didn't really understand how they could be used with Gatsby.
It looks like a problem others are having also
The domain is https://suddenlysask.com if you want to look at it
My DNS records
Use a CNAME record on a non-apex domain. By using the bare/apex domain you bypass the CDN and force all requests through the load balancer. This means you end up with a single IP address serving all requests (fewer simultaneous connections), the server is proxying to the content without caching, and the distance to the user is likely to be further.
EDIT: Also, your HTML file is over 300KB. That's obscene. It looks like you're including Bootstrap in it twice, you're repeating the same inline <style> tags over and over with slightly different selector hashes, and you have a ton of (unused) utility classes. You only want to inline critical CSS if possible; serve the rest from an external file if you can't treeshake it.
Well the behavior is unexpected, I ran the pagespeed insights of your site and it gave me a warning on first test with initial response time of 0.74 seconds. Then i used my developer tools to look at the initial response time on the document root, which was fairly between 300 to 400ms. So I did the pagespeed test again and the response was 140ms. The test was passed. After that it was 120ms.
See the attached image.
I totally think there is no problem with the site. Still if you wanna try i would recommend you to change the server or your hosting for once, try and go for something different. I don't know what kind of server you have right now where the site is deployed. You can try AWS S3 and CloudFront, works well for me.

if make i changes in cpanel filemanager it doesn't really take effects on the web site

so as you see from the address I make changes in the public_html folder and I see the changes through the cpanel filemanager. however, it doesn't make any changes in the website and when I try to see the files of the website through my domain Ienter image description here can see that there are no changes happened . the changes is like creating a new folder or file or even renaming a file
This type of problems may occur due to server sided caching or it can be a simple bug which doesn't let the code to execute it on the website.
Or might be the server issues, for which you should contact the customer care of your hosting provider.
Try to clean cache of your browser and also disable the caching in your server if enabled.
Try these all things and you may see changes.

Do I need a service worker when my application often communicates with the server?

I'm working on a simple chat application that uses this frameworks, libraries: react, socket.io, express.
When a user opens the web app for the first time, he sees a login form, and after login, the server retrieves the list of all users and sends it to the client. When someone writes a new message, the server sends the message to all the clients.
As you can see, every part of the app depends on the server.
Does it make sense to use a service worker? Can it be at all?
As far as I know, a service worker is good at storing images, css, js files, and it help the users to use the app while they don't have internet connection.
But I do not know when everything depends on the server what can be done.
You have a great question.
You can most certainly use a Service Worker but most likely not to the extent some other apps could use it. You have outlined the problem yourself: your website depends on the server so it's not possible to make it offline or so. Some other websites could be made offline or could be made mostly offline showing some content without network connection and giving the full experience when connectivity comes back, but that doesn't sound like to be the case for your website.
Based on the description you've given, there's still something you could easily use Service Worker for, however. You've understand correctly that SW is very good at storing (caching) static assets and serving them from the device's cache without any network connectivity. You could use this feature and make your site faster. You could use a SW to proactively cache all the static assets of your site and have the SW return them from the local cache without requesting anything from the network. This would make your site a bit or much faster, depending on the user's connectivity (if the user has a slow 3G connection, then the SW would make the site super fast; if the user has a steady fiber or whatnot, then the difference wouldn't be that huge).
You could also make your site available offline without any internet connectivity. In that situation you would of course show the user a message saying "Hey, it seems like you're offline! Shoot! You need connectivity to use the app. We'll continue as soon as we get the bits flowing!" since this would probably make the user experience nicer.
So, in conclusion: you can leverage SW to make the initial loading of the site faster but you most likely won't get as much out of a SW configuration as some other site would get.
If you have any other questions or would like to have some clarifications, just comment :)
Sure you can benefit from having a Service Worker, it is universal enough to have an application for all kinds of applications and I don't agree it is only good for static assets.
It all depends on the actual requirements for you application, obviously. But technically there is no limitation that would prevent you from caching your users response in the Service Worker.
Remember that "offline" is a condition that happens in multiple circumstances - not only being far from the network coverage, but also outages, interferences, lie-fi or going through a tunnel. So it can as well happen intermittently during your app operation and it might make sense to prepare for it.
You can for example store your messages for offline in IndexedDB and for messages sent during that time, register a Background Sync event to send it to the server when the connectivity is back. This way users might still be able to use the app in the limited fashion (read the previously exchanged messages and post their own messages to be sent out later).

Access Sitecore DB from API in Console application

I would like to accesss the sitecore DB and items from console application like
Sitecore.Data.Database db = Sitecore.Context.Database
or
Sitecore.Data.Database db = Sitecore.Data.Database.GetDatabase("master")
how do I configure and setup my console application to access the DB as above?
Thanks Everyone for the suggestion, I am really interested in config changes, I used webservice, but it has very limited methods. For example, if I would like create an Item with the template and insert the item with prepopulated value, there is no such option. The reason I am looking for the console apporach is I would like to import the contents from XML or excel sheet and push those to the sitecore tree, eventually use the scheduled task to run the console app periodically. I do not want to copy the entire web.config and app_config. If anyone has already done this, could you please post your steps and necessary config changes?
You have two options I think:
1) Import the Sitecore bits of a website's web.config into your console application's app.config, so that the Sitecore API "just works"
I'm sure I read a blog post about this, but I can't find the reference right now. (I will have another look) But I think the simple but long winded approach is to copy all of the <sitecore/> element and all the separate files it references. I'm fairly sure you can whittle this down to a subset of the config required for data access with a bit of thinking.
2) Don't use the Sitecore API directly, connect to a web service that exposes access to it remotely.
There are a few of these that already exist. Sitecore itself exposes one, Sitecore Rocks has one, and Hedgehog TDS has one too. And you can always write your own (since any web service running inside the Sitecore ASP.Net app can make database calls and report values back and forth - just remember to consider security if this web service might end up exposed externally for any reason)
John West links to some relevant stuff here:
http://www.sitecore.net/Learn/Blogs/Technical-Blogs/John-West-Sitecore-Blog/Posts/2013/09/Getting-Data-Out-of-the-Sitecore-ASPNET-CMS.aspx
-- Edited to add --
I've not found the blog post I remember. But I came across this SO thread:
Accessing Sitecore API from a CLI tool
which refers to this blog post:
http://www.experimentsincode.com/?p=232
which I think gives the info you'll need for option 1.
(And it reminds me that, of course, when you copy the config stuff you have to copy the Sitecore binaries into your app's folder as well)
I would just like to expand on #JermDavis' post and note that Sitecore isn't a big fan of being accessed when not in a web application. However, if you still want to do this, you will need to make sure that you have all of the necessary configuration settings from the web.config and App_Config of your site in your console application's app.config file.
Moreover, you will never be able to call Sitecore.Context in a console application, as the Sitecore Context sits on top of the HttpContext which means that it must be an application and have a valid request for you to use it. What you are looking for is something more along the lines of Sitecore.Configuration.Factory.GetDatabase("master").
Good luck and happy coding :)
This sounds like a job for the Sitecore Item Web API. I use the Sitecore Item Web API whenever I need to access Sitecore data from the master database outside the context of the Content Management server or outside of the context of the Sitecore application. The Web API definitely does not allow you to do everything that the standard Sitecore API does but it can act as a good base and I now extend upon the Web API instead of writing my own custom web services whenever possible.
Thanks to JemDavis's advise.
After I copied the configuration and made changes to config section to get rid of conflicts. I copied almost all of Sitrecore, analytics and lucene dlls, it worked great.
Only thing you have to remember is, copy the app_config folder to the same location where your dlls are.
Thanks again JemDavis....

Resources