So create-react-app includes service worker functionality by default, which is lovely - all my static assets get cached for offline use out of the box. Cool, but now I want to take things a bit further and use indexedDB to cache some dynamic content.
Problem is, there's no service-worker.js file to modify. It gets generated during the build process.
Is there a way to add additional logic without ejecting create-react-app or redoing all the nice static caching stuff?
As you've observed, create-react-app's config is locked down, and the service worker logic is entirely defined in the config.
If you'd rather not eject but you want some customization, another option is to modify the create-react-app build process to explicitly call the sw-precache CLI after the normal build has completed, overwriting the service-worker.js that create-react-app generates by default. Because this involves modifying your local package.json, it doesn't require ejecting first.
There's some info on this approach here, and the general idea is modifying your npm scripts to look something like:
"build": "react-scripts build && sw-precache --config=sw-precache-config.js"
With sw-precache-config.js configured based on your needs, but including
swFilePath: './build/service-worker.js'
to ensure that the built-in service-worker.js is overwritten.
I had the same problem and without doing eject, I could replace the default service-worker with workbox-generated one to add runtime caching webfonts, api calls, etc.
install workbox-build
prepare src/sw-template.js to add your registerRoute calls
prepare /build-sw.js to copy workbox file to 'build' folder and injectManifest
modify package.json scripts to run above build-sw.js
modify src/registerServiceWorker.js to replace the default one
You can find detailed file changes here.
Related
I'm in WSL2, and my react app does not update any changes at all, only updates when re-running "npm start"
I've tried "npm install react-dotenv" and creating an .env file with
FAST_REFRESH=false
CHOKIDAR_USEPOLLING=true
doesn't work
tried in the package.json
"start": "CHOKIDAR_USEPOLLING=true react-scripts start"
doesn't work
any suggestions? I don't even mind manually refreshing the browser, it's just that it won't update unless I restart the whole thing.
You do not have to install an additional dotenv package since Create-React-App already supports environment variables natively. However if you use environment variables, you need to prefix them with REACT_APP. e. g. REACT_APP_MY_VARIABLE.
Also note: Whenever you update an environment variable you have to restart the app.
Take a look at the official CRA docs.
Now for the reloading problem. There are a couple of possible solutions:
Add a .env file to your project without third party package and
define a variable named FAST_REFRESH=false. (CRA advanced
configuration)
If you are using a Virtual Machine try adding CHOKIDAR_USEPOLLING=true to your .env file.
There is another common problem in CRA ^17.0.1 with hot reloading (Github issue - Hot Reload stopped working with React "^17.0.1")
if (module.hot) module.hot.accept();
Finally (and this is the most likely solution in my opinion) try to move your project folder to somewhere, where npm can automatically recompile in WSL. E. g. move project from your desktop to your actual home directory.
I'm currently working on a React project, initiated with Create React App. Currently, to compile, I am using the default command npm run start which runs react-scripts start.
I have a bunch of #typescript-eslint rules that force me to have a clean code before delivering it and deploy it. However, while I'm developing, I may have some unused variables and still want to compile to see if something else works.
Is there a command to force the compilation, while ignoring some or all #typescript-eslint rules?
This is a CRA configuration that can be overwritten. In an .env file, you can add these variables
TSC_COMPILE_ON_ERROR=true
ESLINT_NO_DEV_ERRORS=true
Here is the full list https://create-react-app.dev/docs/advanced-configuration/
I am working on React web app and to deployed it I used create-react-app. There is a file called registerServiceWorker.js which takes care of initializing the service worker. I want to cache some files on install event however the self.addEventListener('install', event gives me the error "Unexpected use of 'self' no-restricted-globals". I manage to get rid of that by changing self to window, however the install event is never being fired. How to use this "build in" service worker in React? Or can I create the other service worker?
After struggling with this myself, I finally figured out the following pieces of information:
the serviceWorker.js file in the default CRA project is not the same sort of service-worker.js file described by the PWA documentation from Chrome and Mozilla. That's not where the self.addEventListener statements go. They go into the file referenced by CRA's serviceWorker.js, specified by the string
const `swUrl = ${process.env.PUBLIC_URL}/service-worker.js`
By default, that service-worker.js is a file that you cannot access or modify! You will need to create your own service-worker.js file in the /public folder and point swUrl to it instead. It should point to the location as a string, statically, which means it will not get integrated as part of the build process and self will correctly refer to the module instead of the global context.
I found the simple solution. This utility is perfect for that: https://github.com/bbhlondon/cra-append-sw.
cra-append-sw
Utility tool to append custom code to ServiceWorker created by Create
React App.
It allows to keep the default CRA configuration (no ejecting). It
simply appends custom code to the ServiceWorker file created by CRA
build scripts. By default, it bundles the code using very basic
Webpack+Babel configuration (this can be omitted; see options).
Installation
$ npm install cra-append-sw --save
Usage
"start": "react-scripts start && cra-append-sw --mode dev
./custom-sw.js",
"build": "react-scripts build && cra-append-sw
./custom-sw.js",
What does the npm run eject command do? I do understand what other commands do like start, build, test. But no idea about eject.
create-react-app encapsulates all of the npm modules it is using internally, so that your package.json will be very clean and simple without you having to worry about it.
However, if you want to start doing more complex things and installing modules that may interact with modules create-react-app is using under the hood, those new modules need to know what is available and not, meaning you need to have create-react-app un-abstract them.
That, in essence, is what react-scripts eject does. It will stop hiding what it's got installed under the hood and instead eject those things into your project's package.json for everyone to see.
npm run eject
Note: this is a one-way operation. Once you eject, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except eject will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use eject. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
link to documentation
Alternatives to Ejecting
Ejecting lets you customize anything, but from that point on you have to maintain the configuration and scripts yourself. This can be daunting if you have many similar projects. In such cases instead of ejecting we recommend to fork react-scripts and any other packages you need. This article dives into how to do it in depth. You can find more discussion in this issue.
eject: is an advanced operation it allows you to customize the configuration under Create-React-App(react-scripts)
Before do eject you need to understand the consequences: it is a one-way operation!
The only reason I would encourage you to do eject is that: learn how the build process(create-react-app) works.
One more thing you need to do before eject is to commit your project to git. If your current project hasn't been added to git yet. npm run eject or yarn eject will fail.
There are packages that will allow customizing without ejecting, acting like a middleware between react-scripts and your customizations:
https://github.com/arackaf/customize-cra
https://github.com/harrysolovay/rescripts
https://github.com/gsoft-inc/craco
react-scripts basically encapsulates all the configurations and boilerplate in a single dependency so you won't have to configure the complete project from scratch. However, there might be a case where you want to override those configurations for build customization or something more specific. hence, it provides eject functionality so you can take control over those configurations. Including lint, bundling, code-splitting, etc.
I started to build a component library that I want to publish on NPM (and reuse in other apps) by creating a React app using create-react-app. Unfortunately the create-react-app default configuration doesn't seem to support building such component libraries (see these issues). So it seems I have to eject.
Do you have some instructions what to configure after ejecting to make this a component library I can reuse in other apps (I guess some Webpack stuff)?
Re-framing my comments into an answer.
Don't eject! CRA hides a lot of stuff under the hood and ejecting throws it up. It's relatively easier to just clone your src into another project with the tooling setup done.
And it's not very difficult to setup one yourself! Here's the things you will need to do:
Basic babel and webpack configuration so your code compiles.
Make sure React and React-DOM are added as external dependencies in your package.json file and added as alias in your webpack.config.js. (A thorough discussion is here.) This is important to ensure you ship the smallest bundles only. Also, React doesn't play well with multiple copies.
Optionally, do the same for any other heavier libraries, e.g. Material-UI, Bootstrap, Lodash etc.
In webpack's configuration, decide how you want your library exports should be? You should be good with UMD.
Add main (and optionally module) entries in your package.json to let npm imports know where the components should be imported from.
Publish it.
Done!
Or, you can simply clone one of these super thin component projects and put in your components there -
https://github.com/wangzuo/react-progress-label
https://github.com/aaronshaf/react-toggle
There are more complete starter-kits as well, but IMO it's important to first know the details yourself before you abstract them away. Once you are familiar with the process, you should try leveraging the kits too as they go much beyond the basics, like test integration, react-storybook support and great npm publishing support.
UPDATES:
The purpose of CRA is to allow quick experimentation and on-boarding to React development, without going through the (somewhat complicated to a beginner) tooling setup. The intended use case of CRA, as denoted by the "App" in the name, is the whole app, not a component. Although developing anything built on language features like ES6 takes some tooling, an app typically takes more setup than a component. E.g. you also need a server component which hosts the generated code. CRA does all this and more for you.
And if you are working on an app, you will eject when you want to take control of the server side of it. It adds value in that case as you will get the basic hosting code auto-generated by CRA during eject.
To address test needs, CRA also has Jest integration, which is a test runner having React specific features like snapshot testing. Again, setting it up manually with your build pipeline is a handful and CRA once again hides all of this complexity from you, so you can simply focus on writing the tests.
This is super simple - you don't actually need webpack if you want to publish a package. Don't install it just for that if you don't want to.
If you use ES6:
You can use a simple script to create a dist folder that babel will create the files after transpiling:
"scripts": {
// other scripts
// .. might want to change "rm -rf" below if you're on a PC
"build:production": "rm -rf es && cross-env NODE_ENV=production node_modules/.bin/babel ./src -d es"
},
What this does is:
Remove the es folder, which is a build folder.
Runs babel for your files (in case they are located in src folder, change it to wherever your files reside) and create the es folder with the transpiled files.
In order to use the script above you need to install the following dependencies:
babel-cli / babel-core / babel-preset-es2015 / cross-env
Make sure you have a .babelrc file so that babel will work:
{
"presets": [
["es2015", { "modules": false }]
]
}
Now all you have to do (after running npm run build:production) is to run:
npm publish
And your library is published in npm. This is also the command you run if you want to update, just don't forget to update the version number in your package.json.
In case you have files you dont want published to npm, just have a file in your root called .npmignore (similar to .gitignore) and list everything you want excluded.
If you don't use ES6:
In this case you don't need to transpile anything, just go straight to the npm publish section above and run it on the root folder you want published.
create-react-app is meant for quick setting up and development of apps, not really for development of libraries. For one thing, create-react-app creates an index.html file when building, which is usually not needed by libraries. Libraries require a different set of configuration (much less).
I faced this problem myself and have written a React component boilerplate for writing and publishing React components: https://github.com/yangshun/react-component-starter, after referencing how popular ES6 libraries were written, such as Redux.
Pros:
Similar to create-react-app, batteries are included
It has got all the important areas covered: development, linting, testing, and distributing
Minimal configuration
Babel for transpilation to ES5 and CommonJS format
ESLint included and configured
Jest tests examples
Webpack configuration that compiles to UMD
React Storybook for quick development of the components
Support for stylesheet distribution alongside your component
Cons:
Highly opinionated in terms of choice of tooling; they follow the choices set by create-react-app.
Have to manually update each package dependencies in future (you'll face this issue if you did eject anyways)
There is minimal configuration included and setup is easy. The various webpack, Babel and ESLint configurations should be quite understandable.
Hope this will be helpful to you. Feel free to give suggestions and comments on how it can be improved.