User Tools

Site Tools


2017:09:30:building-a-front-end-app-with-react-and-material-ui

Building a Front-end application with React and Material-UI

Introduction

I use version managers for setting up separate programming environments, due to each project having different needs; such as different versions of an interpreter or a package. For Python, I use pyenv, and for Node, I use NVM (Node Version Manager), which I'll cover in this article.

It's been a while since I've used Node, and for a project that I've been working on, I needed to setup Node on OS X so that I could assemble a front-end that's built with React and Material-UI; and I have documented the entirety of my steps, including key web pages that I read.

When I started writing this article, I realized that I'll also want to port some of this work to run as a an application on a Server (Linux and Unix: -nix), Mobile (iOS and Android), and Personal Computers (OS X and -nix), so this is part of a set that I will be expanding upon, as time permits:

  1. Building a Front-end application with React and Material-UI - You are here.
  2. Building a Universal application with React (AKA an Isomorphic Application)

Prerequisites

In an effort to make this cross-platform, I'm working on a Docker image, and will update this article at a later time. I didn't want to hold up publishing this article, so for now, I'm covering the process from an OS X perspective.

If you know how to use -nix systems, then you should be able to follow this guide with slight changes for your particular flavor.

Setup

System

  1. Update Homebrew package manager.
  2. Install system packages with Homebrew:
  3. Using Yarn, install additional packages for system-wide use:
    • create-react-app - Create React apps with no build configuration.
    • serve - Static file serving and directory listing.
    • json - A “json” command for massaging JSON on your Unix command line.
    • goog-webfont-dl - A utility to download Google web fonts to your local machine.
(
    brew update

    brew install nvm
    brew install yarn --without-node

    yarn global add \
        create-react-app \
        serve \
        json \
        goog-webfont-dl \
        ;
)

Environment

Setup your login shell to behave identically to a non-login shell:

~/.bashrc is executed for interactive, non-login shells (e.g. GNU Screen), while as ~/.bash_profile is executed for login shells (e.g. opening a terminal window). I tend to place the bulk of my configuration in ~/.bashrc and source it, so that my environment is the same for both of my daily uses:

~/.bash_profile
source $HOME/.bashrc

Now that ~/.bashrc is being sourced, setup a directory for NVM, and then setup environment variables:

mkdir -pv ~/.nvm

cat <<EOF >> ~/.bashrc
# NVM
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh
EOF

You can either close your shell and re-open it,
or run source ~/.bash_profile

To verify that required software is working:

(
    echo -n "NVM: "; command -v nvm >/dev/null 2>&1 && echo "PASS" || echo >&2 "FAIL";
    echo -n "Create React App: "; create-react-app --version >/dev/null 2>&1 && echo "PASS" || echo >&2 "FAIL";
)

Node

Node has 2 major release streams to choose from: LTS or Stable. By using NVM, you can use multiple versions at the same time. When you visit the Node website, you'll find a similar set of choices that provide information about both versions:

Screenshot: 2017-09-30

nvm install has an alias for the Stable release, but not for the LTS release (there's a discussion about it on NVM's issues page).

I'm using the Stable release for this article.

nvm install stable
nvm alias default stable

Application

Initialize

Store your site's FQDN as a variable for use throughout the rest of the shell commands in this article:

read -p "Website FQDN : " fqdnSite

Create application for your FQDN in ~/src/:

create-react-app ~/src/sites/${fqdnSite} \
    && \
    cd $_ \
    ;

After a moment, it will result in similar output:

Success! Created ${fqdnSite} at ~/src/sites/${fqdnSite}
Inside that directory, you can run several commands:

  yarn start
    Starts the development server.

  yarn build
    Bundles the app into static files for production.

  yarn test
    Starts the test runner.

  yarn eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd ~/sites/${fqdnSite}
  yarn start

Happy hacking!

Your freshly-created application structure should now resemble:

Packages

Add Node packages at a local level to a new project:

  1. material-ui - React Components that Implement Google's Material Design.
  2. webfontloader - Gives you added control when using linked fonts via @font-face.
yarn add \
    material-ui \
    webfontloader \
    ;

Fonts

There seems to be a bit of confusion when following Material-UI's installation instructions to include the Roboto font for offline use and/or hosted separately from Google (which can include blocking). 4) 5)

I'll admit, it took me a hot minute to read several sites to figure it all out. 6) 7) 8) 9) 10)

I've tried to document the process for making this as turnkey as possible. If you know of a better way, please let me know so that I can update this article.

goog-webfont-dl \
    --font 'Roboto' \
    --styles '300,400,500,700' \
    --all \
    --destination ~/src/sites/${fqdnSite}/src/fonts/roboto/ \
    --out ~/src/sites/${fqdnSite}/src/fonts-roboto.css \
    --prefix 'fonts/roboto' \
    ;

Configure

Package Manifest

Set your project's homepage as a relative path:

json \
    --in-place \
    -f ~/src/sites/${fqdnSite}/package.json \
    -e 'this.homepage="./"' \
    ;

Entry point

It is convenient to organize programs and libraries into self-contained directories, and then provide a single entry point to that library. There are three ways in which a folder may be passed to require() as an argument.

Node : Folders as Modules”, 2017-09-30 17:20:04 UTC

Node has an ordered sequence for entry point selection:

  1. package.json
  2. index.js
  3. index.node (C++ addon)

If main is not set in package.json, it continues down the aforementioned list.

Based on Stack Overflow answer : difference between app.js and index.js in Node.js

Boilerplate JavaScript has been setup at ~/src/sites/${fqdnSite}/src/index.js

The panel on the left is the original (as of 2017-09-30), and the panel on the right are changes needing to be made to support additional packages:

    • Roboto Font family (required by Material-UI, downloaded by goog-webfont-dl, loaded by webfontloader)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
 
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import './fonts-roboto.css';
import WebFont from 'webfontloader';
 
WebFont.load({
 
	custom: {
		families: [
			'Roboto:300,400,500,700',
			'sans-serif'
		],
	},
 
	loading:  function(){ console.log('WebFonts loading'); },
	active:   function(){ console.log('WebFonts active'); },
	inactive: function(){ console.log('WebFonts inactive'); }
 
});
 
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();

Application Index

In index.js, the 4th line import App from './App'; is what opens this section of code, and the prior Entry point section discusses some of the structural nuances. This particular implementation is due to the way that Create React App structures initial projects.

If you forgo this step for the next step, you'll be able to view
a fresh installation of your Front-end application in your browser.

Feel free to try it, then make the following changes, and then try it again. See the difference?

Boilerplate JSX has been setup at ~/src/sites/${fqdnSite}/src/App.js

The panel on the left is the original (as of 2017-09-30), and the panel on the right are changes that need to be made in order to implement:

App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
 
class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
        </p>
      </div>
    );
  }
}
 
export default App;
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import RaisedButton from 'material-ui/RaisedButton';
 
class App extends Component {
  render() {
    return (
      <MuiThemeProvider>
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </div>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
          <RaisedButton label="Material UI Raised Button" />
        </p>
      </div>
      </MuiThemeProvider>
    );
  }
}
 
export default App;

If you compare the two panes of code, you'll notice that I've added a few lines.

In the header:

  1. import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
  2. import RaisedButton from 'material-ui/RaisedButton';

In the body:

  1. <MuiThemeProvider> and </MuiThemeProvider> wrap everything else.
  2. <header> tags were changed to <div> tags:
    • <header className="App-header"><div className="App-header">
    • </header></div>
  3. <RaisedButton label=“Material UI Raised Button” /> to test Material-UI and fonts (if fonts aren't working, the letters won't be bold).

Develop

To start a test server for viewing changes as you make them in ~/src/sites/${fqdnSite}/

yarn start

Test

Optional: run the test script defined by the package. 11)

yarn test

Build

Are you ready to deploy your React website with assets to a framework such as Django and/or a web server such as Nginx?

yarn build
  • The results will be saved in ~/src/sites/${fqdnSite}/build/
  • The contents in build/ are what you would then move to ~/srv/sites/${fqdnSite}/public/ if you followed prior articles. 12) 13)

Preview

When you built your project, static files were generated and linked together. You can test the results against a local web server that functions identically to your production deployment (e.g. using Nginx to serve your content).

serve \
    -s ~/src/sites/${fqdnSite}/build \
    --clipless \
    ;

Deploy

Even though Create React App was used as a starting point, there is no vendor lock-in. When you're ready for your Node project to stand on its own, you simply run this command for the configuration and build dependencies to be moved directly into your project, and all connections to Create React App to be severed.

You should only run this command if you are sure of your decision.

yarn eject

Conclusion

This article only serves as an introductory article for creating a front-end with React, and to document my steps for:

  1. Setting up Node Version Manager.
  2. Setting up Node.
  3. Setting up Yarn package manager.
  4. Installing packages with Yarn.
  5. Creating a React application.
  6. Adding Material-UI.
  7. Installing Roboto fonts that will work offline.

There are many different ways to structure your React application. As you progress, and your program becomes more complex, especially if you're working on a team, organization of your code and assets will be just as important.

Relating to structure, I suggest that you read:

Saving the best for last:

Buy and read The Road to learn React by Robin Wieruch. Buy and read Fullstack React by Anthony Accomazzo, Ari Lerner, Clay Allsopp, David Guttman, Tyler McGinnis, and Nate Murray. Watch React video tutorials by Ben Awad.

References

External links

2017/09/30/building-a-front-end-app-with-react-and-material-ui.txt · Last modified: 2017/12/31 00:29 by Administrator