Unknown service worker is being registered - reactjs

I am using the built in service worker found in create-react-app. I have registered it in index.tsx with serviceWorker.register();. If I create a production build and run it, or run it on heroku server, I successfully get a service worker registered. However, upon further inspection under the Application tab in the dev tools, I see service-worker.js as the name of my service worker, which is NOT what mine is called. Inspecting the worker, it is also very different code from that of the default create-react-app, the contents are below -
/**
* Welcome to your Workbox-powered service worker!
*
* You'll need to register this file in your web app and you should
* disable HTTP caching for this file too.
* See https://developers.google.com/web/tools/workbox/guides/service-worker-checklist
*
* The rest of the code is auto-generated. Please don't update this file
* directly; instead, make changes to your Workbox build configuration
* and re-run your build process.
* See https://developers.google.com/web/tools/workbox/modules/workbox-build#full_generatesw_config
*/
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.740fac3abc44b443a1d2c6ac9789a1e1.js"
);
self.addEventListener('message', (event) => {
if (event.data && event.data.type === 'SKIP_WAITING') {
self.skipWaiting();
}
});
workbox.core.clientsClaim();
/**
* The workboxSW.precacheAndRoute() method efficiently caches and responds to
* requests for URLs in the manifest.
* See https://developers.google.com/web/tools/workbox/modules/workbox-precaching
*/
self.__precacheManifest = [].concat(self.__precacheManifest || []);
workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/index.html"), {
blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/],
});
Meanwhile the create-react-app service worker should look like this.
I am wondering where this other service worker is coming from, and how can I make sure my own is registered instead?

I haven't read them both, but it seems like maybe yours was compiled/transpiled by webpack into that one.
https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/package.json
That service worker cdn is workbox v4.3.1 which you can see in the above package.json is a dependency. It is then used in a webpack config file.
Typescript is a way to write JavaScript, but it needs to be changed to JavaScript before it can be run in most cases.
Edit: where it's used
https://github.com/facebook/create-react-app/blob/589b41aecaa10d410713794f66a648bf3a72fb62/packages/react-scripts/config/webpack.config.js#L674
https://create-react-app.dev/docs/making-a-progressive-web-app/
And in conclusion: serviceWorker.ts is not a service worker. It is used to register one. The one you see on Heroku? That is the service worker you registered for, create-react-app's default one.

In my case:
I was using react.js and create-react-app.
I adopted new service-worker.js in public/
and my problem was that when I used yarn build to build react app, my service-worker.js is replaced with above file you copied(workbox service worker)
So I just made new file (public/worker.js) and replace
const swUrl = "${process.env.PUBLIC_URL}/service-worker.js";
with
const swUrl = "${process.env.PUBLIC_URL}/worker.js";
in src/serviceWorker.js > register > window.addEventListener('load')
and finally I can register my own service worker to my app

Related

React App doesn't make proxy calls after deployed to azure

Simple setup:
React App created with create-react-app
ASP.NET Core web API - a couple of controllers (currently no security until I make it work)
Both the API and Application are deployed to Azure.
When I run the app locally with configured proxy (I contact the deployed API on Azure) it works correctly makes the calls.
If I try the API directly from my machine it works too (PostMan for example)
When I open the deployed React APP - The application loads correctly but the call to the API doesn't get proxy(ed). What I mean it's not returning 404, 403 - it returns status 200, but makes the call to the app itself instead of proxy the request to the API.
I've tried both using "proxy" configuration in package.json as well as using "http-proxy-middleware". Both cases work with locally running app, but not deployed. Here is the configuration of the proxy:
module.exports = function (app) {
app.use(
'/api',
createProxyMiddleware({
target: 'https://XXXXXX.azurewebsites.net',
changeOrigin: true,
})
);
};
I suppose it's something related to the configuration of the node server used when I deploy to azure, but I don't have a clue what.
I've used the following tutorial for deployment: https://websitebeaver.com/deploy-create-react-app-to-azure-app-services
But as seen from content there is no proxy part in it.
After long troubleshooting I realize the issue was due to wrong understanding of the proxy configuration.
So I was not realizing the proxy configuration is respected only in debug mode and totally ignored into prod build. And of course while debugging the issue I was not realizing the Azure Deployment pipe was doing production build. So the resolution was to detect the production/dev on application layer and inject correct URL.
Here I hit another issue - process.env.NODE_ENV, which I was using to distinguish between development and production was undefined into my index.tsx - it was available in App.tsx and all its children, but not in index.tsx where my dependency container was initialized.
What resolved my issue is package called dotenv. Then I've just imported it into index.tsx and the process.env was available.
import * as dotenv from 'dotenv';

Serve react project on dev througth proxy

I've split my react application in 3 different projects, using CRA for all of them, auth, X and Y. User is first sent to auth, then I redirect him to either X or Y based on some info.
It works perfectly on PRODUCTION environment (because they run on the same domain), but on dev, X and Y failed to authenticate the user, because they run on different ports (different domains) the data in local storage is not shared between auth, X and Y.
I've tried to find a way to use a reverse proxy (http-proxy) to host the React dev servers on the same domain, but failed too, because the services could not find the assets/static folder, resulting in 404. Also tried http-proxy-middleware, as it is recommended on the CRA docs page, but failed to do so. Is there an easier way that I'm not seeing?
Edit: Found something new, but also failed. Used react-rewired to override CRA scripts, to use PUBLIC_PATH on DEV, but now my bundle.js returns an index.html file.
The following code does redirect to the accordingly react project, but the assets are requested to the wrong path.
const apiProxy = httpProxy.createProxyServer();
app.all("/login/*", function(req, res) {
console.log('redirecting to Login');
apiProxy.web(req, res, {target: servers.login});
});
app.all("/implementacao/*", function(req, res) {
console.log('redirecting to Implementation');
apiProxy.web(req, res, {target: servers.implementation});
});
So I used react-rewired to change the public path
const {
override,
} = require('customize-cra');
module.exports = {
webpack: override(
(config) => {
config.output.publicPath = '/login/';
return config;
},
),
jest: config => {
return config;
},
devServer: configFunction => (proxy, allowedHost) => {
return configFunction(proxy, allowedHost);
},
paths: (paths, env) => {
return paths;
}
};
Now, the assets requests are made correctly to /login/, but nothing the dev server always return an index.html file.
Even with react-app-rewired, to override config, and use publicPath on dev, the assets will not be served from the publicPath.
There is already a pull request on CRA to use PUBLIC_URL in dev mode.
Is there an easier way that I'm not seeing?
Another approach would be to use multiple React Single Page Applications (SPAs) inside one application, see crisp-react. E.g. instead of 3 CRAs in 3 applications/projects have 3 SPAs in one application/project. The backend surely can get data from other backend servers transparently for each SPA.
how do I migrate from a set of existing CRA projects to using crisp-react ?
Background
crisp-react comes with two stock SPAs called ‘First’ and ‘Second’. Both render some explanatory/sample UI.
Migration overview
1.Pick one CRA project and migrate it to the ‘First’ SPA. When finished, you have two CRAs left and two crisp-react SPAs: ‘First’ (renders your UI) and ‘Second’ (still renders the sample UI). Rename the ‘First’ SPA to give it more meaningful name.
2. Pick another CRA and migrate it. When finished, you have one CRA left and two crisp-react SPAs both rendering your UI.
3.Modify crisp-react to add the third SPA and then migrate the remaining CRA to the third SPA.
Migration steps (sketch)
1.1 Follow crisp-react Getting Started.
1.2 The landing page of the First SPA is rendered by crisp-react/client/src/entrypoints/first.tsx
The landing page of the CRA is rendered by src/index.tsx
Replace the content of the former with the latter.
1.3 The first CRA consists of React components: src/App.tsx and others you added. Copy the components to crisp-react/client/src/components/from-first-cra/
1.4 Ensure crisp-react client app compiles: From crisp-react/client/ execute: yarn compile
1.5 Ensure crisp-react client app builds: From crisp-react/client/ execute: yarn build
1.6 Ensure crisp-react client looks ok without backend data: see client Usage Scenarios.
1.7 Get the backend (e.g. Express) involved: see backend Usage Scenarios.
1.8 Milestone reached: browser can be pointed to backend (Express) and get from it html files and bundles - which results in the first SPA rendering initial UI (to the extent possible without data supplied via API enpoints).
1.9 Decide how the the first SPA will get data from API. 3 basic choices here:
- the API endpoints are implemented in Express so you can retire your backend servers
- Express does expose API endpoints but acts as a reverse proxy getting data from your backend servers
- Express knows nothing about API and data supplied by backend servers that are queried directly by the components inside the first SPA.
2.1 Second SRA
as above
...

build of create-react-app --typescript api call returns You need to enable JavaScript to run this app. on deployed?

it works perfectly fine on localhost but i cannot make api request when deployed, the api call returns
You need to enable JavaScript to run this app.
i have npm run build the app, my server sends file to it:
if (process.env.NODE_ENV === 'production') {
// Serve any static files
this.app.use(express.static(path.join('../../frontend/build')));
// Handle React routing, return all requests to React app
this.app.get('*', (req, res) => {
res.sendFile(path.join('../../frontend/build', 'index.html'));
});
}
this works perfectly fine with create-react-app but not in create-react-app --typescript? help?
The error message seems to imply that javascript is not enabled in your browser. Which means that the change might be in system configuration/settings rather that the build.
Each browser has a different way of enabling/disabling javascript but you can search for it on google and change your settings accordingly. For example the procedure for Firefox is detailed here: https://www.technipages.com/firefox-enable-disable-javascript

React - Unregistering a registered service worker

I'm developing a React web-app (https://timatorg.is - in case someone wants to look at the response headers) created using create-react-app. At the time it was created, a service worker was registered by default and I didn't really think much about it. The app is hosted at Netlify and the DNS is at Cloudflare.
Now when deploying updates to the website, users that have visited the site before always get the same version of the app and I'm pretty sure it's because of the service worker. But the strange thing is that it's only "https://www.timatorg.is" that is causing issues, not "https://timatorg.is"
I've read a lot of material about how to unregister an already cached service worker but all I've found is a solution that the client can perform in his/her browser but nothing that I can do to solve this for all of our clients.
So my question is, how do I get rid of the service worker? Or more general, push the latest update of our app to our clients?
You can change to the following in your index.js file, like the comment in a new Create React App project says:
import { unregister } from './serviceWorker';
// ...
unregister();
Add the following code into your index.js file:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
if (caches) {
// Service worker cache should be cleared with caches.delete()
caches.keys().then(async (names) => {
await Promise.all(names.map(name => caches.delete(name)));
});
}
});
}

ServiceWorker is not updating, goes to skipwaiting in React app

When I make a new production build of React app, new services worker installs but goes to skipwaiting state. So I have to hard reset cache on every build that is not good on live site.
I can't tell to every client, "please clear your cache to see latest". If I remove registerServiceWorker() from index file then build production do not detect my routes so it redirects to 404.
I used react-rewired-app boilerplate for my project and faced issue in that. Now I resolved that with a bunch of code in config-overrides.js file
config.plugins.forEach((obj) => {
if (obj.config) {
if (obj.config.clientsClaim) {
obj.config.skipWaiting = true
}
}
});

Resources