How to configure service workers with create-react-app - reactjs

I am creating a ReactJS app with the create-react-app utility. How could I configure it to use a file that will contain a service worker?
EDIT:
From Javascript side is clear for me, add the registration in my index.js:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./service_workers/sw.js')
.then(function(registration) {
// Registration was successful...
}).catch(function(err) {
// registration failed ...
});
}
Then my configuration in my service worker file (that for me is in service_wokers/sw.js):
self.addEventListener('install', function(event) {//my code here...});
self.addEventListener('activate', function(event) {//my code here...});
self.addEventListener('fetch', function(event) {//my code here...});
When I run this the console shows:
ServiceWorker registration failed: DOMException: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script.
The file is not there as I am not configuring Webpack to do that. So I am trying to copy the sw.js file with the ouput with:
test:
/\.(js)$/,
loader: "file?name=[path][name].[ext]&context=./service_workers",
include: '/service_worker'
I think there is no need to say that I am totally new to Webpack.

for people who are still struggling on this. please refer https://create-react-app.dev/docs/making-a-progressive-web-app.
service workers are configured in CRA and will handle the caching for you! You just need to change :-
serviceWorker.unregister();
to
serviceWorker.register();
in your src/index.js file;
Also, service workers work on production mode only so make sure to build your application and serve it locally before testing your app for service workers.
npm i http-server -D
then add this to package.json, in your scripts.
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start-sw": "http-server ./build"
}
now run :-
npm run build && npm run start-sw
hope it helps!

First, you have to do some changes in package.json:
Changes in package.json:
{
"name": "create-react-pwa",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.7.0",
"sw-precache": "^4.2.2"
},
"dependencies": {
"react": "^15.4.0",
"react-dom": "^15.4.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build && sw-precache --config=sw-precache-config.js",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Then create a js file "sw-precache-confi.js" in the root folder of your project:
sw-precache-config.js:
module.exports = {
stripPrefix: 'build/',
staticFileGlobs: [
'build/*.html',
'build/manifest.json',
'build/static/**/!(*map*)'
],
dontCacheBustUrlsMatching: /\.\w{8}\./,
swFilePath: 'build/service-worker.js'
};
Changes in index.html, Add service worker in index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('/service-worker.js');
});
}
</script>
</body>
</html>
After doing all the things run npm install at root of project then npm start.
Further reading: https://github.com/jeffposnick/create-react-pwa#what-additional-changes-might-be-needed

I would recommend this library called cra-append-sw to add custom service workers to CRA.
Most of the details of how to use it are in the npm page, but simply put you just need to install the library (npm i --save cra-append-sw).
Make a few changes to your package.json:
"start": "react-scripts start && cra-append-sw --mode dev ./public/custom-sw-import.js",
"build": "react-scripts build && cra-append-sw --skip-compile ./public/custom-sw-import.js"
And finally create a file in your public folder called custom-sw-import.js and all of the service worker code you write there will simply be appended to cra's service worker.
I can verify this works since I applied the same principle to make my website www.futurist-invenzium.com which gives a demo of all the features provided by PWA's.
I also found this blogpost to be helpful if you want a more indepth answer : https://medium.freecodecamp.org/how-to-build-a-pwa-with-create-react-app-and-custom-service-workers-376bd1fdc6d3

Service workers and offline functionality should be included now in create-react-app builds, see this pr

Related

Electron react app hot reloading from src folder not working

I'm trying to use the hot reload feature in development mode of a react electron app.
It use to work well but I'm having issues with the latest electron version 15+.
I am able to run the app from the build folder but anytime I want to make a change I need to run the build command therefor the hot reloading is not working.
I have change the package.json path to use the public folder. But I get a blank page. however if I make a change to the main.js folder, the app reload but not when I make a change within the src folder of the app itself.
In my package.json if I use the public folder the app is not loading. It only loads when I use the build folder.
"version": "0.1.0",
"private": false,
"main": "build/main.js",
"homepage": "./",
"files": [
"public/**/*",
"node_modules/**/*"
],
"scripts": {
"electron-dev": "set ELECTRON_START_URL=http://localhost:3000 && electron . --overwrite --asar=true --platform=win --arch=x64 --icon=icons/icon.png --prune=true --out=build",
"electron": "electron .",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"dist": "electron-builder --win"
},
"devDependencies": {
"electron": "15.3.0",
"electron-builder": "^22.13.1",
"electron-reload": "^2.0.0-alpha.1",
"electron-reloader": "^1.2.3"
}
In my public/main.js file;
require('electron-reloader')(module,
{
debug: true,
watchRenderer: true
});
const startUrl = url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
});
I can also see the watcher in the console;
Watched paths: {
'..': [
'public'
],
'.': [
'assets',
'favicon.ico',
'icon.png',
'index.html',
'logo-black.png',
'logo.png',
'logo.svg',
'main.js',
'manifest.json',
'package.json',
'preload.js',
'robots.txt'
],
assets: [...]
It seams like the public folder is not being watched at all. When ever I make a change to my app inside the src folder. nothing get's picked up. The src folder is not being watched/
What should I look for?
Please comment if you would like to see more code.
[UPDATE]
The start url is not getting picked up in the .env nor in the inline command.
As a temporary solution I am running the build & electron.
Very counter productive!
One potential hacky solution you could use is just using nodemon, and make it re-launch electron each time you change any content inside the src directory. In order to do this you would have to run npm install --save-dev nodemon. Then in your packages.json put in the following
"dev": "NODE_ENV=development nodemon --watch ./src/**/* --watch . --exec 'npm run electron'"
With respect to the actual question, why are you using electron-reloader over just using electron-reload. It is easy to setup, just by adding the following to your code
require('electron-reload')(__dirname, {
electron: path.join(__dirname, 'node_modules', '.bin', 'electron'),
hardResetMethod: 'exit'
});

Framer motion error after install the package and import

I get this error after installing and importing framer-motion in the middle of my project
Can't import the named export 'Children' from non EcmaScript module (only default export is available)
I have tried to install after npx create-react-app and it works fine. This only happened if I install the package in the middle. This is my project
First, install the react-app-rewired NPM package as a dev dependency.
Then, in package.json, update the start, build, and test scripts to replace react-scripts with react-app-rewired:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
Finally, paste this into a file in the project root directory named config-overrides.js:
module.exports = function override(webpackConfig) {
webpackConfig.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto"
});
return webpackConfig;
}
Now npm start / yarn start should work.

When you run, npm start, how is index.js picked up for running

I created a react project using
create-react-app react-app
Then a react-app was created with all the folders. (Using Visual Studio Code)
Then deleted the "src" folder using rimraf
Then opened index.html and deleted all its content.
Then ! and enter and created the HTML boilerplate code in index.html
Then created following div in it,
<div id="root">
React Component goes here....
</div>
Now created "src" folder and in it created "index.js" with following content,
import React from "react";
import ReactDOM from "react-dom";
import "../node_modules/bootstrap/dist/css/bootstrap.css";
import HelloComponent from "./components/helloComponent";
import BindingComponent from "./components/bindingComponent";
ReactDOM.render(
<React.Fragment>
<HelloComponent name={"Rohit"} />
<HelloComponent />
<BindingComponent></BindingComponent>
</React.Fragment>,
document.querySelector("#root")
);
In "package.json" i have the following in scripts section,
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
Also created React Components in the components folder
Now when I run using npm start, how does it call index.js ???
npm start is a short-hand for npm run start, which calls the react-scripts start script.
If we investigate the scripts in their github repo, we find that the entry is configured in their webpack.config.js file:
entry:
isEnvDevelopment && !shouldUseReactRefresh
? [
webpackDevClientEntry,
paths.appIndexJs,
]
: paths.appIndexJs,
The paths are defined in paths.js file:
module.exports = {
dotenv: resolveApp('.env'),
appPath: resolveApp('.'),
appBuild: resolveApp('build'),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
appTsConfig: resolveApp('tsconfig.json'),
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
publicUrlOrPath,
};
react-scripts add it to body. So you need to add it.

Erro when deploying to heroku my react app

I create an app with react, this app has a few fetch that gets data from mongodb. when I finished the app and everything was working I deployed to heroku but I had the error of Invalid host Header, so after looking for a solution i found out that i should erase proxy://localhost:5000 from package.json in client folder. Now you can see the app in heroku but in heroku and in my pc the fetch are returning the index.html. all of them. If i put the proxy back the fecth in my computer work but in heroku appears again de Invalid host Header error. Please help me
here is the errorcannot find module
this is my scripts in package.json in root folder"scripts": {
"server": " nodemon server",
"test": "echo \"Error: no test specified\" && exit 1",
"start": " concurrently \"npm run server\" \"cd client && npm start\"",
"heroku-postbuild": "NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run build --prefix client"
}
this is in the server.js that is outside of src
if (process.env.NODE_ENV === "production") {
// Static folder
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
I created a Procfile like others say to do
web: node my-app/server.js
and here is my github repository
github repository

Angular JS and Springboot integration using rest api

I am trying to connect two different small applications. Client application is in Angular 5 and Server side is in Spring boot. Angular 5 application works fine on localhost:4200/register port and Spring boot (Server Side) works fine on port localhost:8080/api/demo.
For integration I have used added a proxy.conf.json file in Angular Application. I have updated package.json script also. Followed the instruction on the website: http://javasampleapproach.com/java-integration/integrate-angular-4-springboot-web-app-springtoolsuite#5_Import_Angular4_client_project_to_SpringToolSuite.
Both the projects are in same workspace.
Angular project files added for integration--->
proxy.conf.json :
{
"api": {
"target": "http://localhost:8080",
"secure": false
}
}
Package.json:
{
"name": "my-new-project",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
SPRINGBOOT --->
Rest API:
package com.example.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class DemoController {
//#RequestMapping(method = RequestMethod.GET, value = "/api/demo")
#RequestMapping("/api/demo")
public String demo() {
return "Hello Demo Application";
}
}
So I want to access url like localhost:4200/api/demo (localhost:4200 is angular and "api/demo" comes from Springboot )
Can someone please guide me here in the right direction. TIA
As said in docs either set server.port as system property using command line option to jvm --server.port=8090 or add application.properties in /src/main/resources/ with
server.port = 4200

Resources