Code splitting definition and benefits
Code-splitting is the process of breaking an app into smaller bundles that can be loaded on demand. It helps address slow loading times that occur when all of the code for the entire app needs to be sent before it can be used. Splitting code by route, when integrated with bundling and data fetching, can reduce the initial load time and the time it takes for the largest visible content to render (Largest Contentful Paint).
Build tool code splitting documentation
For code-splitting instructions: Vite provides build optimizations at https://vite.dev/guide/features.html#build-optimizations, Parcel provides code splitting at https://parceljs.org/features/code-splitting/, and Rsbuild provides code splitting at https://rsbuild.dev/guide/optimization/code-splitting
Code splitting waterfall pitfall with lazy loading
Lazy loading a component such as a chart using React.lazy can cause a waterfall if the component fetches its data after being initially rendered. This requires waiting twice: first for the code to load and render, then for the data to fetch. Fetching the data and sending the code to render it simultaneously is faster than waiting for each step to complete sequentially.
Example: Split Profile and Gallery into separate files with named exports
Profile.js:
```js
export function Profile() {
return (
<img
src="https://react.dev/images/docs/scientists/QIrZWGIs.jpg"
alt="Alan L. Hart"
/>
);
}
```
Gallery.js:
```js
import { Profile } from './Profile.js';
export default function Gallery() {
return (
<section>
<h1>Amazing scientists</h1>
<Profile />
<Profile />
<Profile />
</section>
);
}
```
App.js:
```js
import Gallery from './Gallery.js';
import { Profile } from './Profile.js';
export default function App() {
return (
<div>
<Profile />
<Gallery />
</div>
);
}
```
Error when mixing import and export styles
You will get an error if you try to import a default export the same way you would a named export, or vice versa. The import syntax must match how the component was exported.
Named export syntax and import syntax
To create a named export, use `export function Button() {}`. To import a named export, use `import { Button } from './Button.js';`.
When to use default vs named exports
People often use default exports if the file exports only one component, and use named exports if it exports multiple components and values. Some teams choose to stick to one style (default or named) or avoid mixing them in a single file to reduce confusion.
Multiple exports from one file
A file can only have one default export, but it can have numerous named exports. This allows you to export multiple components from the same file by using named exports for all but one component, or using default export for one and named exports for others.
Component names matter for debugging
Components without names, like `export default () => {}`, are discouraged because they make debugging harder. Always give meaningful names to your component functions and the files that contain them.
Three steps to move a component to a separate file
To move a component into its own file: (1) Make a new JS file to put the components in. (2) Export your function component from that file using either default or named exports. (3) Import it in the file where you'll use the component using the corresponding import technique.
File extensions in imports
Both './Gallery.js' and './Gallery' will work with React when importing modules, though the former is closer to how native ES Modules work.
Default vs named exports comparison
Default exports and named exports are two primary ways to export values in JavaScript. A file can have no more than one default export, but it can have as many named exports as you like. Default import syntax: `import Button from './Button.js';` Named import syntax: `import { Button } from './Button.js';` When you write a default import, you can put any name you want after `import`. With named imports, the name must match on both sides.
Default export syntax and import syntax
To create a default export, use `export default function Button() {}`. To import a default export, use `import Button from './Button.js';`.
Bundlers use dependency trees for code splitting
Bundlers use a React app's dependency tree to determine which modules should be included in the bundle for production. As apps grow larger, bundle size can increase and delay UI rendering. Understanding the dependency tree helps debug bundle size issues and identify opportunities for optimization.
Difference between render tree and dependency tree structure
Module order in a dependency tree can differ from the render tree. A component may render another component as a child prop without directly importing it. For example, InspirationGenerator renders Copyright as a child but does not import it directly, so Copyright.js appears under App.js in the dependency tree but under InspirationGenerator in the render tree.
Module dependency tree includes non-component modules
Unlike render trees which only contain components, module dependency trees also represent non-component modules such as utility files or data files. For example, in the Inspirations app, the module dependency tree includes inspirations.js even though it is not a component.
Module dependency tree definition and purpose
A module dependency tree models the relationship between JavaScript modules in a React app. Each node represents a module and each branch represents an import statement. The root node is the root module, typically the entrypoint file that contains the root component. Dependency trees help determine what modules are necessary to run a React app and are used by bundlers to determine what code to include.