What best solution for prevent browser cache file in react - reactjs

My problem is
when I deploy new version react web to production
some user browser display old version from previous deploy
My user have to press ctrl+f5 for clear cache browser then I think which bad solution
please suggest best solution for me thx bro.

This could be because your web server is setting a cache control response header, which is set to a large value. Could you check the value in devtools?
A simple explanation of what cache control does is it tells the browser that the browser can use the cached resource upto n minutes. So only after n minutes will the browser send a new request for the resource.
Since you have a react app (a web app), the browser requests for index.html, and it will subsequently fetch the js bundle for your react app.
When you push an updated version, the browser doesn't know that there is an update. Since the index.html was cached, it continues to use it. Until the cache time expires, and then it will fetch again and this time it will get the latest js bundle.
Based on your server, you will need to figure out how to set the cache-control header for index.html to be of value no-cache. Here is an example of how I set it up in firebase hosting,
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint",
"npm --prefix \"$RESOURCE_DIR\" run build"
]
},
"hosting": {
"public": "build",
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
"headers": [
{
"source": "/service-worker.js",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
},
{
"source": "/index.html",
"headers": [{ "key": "Cache-Control", "value": "no-cache" }]
},
{
"source": "/static/**/*",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Since create react app automatically configures the webpack build to generate static files with different hashes in the filename, it is fine to set a large cache value for it.

That occurs because, by default, the service workers do cache, so you should check your react project index.js file and check to see if services workers are registered. serviceWorker.register().
If it is registered then Unregister the service worker serviceWorker.unregister().
The above being quite drastic as a method, since it could affect your user experience what is recommended is that you configure your PWA to suit your particular caching needs. Follow this resource "https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker" for more about playing with service workers.
In case you need caching for your application, your backend sends appropriate response headers.

Related

app configuration appId is missing from Firebase Hosting reserved URL "/__/firebase/init.js" on localhost only

I recently started seeing an error on my localhost version of Firebase hosted website in Chrome:
Uncaught FirebaseError: Installations: Missing App configuration value: "appId" (installations/missing-app-config-values).
I'm not sure what has triggered this. I'm using the Firebase Hosting Reserved URL method to include the firebase config and it's had no issues until recently.
The config is loaded via <script src="/__/firebase/init.js"></script>.
This is the config file at that URL:
if (typeof firebase === 'undefined') throw new Error('hosting/init-error: Firebase SDK not detected. You must include it before /__/firebase/init.js');
var firebaseConfig = {
"projectId": "remotesoc...",
"databaseURL": "https://remotesoc...firebaseio.com",
"storageBucket": "remotesoc...appspot.com",
"locationId": "us-central",
"apiKey": "AIzaSyC3K7HT9- ... ",
"authDomain": "remotesoc...firebaseapp.com",
"messagingSenderId": "43697..."
};
if (firebaseConfig) {
firebase.initializeApp(firebaseConfig);
}
As you can see the "appId" value is missing. I'm almost certain this used to be there.
I've built and deployed the app multiple times which is listed as the way to ensure that Firebase has the correct config values for the project.
The app is definitely using the correct project, and has a reference to the hosting site in the firebase.json
{
"database": {
"rules": "database.rules.json"
},
"functions": {
"source": "functions"
},
"hosting": {
"site": "remotesoc...",
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
}
}
I've run >firebase init several times in an attempt to reset the CLI.
The deployed site has no missing config vars and is working perfectly this is only on localhost.
I could revert to using an included config file, however that negates the benefits of having the reserved URLs inject the values for you.
Any help would be appreciated.

manifest.json 404 (Not Found)

I have a react application that works fine locally. However after I deploy to Azure Web App I get following error in console:
https://xxx.azurewebsites.net/manifest.json 404 (Not Found)
I can see the purpose is when people install the app on a mobile, then REACT renders differently dependent on the devise. I can also see it is located in the index.html file:
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
As my app is a web site does this file has any effect? Can I just delete it or should I try to solve the error? And if yes how?
Are you using create-react-app?
The manifest makes only sense when you want that your users can install your app so it works without an internet connection e.g. Thats in the end a Progressive Web App. So for you it's probably fine to just remove the line.
(under which path does your app serve? Maybe you have to specify a base path: https://create-react-app.dev/docs/deployment/#building-for-relative-paths
have you tried this?
go to angular.json
add manifest.json location in assets
"assets": [
"src/favicon.ico",
"src/assets",
"src/manifest.json"
],
restart dev server using
ng serve
For production apps, you have to target build for the public in firebase.json like the following:
{
"hosting": {
"public": "build", // Here you have to make changes.
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
],
"headers": [
{"source": "/service-worker.js", "headers": [{"key": "Cache-Control", "value": "no-cache"}]}
]
}
}

Firebase SPA rewrite rules not redirecting to index.html

I just started to build a Single-Page App on Firebase Hosting using AngularJS framework. I have run firebase init and chosen to rewrite all urls to /index.html as shown below:
"hosting": {
"public": "public",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
I have my partial view templates stored in the following folders:
public/templates/home/dashboard.html
public/templates/courses/default.html
My Angular routings are working correctly and have my public/index.html checks for authorized access, including those partial views, and redirect the user to login view if the user has not been authenticated.
However, when I try to paste the URL of my template HTML files directly onto the browser address bar, Firebase does not redirect it to /index.html:
http://localhost:5000/templates/home/dashboard.html
http://localhost:5000/templates/courses/default.html
All the above template files are loaded on the browser and viewable by any unauthorized users who know the URLs of these template files. I have tried to add the following rules to my firebase.json file but none of them work:
Test #1:
"rewrites": [
{
"source": "**",
"destination": "/index.html"
},
{
"source": "/templates/**/.*",
"destination": "/index.html"
}
]
Test #2:
"rewrites": [
{
"source": "**",
"destination": "/index.html"
},
{
"source": "/templates{,/**}",
"destination": "/index.html"
}
]
NOTE: I did restart firebase serve for every attempt, but I'm not sure if the cache will affect this type of testing. I also don't know how to clear the server cache either.
My questions are:
What is the correct way to write the url rewrite rule in order to redirect users to /index.html when direct accessing to these partial view templates?
If there is no way to prevent direct access to partial view templates through the Firebase url rewrite rules, is there any other way that I can prevent this for security purposes?
Firebase hosting will serve static content with priority above dynamic rewrites. See this hosting order.
If you don't want those views accessed directly, you could move them to a cloud function and setting up your hosting to reroute "templates" to serve that cloud function. Then you can configure your cloud function to provide/deny access as needed.
Use redirects instead of rewrites
"hosting": {
"redirects": [ {
"source": "/foo",
"destination": "/bar",
"type": 301
} ]
}
Add ** to source to append destination with additional URL string.
E.g.
"hosting": {
"redirects": [ {
"source": "/foo**",
"destination": "/bar",
"type": 301
} ]
}
Results in /foo?var=bar redirecting to /bar?var=bar
See Configure redirects for more info.

Firebase URL rewriting to both functions and destinations

I am building a React/Redux app and trying to rewrite to one Firebase function, with all other URLs rewriting to index.html.
Right now, I am only able to get a URL to rewrite to the function when I perform the "empty cache and hard reload" on my Chrome browser.
This is my firebase.json file.
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "build",
"rewrites": [
{
"source": "/Photos/**", "function": "getPhoto"
},
{
"source": "**", "destination": "/index.html"
}
]
}
}
For example, when I go to https://nameofmyapp.firebaseapp.com/Photos/2017/October/2/12345, I am routed to the root directory (index.html), when I expect to be directed to the getPhoto function.
The only time I am able to get to the "/Photos/**" rewrite URL is if I first enter the https://nameofmyapp.firebaseapp.com/Photos/2017/October/2/12345 URL in the browser, then perform a "Empty Cache and Hard Reload" in Chrome. This is the only time that the function is executed for me. (Not sure if this is related to the service-worker behavior?) Even so, on normal refresh at that URL, I end up back in index.html again.
Can anyone let me know what I am missing?
I've just posted an answer for a very similar problem
You need to change your "single app rewrite" :
{
"hosting": {
"public": "build",
"rewrites": [
{
"source": "/Photos/**", "function": "getPhoto"
},
{
"source": "!/Photos/**", "destination": "/index.html"
}
]
}
}
Instead of redirecting everything on index.html (as do " ** "), this rule redirect everything that is not in the Photos folder and subfolders.

Not including old JS in Firebase hosting causes service worker white screen

The build process of create-react-app (yarn run build) deletes the old static JS file before building anew. When deployed to Firebase Hosting, the old JS files are not included and are no longer served.
However after visiting the old version the Service Worker (built by sw-precache and sw-precache-webpack-plugin, included by default in CRA) has cached the old HTML, which includes the old JS file, which is no longer served, so I get a white screen and an error in the console, which is only fixed by clearing cache and reloading.
Am I doing something wrong?
The issue was that my Cache-Control headers were too short, meaning that my JS file wasn't being cached for long enough, causing the browser to re-request it upon a reload and not find it until the Service Worker updates.
Resolution: have long Cache-Control headers
I resolved this slightly differently to Marks answer.
Within your firebase.json file you need to make sure the Service Worker and the index.html file aren't cached. For me it was the index.html being cached which was the main issue.
Webpack changes the chunks name with each build and removes the previous version from /build. Therefore when they don't get uploaded and your browser looks at the cached index.html file it causes the white screen and the error.
I ended up with the following in my firebase.json file. Hope that helps
{
"hosting": {
"public": "build",
"headers": [
{
"source": "/service-worker.js",
"headers": [
{
"key": "Cache-Control",
"value": "no-store"
}
]
},
{
"source": "/index.html",
"headers": [
{
"key": "Cache-Control",
"value": "no-store"
}
]
}
],
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
],
"source": "functions"
},
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
}
}

Resources