2

I created a react app that both server and client shares the same package.json:

├───build
│   └───static
│       ├───css
│       ├───js
│       └───media
├───server (backend code)
├───src (client code)
├───package.json (shared)

My question is very simple, are all packages from package.json included in the final production React build?

For example, I use express for server. Is it included in the React build?

If so, is there any way to avoid it? Or did I choose a wrong architecture?

Edit:

Im using create-react-app, default mode

Rashomon
  • 5,962
  • 4
  • 29
  • 67
  • How exactly are you building the React application? Are you create-react-app or a webpack configuration that does bundling, minification, and tree shaking? If you are then only what React actually imports and uses will be included in the static built assets. That being said you need to share more information on how you build the React portion. – Alexander Staroselsky Jun 01 '19 at 19:44
  • 1
    You chose the wrong architecture. You definitely should have a `client` and `server` folders, with 2 seperate `package.json` files. Additionally: Shared things between client/server can go into a third folder, which can be included using `../shared` – Blue Jun 01 '19 at 19:44
  • @AlexanderStaroselsky Im using create-react-app in default mode – Rashomon Jun 01 '19 at 19:47

3 Answers3

3

No* (in the common case).

The most popular react build tooling will use webpack (or other bundlers which do similar things). Webpack receives some "entry point filepaths", from those entry points he crawls for dependencies. Then webpack packs everything into a single output file (or a set of files, depending on the settings).

If you didn't import express from any of your frontend files, it won't go into the bundle.

wkrueger
  • 1,281
  • 11
  • 21
1

Im not sure about combining the package.json for both your express and React app, I dont see an advantage to doing this since React uses webpack and combining the express server might mess up some of the default settings, I will share with you how I do it.

When you are in a development build you will have 2 separate apps running independently. Both the create-react-app and the node/express server will be running independently of each other and they will have their own separate package.json.

In production however you will run npm run build on your React app and it will be served as a static file from your express server. A built React app does not have a package.json

I have implemented both of these scenarios you can check it out here

Dev build: https://github.com/iqbal125/react_hooks_fullstack_skeleton

Produiction Build: https://github.com/iqbal125/react-prod9

iqbal125
  • 1,331
  • 2
  • 11
  • 19
0

Previously answered, According to Webpack doc, Webpack generates a dependency graph starting from entry point which is usually index.js. And also if you use something like create-react-app that uses webpack under the hood, it will generate a package json like this:

{
  "name": "my-app",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.3.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "build": "react-scripts build",
  },

You can see there is no devDependencies! that means not all thing that you just put on the dependencies will be included in your final build.

Finally I've tested inside a new CRA my app:

  1. pressed npm run build on the bare installed:
File sizes after gzip:

  46.61 kB  build\static\js\main.46f5c8f5.js
  1.78 kB   build\static\js\787.28cb0dcd.chunk.js
  541 B     build\static\css\main.073c9b0a.css
  1. Installed axios via npm i axios, but never imported it. output after running npm run build:
File sizes after gzip:

  46.61 kB  build\static\js\main.46f5c8f5.js
  1.78 kB   build\static\js\787.28cb0dcd.chunk.js
  541 B     build\static\css\main.073c9b0a.css

Nothin has been changed!

  1. import axios from "axios", inside but never use it in the code:
import axios from "axios";
export default function App() {
  return (
    <div className="App">
    </div>
  );
}

This is the output:

[eslint]
src\App.js
  Line 3:8:  'axios' is defined but never used  no-unused-vars

File sizes after gzip:

  46.61 kB  build\static\js\main.46f5c8f5.js
  1.78 kB   build\static\js\787.28cb0dcd.chunk.js
  541 B     build\static\css\main.073c9b0a.css

Again nothing changed! but you can see eslint warning too!

  1. Use one of it's functions e.g. get method only:
import axios from "axios";
export default function App() {
  console.log(axios.get);
  return (
    <div className="App">
    </div>
  );
}

the output:

File sizes after gzip:

  57.92 kB (+11.31 kB)  build\static\js\main.4c83ea39.js
  1.78 kB               build\static\js\787.28cb0dcd.chunk.js
  541 B                 build\static\css\main.073c9b0a.css

Conclusion:

If we don't use a package inside our app, it won't get into the final build.

Note:

Although extra packages won't affect production, don't forget to uninstall unused packages from time to time. Running npm install still install every package defined in the package.json, no matter whether they are used or not. So having loads of unused packages will slow down deployment and affect your teammates (they need to run npm install as well!!.

Reference

SeyyedKhandon
  • 5,197
  • 8
  • 37
  • 68