Can all dependencies of a React-based website be declared as devDependencies instead of (production) dependencies?
Since the build folder is not versioned together with the code, each checkout of the repository will require a build operation to run the website. Thus every checkout can be considered a development environment.
dependencies is an object of dependencies that the app itself use, E.G react, react-dom.
On the other hand, devDependencies are dependencies that are only used when you're developing or building the package, E.G. webpack, babel, prettier.
Whether you need npm install in production or not, filling these fields appropriately will (at least) provide clarity for the readers.
Now answering your question, module bundlers and transpilers don't care whether the dependency is in devDependencies or dependencies or is it there in the first place. All it cares about that it exists in the node_modules folder.
Related
i have some questions and regarding the proper way to handle dependencies in nested projects, added via git submodules. lets assume this structure:
further assume in the top-level package.json dependencies need a react version > 16.7. In the submodule a strict version of 16.3.2 is needed.
when i now run npm install on the top-level, does npm install multiple versions of react? (don't see something like this in node_modules) but it seems to install modules declared only in submodules package.json. (how are they even found at compile time?)
There are certain warnings in the console however, that there might be multiple versions of react running...
What would be the best practice to handle such a situation?
Thanks in advance
I started to use React Native recently and, following the oficial docs, I initialized a project using npx react-native init ProjectName.
I'm not sure if the tools versions matters (probably yes), but i'm using npm version 6.13.7, react-native-cli version 2.0.1 and react-native 0.62.2. With that config, the file architecture i that get is the following:
I seached about it, but i not found an answer. So, can someone please explain to me what is the purpose of each file in this file architecture and which of these files can i remove?
Thank you in advance :D
Package.json
This file holds all of the dependencies of modules that your app is using and needed to install for running your app.
yarn.lock files yarn and package-lock.json
These two files hold the version of your dependencies yarn.lock package-lock.json is automatically generated for any operations where npm or yarn modifies either the node_modules tree or package.json. It describes the exact tree that was generated, such that subsequent installs are able to generate identical trees, regardless of intermediate dependency updates.
app.json
This file holds your application name etc.
babel.config.js
This file holds configs related to babel, Babels is a transpiler that transpile ES6 to ES5.
index.js
This is the entry point of your application form where your react-native code start executing.
EsLint and Prettier
These file related to maintaining the code indentation, Unused imports, extra, spacing, these files holds configs related to these things(EsLint and prettier are used to avoid above-mentioned things).
.watchMan
watchman watches the code changes when the packager is running, so this file have configs about this.
.Flow
Flow is been used for type checking so it holds the configs related to this.
node_modules
This folder holds all of the modules that your app is been using also lited down in your package.json.
And then there is Android(which holds native android code), IOS(which holds native ios code), and other JS files which holds code react-native js code.
Bootstrapped CRA 3.0 app and then ejected.
Inspecting my package.json.
Found multiple packages usages of which are not really clear to me.
"semver": "6.0.0"
Why do I need this? No usages found in config/* nor scripts/*. It seems like an artifact of react-scripts validation-like logic for related packages, so it looks like a piece of bloat in my application dependencies.
"react-app-polyfill": "^1.0.0"
Polyfills for IEs and etc.? OK, but why a separate package? It's frightening to me to use some unknown package on top of core-js or babel-polyfill. And again, no usages found in an initial code base.
P.S. I'm not asking what these packages are, I'm asking why do I see them being unused in ejected scripts
Update: react-app-polyfill/jsdom is used in Jest setup files
create-react-app uses a package named react-scripts which hides all the different packages it uses underneath.
When you eject an application, the dependencies used by react-scripts are copied over to your own package.json. But for some scripts like the eject, various sections are removed using babel annotation like #remove-on-eject-begin. The dependencies used in these sections persist even after you eject.
This is how you find packages like semver that are not used anywhere in your application code. In an unejected create react app, that package would be used for verifying the semantic versions before ejecting.
These are safe to remove now. But they would not be factored into the static bundle you are creating anyhow.
I was playing with create-react-app and found out that it does put all packages under normal "dependencies". I built the app and found out the 'build' folder size was 2.66 MB.
Then I manually moved the packages not needed in production to "devDependencies" and built again, but the 'build' folder size was still 2.66 MB.
Is there some logic in the webpack.prod.js file, that knows what is needed even if all the packages are listed under "dependencies"?
If so, is there still some benefits using "devDependencies" in package.json?
When webpack builds your project it determines everything your project depends on, starting at the entry file, and then combines, uglifies and so on, and disregards everything else.
For example, if index.js is your entry file and it depends on moment.js, moment.js will be included in your build regardless if it's a dependency or devDependency.
The reason for this is npm distinguishes between dependencies and devDependencies, while webpack only distinguishes between that which is needed and that which is not.
If so, is there still some benefits using "devDependencies" in package.json?
I still use devDependencies, but solely as a means of ordering my package.json, but everything can safely be in dependencies when a tool such as webpack is used to build the production site/app
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.