Create React App
February 24, 2020
The goals of this lecture are to:
- Understand what Create React App is and how to use it
- Use ES6 modules to share code across files
- Compare
default
vs. non-default exports - How to serve assets (CSS + images) in CRA
What is Create React App (CRA)?
React is a frontend library, meaning that we could grab the dependencies from a CDN and then transpile JSX to be readable by the browser at runtime.
But we have an easier option to the same end: Create React App.
Create React App is a utility that we can use to:
- Quickly create a skeleton React project
- Sets up processing of JavaScript files through Babel automatically
- Allows us to use latest-and-greatest JavaScript features
- Makes deployment and testing easier
Using CRA to Create New React Project
To create a new React project using create-react-app
, we run the following command:
$ npx create-react-app your-app-name
Doing so will create a helpful skeleton application for us to work with.
To start our new application, we run:
$ npm start
npx
as an alternative to installing packages globally. Some of the packages we reach for are used specifically to generate projects or other starter code, and we only reach for them one in a while. This means that the copy we have installed locally is likely to be out of date if we've installed it globally in the past.
npx
allows us to use the latest and greatest version of the package without having to keep a copy on our machine!
Webpack
Create React App is built on top of Webpack, which is a utility that does a few things for us:
- Enables module importing/exporting. We can easily bundle up all CSS/images/JS into a single file to be served up in the browser. As a result, we can dramatically reduce the number of HTTP requests required.
- Hot reloading. Whenever we make a change to our application while developing, it will automatically be reloaded/refreshed in the browser.
- Enables easy testing and deployment.
Modules
Create React App uses ES2015 Modules, which is a newer, standarized version of the modules we've seen used with Node's require()
function.
We will be using these ES2015 modules to share code across different files within our React application.
require
and the relative vs. absolute path passed in, when importing modules with ES2015, an omission of the relative path will indicate the import is an npm
package.
Modules: Importing default Export
The default
keyword is used to designate what the default piece of code from a given module will be if our import doesn't use destructuring to grab specific pieces.
For example, say we have a module that contains a utility function that we'd like to export for use across other files in our application:
function mainFunc() {
console.log("Hi");
}
export default mainFunc;
Meanwhile, in another file, we can import myFunc
with any name we choose (but it's often best to maintain parity between the export and import sites):
import mainFunc from './myFile';
default
exports are used in modules when there is something that is most likely the code/functionality that the consumer is likely to be reaching for.
In a React component, the default export is usually the component itself.
Sometimes it might be the case that we'd like to specify a default, but also export other pieces of code for use:
function mainFunc() {
console.log("Hi");
}
const msg = "Awesome!";
export default mainFunc;
export { msg };
In the case above, we would import both in the following way (and according to how they were exported):
import mainFunc, { msg } from "./myFile";
We don't need a default export, but it can be useful to indicate what the most important member of the file is.
CRA and Components
It's considered good style to maintain that same separation of concerns we've come to know and love up until this point by separating out your components into their own dedicated files.
For example, our Car
component will live in an aptly-named Car.js
file, whereas our House
component will live in House.js
.
In these files, you'll define the component itself and then export
it as the default
at the end of the file.
Serving Assets
To include images and CSS, we simply import them directly into our JavaScript files:
import logo from './logo.svg';
import './App.css';
CSS
With separation of concerns always in the back of our minds, we'll be creating a CSS file for each one of our components.
That House
component from earlier? It will get its own House.css
file, which will be imported with the rest of the imports at the top of House.js
.
One thing to note: any CSS imported from these files will be applied to all of your application! These imported styles are not scoped just to the component they're being applied to.
To scope these styles, it's conventional add the component's name as a class to the root element in the file (ie, className="House"
), and then use this class to add styling in the CSS file.
Any nested elements will also take on that component name, with hyphenated additions that describe the element's purpose.
A resultant component might look like this:
<div className="House">
<p className="House-title">{ props.title }</p>
<p className="House-address">{ props.addr }</p>
</div>
Images
When working with images, we'll store them in the src/
directory with the rest of our components.
To use them, we import them as we have our other files, providing an intuitive and explicit alias:
import puppyImg from "./puppy.jpg";
function Animal() {
return (
<div>
<img src={puppyImg} alt="Cute puppy!" />
</div>
);
}
Building for Deployment
Building and processing a project's code for development purposes often looks different to preparing it for production purposes.
Building for production will squeeze every little bit of efficiency and optimization we can out of it, by minifying, uglifying and combining files to reduce the number of HTTP requests to download all of the resources necessary for a user to run our application.
To run code for production, we'll use the following command:
$ npm run build
This command will bundle like-files and optimize them for performance purposes, creating a build
directory in the process from which our production-ready application will be served.