What is CRA?
Create React App is a toolchain built and maintained by developers at Facebook for bootstrapping React applications. You si...
For further actions, you may consider blocking this person and/or reporting abuse
Not all advantages and disadvantages are created equal: having to create and maintain your own build stack is just a single disadvantage, but it's a huge one.
Maintaining is not that difficult. You just have to be informed with new webpack and babel releases just like you do for React and other feature releases.
There is a reason why a great many developers abhor the word 'just'.
CRA is not boilerplate. It's build tool itself. You can DIY same kind of setup but you are really underestimating how much work it is to keep it up to date. CRA is managing build toolchain versioning for all "hidden" dependencies. When project lasts more than a couple of months, it's huge benefit.
Thank you for putting this together. A really worthwhile exercise that- even if you don't use it- helps students understand what is going on inside all of those packages and extra files in CRA.
IMO, dealing with Facebook baked-in vulnerabilities is an even bigger problem.
I really have to disagree with the premise. Maintaining the whole build process is a lot of work and very error prone.
I usually go a step futher and use the react-boilerplate template for create-react-app:
This way I have a full structure and thoughtfully setup react app in minutes. With typescript, redux, redux-saga, styled-components included.
Sure, it ultimately boils down to your requirement. I'd like to have control over the configs and I'm confident about maintaining the build process so I gave it a try🙂
I like this article and agree with some of the points. Most important one is that you need to know what is running under the hood.
Considering that, I would like to point out the main disadvantage - you need to update manually all the build dependencies, or maintain outdated configs.
Create React App is not to be used for every app, it depends on the use case. Gatsby and Next.Js might also be great candidates for this 0 build tooling approach.
I wrote about it here:
When to pick Gatsby, Next.Js or Create React App
Alexandru-Dan Pop ・ Jul 13 '20 ・ 4 min read
Great article.
Thanks!
I couldn't agree more! CRA is waaaaaay too bloated in my opinion. It took me a while to learn Webpack when I wanted to do some customization, and I think relying on CRA was part of it.
I'd say it's ok and probably a must-do at some point of every React and FE developer journey; to do some experimenting with the tooling we use every day, which we don't even care about it (webpack, babel, eslint, etc).
But that's the point to use said technologies, they were created for us to configure once and forget about them, so we can focus on our business logic intead.
IMO it isn't wise to encourage people to do this for every project. Yes, do it once and for learning purposes, but this is clearly a foot gun.
The experience will teach you to not do this. Once the projects grows, your dependencies get obsolete and because your build system is totally custom, you're many steps behind, not only to upgrade something like your React version (which might be straightforward), but also to gain advantages of many cool improvements the people behind CRA came up with, and you're losing that train.
"Let's measure how many lines of code we didn't have to write instead"
Well said - I think its very important to know the tools we use under the hood on a daily basis. However projects like CRA were made and maintained by the some of the greatest minds in web development - might be best to stick with it unless it's for educational purposes.
I see your point. But hear me out, my project grows and I create my own design component library and I want this library to be bundled separately from other vendor bundles. If I have my own build configs I can easily add
cacheGroups
in webpack to achieve this but it's difficult to do so in CRA(without ejecting). It ultimately boils down to your project requirements🙂To be honest, that's when you should start considering how you structure your project. You are probably adding some unnecessary complexity into its build system.
I'd use a separate project for my UI library, heck, I wouldn't even use webpack on it, I prefer rollup for libraries, but that's totally my opinion.
Yes - IMO. Look at this way. These are the advs of CRA
react-scripts
- Easy to upgradeBecause of the first two points, we are sacrificing two things
So we cannot incorporate the first two advs, so "The only advantage that we can take from CRA is Get started with a single command".
In the rest of the article, I wrote a step by step guide to add your own reactjs setup with webpack and babel. And finally implemented the "Single command" to bootstrap react app advantage using JS executable file and bin property.
If there is any other advantage of CRA, please share. Let's discuss how to implement them.
The problem with react-scripts is that react-scripts uses an older, out of date webpack. If you want to use the newest version, the app would fail to render using react-scripts to run the project. React-scripts forces you to use 4.44.2, whereas the newest version of Webpack is 5.38.1. To me, that's enough of a jump to be considered a huge negative if you want to use webpack.
As always, you can install react-scripts on your own. The advantage I see to using this custom setup is that one, you don't have unused dependencies bloating your project. Using CRA, my boilerplate redux-typescript-mocha setup was 1.17 GB in size. without CRA's bloating, that size shrunk to 839. That's 331 MB less in size. react-scripts alone adds an additional 120~ mb.
So, I can get behind setting up my own projects instead of using CRA. if you need a template, you could always use CRA and then delete what you don't need afterwords.
Awesome, Brian. I would love to checkout your redux-typescript-mocha setup. Can you share the link to the repo, if it's open source?
Sure, github.com/c0dezer019/Stormcaster/... It's in the client folder.
Cool
Some months ago I made a project to do, in some way, the same you do here. With some more experience in the field and more knowledge I can assure you that I learnt a lot, but it was a PAIN.
If you want to do it to understand what is behind webpack, react and babel its a good exercise. Elsewhere, you are just wasting time. IMO.
Trying to follow through this post, however I encountered
Error: Cannot find module 'webpack-cli/bin/config-yargs'
error while running thenpm start
.Changing from
"start": "webpack-dev-server --mode=development --open --hot"
To
"start": "webpack serve --mode=development --open --hot"
resolved the issue.
Seems like the interface in not compatible with webpack5 now. webpack-dev-server
Yeah, i've also encountered that issue (and solved it the same way).
Which btw? Is exactly the argument some people made in the comments above in regards for high maintainance, and error prone code when NOT using CRA, and going for pure Webpack solution.
Yeah, but migration to newer versions won't be that difficult if you have the habit of checking for any potential refactoring in your project regularly.
Thanks. Will update it.
Use Vite over CRA
medium.com/codex/you-should-choose...
CRA is devil! This is good article and I totally agree.
Here is my thoughts:
CRA is toy for dummies, it creates noise in frontend community and some folks think it's a best practies and afraid to admit that they spend days hacking around this crap...
Yes, you can learn how to cook it, and there are many people who will argue with me, but I will never admit that CRA is efficient and reliable way to run project... eventual you do "eject" and live with tones of crap that will be deprecated very soon...
I recommend you to use CRA for learning, but not for real project or you end up fighting against its limitations and "best practies"
The only advantage is that it comes with hot reload feature, but you can do it yourself anyway or just grab it from github
I'm not crazy (CRAzy?) about CRA either, but I do use it and have found workarounds to two of the points you mention:
there are several npm packages that allow more customization of the CRA tsconfig.json, so you can do things like link external project folders
depending on your deployment platform, you can make a monorepo work. I have a server node instance that runs separate of CRA, and the CRA instance proxies unhandled requests back to it (CRA has built-in support for this). At build+deployment time, the CRA project builds to a dist folder that the main project assumes responsibility to serve, so the whole thing can run as a single server instance
Neither of these steps are very confidence inspiring, but then neither is maintaining your own custom build stack. I've done that for personal projects in the past, and it runs into a problem where you have to futz with it just infrequently enough that you forget what you did last time, and have to relearn it all over each time. Between that and the CRA boilerplate, I'm not sure what's better.
Nikhil thank you very much for your excellent article!
Just a small typo in 'webpack.config.js', inside:
plugins: [
new HtmlWebPackPlugin({
template: './src/index.html',
}),
],
instead of
template: './src/index.html'
should be:template: './index.html'
Now, i'm able to
yarn start
the project!Like I said before, some devs like myself would like to have control over the configs.
Another disadvantage is, you're forced to use whatever dependencies CRA requires, including an older version of webpack and babel-loader. CRA is an entire version behind the current webpack version. Installing a newer version will simply break react-scripts.
I'm gonna be blunt and straight to the point.
Go ahead. Use CRA. Then start running things like npm audit. Then try to upgrade individual things without breaking changes. Then be met with a slew of "I CAN'T FORCE UPDATE" messages from npm audit fix --force because everything is bundled together and you're at the mercy of Facebook dev team. The VERY reason why I am here now. IDK about you, but I don't want to be in front of congress (like Zuckerberg) because of vulnerabilities Facebook (or is it meta now?) baked into their "easy button." I may be new to JS and React. But I'm not lazy.
P.S. Ever look at the GitHub issues for CRA? Go ahead. look.
Maintaining your own fork of CRA is the best option if you want to add custom build config. You can still pull the upstream changes with this approach.
create-react-app.dev/docs/alternat...
Since react is really a build step, is there any reason not to have react and react-dom in devDependencies instead of dependencies?
Dan Abramov had mentioned in a CRA, since everything is going through a build step. You should think of it more as everything is a dependency instead of a dev dependency.
Bundle analyzing tools or websites (example bundlephobia) do not read your dev dependencies. I'd recommend keeping it as a dependency!
React is not a build step, you need React to run your application. classic.yarnpkg.com/en/docs/depend...
The current project I'm working on has it all in devDependencies and it works fine.
The project is a little overloaded, it's basically a monorepo with server and client in the same project. All of the client stuff is in devDependencies, everything needed for the server runtime is in regular dependencies.
React per-se doesn't run without this build step. That's why he says that you can list everything under devDeps
Maybe it's just bad luck, but every React project I have be working on, since CRA was made, had something which required me to either eject or use my own setup. And if that is the choice, I will go with my own setup as an ejected CRA is far from simple to deal with.
Its cool however setting up your own React boilerplate seems kind of tedious and adds an additional layer of complexity. For one you now have your own custom build which is fine but now your setup differs from that of all other developers who are using create-react-app which is not great if its a team project. There could be unknown errors as its not been battle tested. Plus creating this setup every-time you want to start a project is just going to add more time and of course you are not going to do this during an interview.
Also you added lots of custom code which a beginner might not understand and it would not be good practice to just copy and paste the code without actually knowing what it all does and how to write it. Using Next.js would be far better its more lightweight.
"Also you added lots of custom code which a beginner might not understand and it would not be good practice to just copy and paste the code without actually knowing what it all does and how to write it."
Agreed. But at the same time its key to understand how webpack and babel works
"Plus creating this setup every-time you want to start a project is just going to add more time and of course you are not going to do this during an interview"
You don't have to do this every time. That's why we use executable JS file and bin property to bootstrap react app with single command just like CRA.
Thanks for this - it was very helpful in creating a new React app minus the bloat.
I ran into a problem creating my own boilerplate though - start.js at line 12 produces an error (line 12: const babel =
"babel": ${JSON.stringify(packageJson.babel)}
)Some error while installing dependencies
Error: Command failed: cd react-test && git init && node -v && npm -v && npm i -D @babel/core@^7.16.7 @babel/preset-env@^7.16.7 @babel/preset-react@^7.16.7 babel-loader@^8.2.3 css-loader@^6.5.1 html-webpack-plugin@^5.5.0 style-loader@^3.3.1 webpack@^5.65.0 webpack-cli@^4.9.1 webpack-dev-server@^4.7.2 && npm i -S react@^17.0.2 react-dom@^17.0.2
npm ERR! code EJSONPARSE
npm ERR! path C:\Users\mang\PycharmProjects\react-test/package.json
npm ERR! JSON.parse Unexpected token "u" (0x75) in JSON at position 226 while parsing near "...on\"\n },\n \"babel\": undefined,\n \"author..."
npm ERR! JSON.parse Failed to parse JSON data.
npm ERR! JSON.parse Note: package.json must be actual JSON, not just JavaScript.
Idk about before, but with the new WebPack you don't need the bin/start. That's pretty useless now and does nothing. Also the command moves from webpack-dev-server to webpack serve (still need that as a dep though).
Thanks for pointing it out.
Even I need sometimes to edit webpack, to start and keep webpack really up to date with all stuff can be really pain in the as*. 'Don't use CRA...' is a little bit missleading title, better to be something like 'How to create your own CRA' :)
In the webpack.config.js file, in the resolve object, you might want to include "extensions: ['.js', '.jsx']" after defining "alias". I had a hard time getting webpack to find and transpile my jsx files until I did that.
You need to define those extensions IN ADDITION to defining rules to deal with those extensions.
Thanks though for teaching use another way besides CRA. CRA was adding dependencies that would make npm freak out sometimes.
Thanks for the suggestion. Will update.
Hello, I'm a Junior FE dev from S.Korea. I just signed up here to say "Thank you"! to you. There are some issues at work for me. The project I'm building at work is really heavy. It's built with CRA by other person and you know there are many dependencies I never use in the boilerplate and I need to learn how to handle bundle size for the future. So I really needed to learn how to set up react project with webpack from A to Z to make its performance better and maintain potential future conflict well. And this post really helped me a lot. I learned a lot from this post. I'm sure the knowledge I learned from here will make my work better! Now, I can build react project from Zero. Thank you so much!
Thanks for the feedback. I'm glad you find it useful.
In one of my Django projects (web framework using python)...
I've used REACT to handle all the frontend stuffs. Coz' Django works using Model-View-Template (MVT), so Django can use my REACT APP in its own template engine.
But, you can't rely on CRA when youre using REACT with Django. That's why I was forced to learn all of these "webpack and babel stuffs".
And gladly, it wasn't actually hard to learn. That's why I completely agree with all of the advantages that the author stated.
Use
"start": "webpack serve --mode=development --hot"
for webpack cli 4 😄I like it. It's a third of the create-react-app size and starts much much faster.
Do we really need the resolve (modules: ... alias:) block though?
I'm glad you liked it ❤️
It's not required for the example mentioned in this blog post. resolve is used to tell webpack how to resolve our imports(modules).
Eg: If you are using
import 'pages/about/About'
(instead of relative paths for cleaner syntax) you need to specifymodules: [path.join(__dirname, 'src'), 'node_modules']
so webpack will first look forpages
folder insidesrc
. If you don't specifymodules
then webpack by default will check in the node_modules and throw this errorModule not found: Error: Can't resolve 'pages/about/About'
.Can you add typescript too?
I do not understand passion of some developers to create abstractions on everything. that is a trap, when you end up creating abstraction on already existing abstraction.
If you need to create abstraction to an abstraction probably you are doing something wrong.
Time is a limited resource. I do not have time to learn how webpack or babel works, when i need to finish my ticket with has nothing to do with it. if workspace is set and everything configured, yo do not need to install webpack or babel.
Again this is a developer trap when some devs try to do everything that is done for them before them by themselves.
Why? just to showoff how cool you are?
Thanks for this detailed breakdown on creating a custom React boilerplate. I've been using CRA for a while, but I've started to feel its limitations, especially when trying to optimize larger projects. Your point about CRA abstracting too much really resonates – I've often found myself wondering what's happening under the hood.
A few questions come to mind:
Have you encountered any specific scenarios where your custom boilerplate significantly outperformed a CRA setup? I'd be curious to hear about real-world performance differences.
For developers just starting to move beyond CRA, which part of the custom setup do you think is most crucial to understand first? Webpack configuration? Babel presets?
How do you handle keeping all dependencies up-to-date in your custom boilerplate? One thing I appreciate about CRA is the ease of updates.
I've been exploring ways to deepen my knowledge, and this approach seems like a great next step. I actually found some free learning resources and fundamentals at that have been helping me understand these tools better. It's amazing how much you can optimize when you have full control over your build process.
One tip I'd add from my experience: it's worth spending time setting up good linting and formatting rules in your boilerplate. It saves so much time in the long run, especially on team projects.
"Let's do this", "Let's do that". How about "why"?
I already mentioned right? To eliminate CRA's drawbacks(Abstraction and difficult to add custom configs), we are setting up our own reactjs boilerplate and make it to bootstrap react projects with a single command like CRA. With this, you have complete control over your app and also you can boot up a new react project with just a single command.
My gut tells me that CRA isn't being maintained properly anymore because it seems to add deprecated dependencies that make npm freak out upon every build or test server start. That makes me sad. I'm a CRA fan, but I'm also glad to see another way.
Glad this post is helpful to you!
nice one!