React.js Front End Setup

In these instructions, we’ll guide you through creating a basic React.js project.

  1. You’ll be using the same repository (client-abc123) as you did in Client0 and Client1.
  • For the remaining parts of the client project (client-2, client-3, client-4), we will create invidiual React apps. (See instructions below)
  1. Install Node.js. We recommend the latest long term support version (v18.12 at the moment). However, if another project on your system requires the development version of Node.js, that is fine. Managing multiple versions of Node.js on a single system is often painful.
  2. The installer will ask if you want to install C/C++ compiler tools. Do this. Many Javascript modules have native code that should be compiled locally. This will also install Python 3.10 or 3.11. This should be ok, and should still be compatible with other python modules (e.g. psycopg2). You will need to re-rerun the pip install of requirements.txt against the new python version. NOTE: If you run into problems, you may need to uninstall the new python version and revert back to python 3.9.
  3. To test that Node.js is installed, go to the command line. Run node --version. You should see the version that you expect to be installed. You should also check your python version.
  4. We’ll use the project Create React App to get started. On the command line in the folder where you keep your code (your root folder), run npx create-react-app abc123-react-client2 (Later you will have -client3, -client4). This creates a folder and a ton of files.
    At this point, your directory structure should look something like this:
.  
├── .git/  
├── .gitlab-ci.yml  
├── README.md  
├── abc123-react-client2/  
│   ├── .gitignore  
│   ├── README.md  
│   ├── node_modules/  
│   ├── package-lock.json  
│   ├── package.json  
│   ├── public/  
│   └── src/  
├── public/    
│   ├── index.html  
│   └── index_1.html  
  1. If all goes well, go to the abc123-react-client2 folder on the command line, and you should be able to run npm start (or yarn start - Yarn is a simpler alternative to the standard node package manager npm). This will start a development server locally, and it fires up a browser automatically at http://localhost:3000
  2. Now is a good time to commit to Git. Commit this starter code and push to your repository on RIT’s GitLab. Make sure that worked before moving forward.
  3. We need to make one small change to the starter code. In package.json, add the key-value pair homepage: "." to the top-level settings. We’ll explain in the starter code walkthrough. So the code looks like this:
{
  "name": "abc123-react-client2",
  "version": "0.1.0",
  "homepage": ".",
  // lots of other stuff after this
}
  1. Let’s test out modifying code locally and then showing up in the browser. Open up src/App.js and change the text Edit src/App.js and save to reload to something else. Switching back to your browser, you’ll see the change is updated (it should auto-reload, but this can be a little flakey, so you may need to refresh the browser manually).
  2. Take a tour of the starter code for a bit. Make a guess in your mind as to what each file does, then check your guess against our explanation down below in our walkthrough. Don’t rush this step. Knowing all of these pieces is important.
  3. For now, go to src/App.js and delete everything inside of the <div className="App"></div>. Also, to suppress a warning, comment out the logo import line. Add a simple heading, with an <h1> tag within the <div>. Thus, your React app will look more like this:
import React from 'react';
// import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <h1> Welcome to React!</h1>

    </div>

  );
}

export default App;
  1. Commit in Git and push to your GitLab repository.
  2. Next, let’s get this up and running on our CI. For this project, we’re going to be emphasizing continuous delivery, which means that every build that succeeds on the repository will be posted to a website. Fortunately, the GitLab pages feature allows us to post code from our repository into a static site associated with the project. So let’s make use of that. Use this setup for your .gitlab-ci.yml Since you will have separate React apps for client-2 onward, you will need edit the .yml file for each app. For example PROJECT_NAME2 (for client2) would be abc123-react-client2. When you do Client3, you would set PROJECT_NAME3 would be abc123-react-client3 and so on. Note that your client-2 webpage will be in a subdirectory of the main URL. Once again, you can see the root of the website in the gitlab settings/pages. We have also added the full URL in the output of the CI. Make sure you check that!
image:
  name: node:18

variables:
  CURR_APP: "" #Will be changed to your React project name

  PROJECT_NAME2: none #e.g. acb123-react-client2.  Change to YOUR project 

  PROJECT_NAME3: none  #e.g. acb123-react-client3.  Change to YOUR project 

  PROJECT_NAME4: none  #e.g. acb123-react-client4.  Change to YOUR project 

  OUTPUT_DIR2: public/$PROJECT_NAME2
  OUTPUT_DIR3: public/$PROJECT_NAME3
  OUTPUT_DIR4: public/$PROJECT_NAME4
  URL_APP2: $CI_PAGES_URL/$PROJECT_NAME2
  URL_APP3: $CI_PAGES_URL/$PROJECT_NAME3
  URL_APP4: $CI_PAGES_URL/$PROJECT_NAME4

.script-run-build: &script-run-build |
  echo "CURR APP:"$CURR_APP

  #Make sure directory for the app exists

  if [  ! -d "$CURR_APP" ]; then
    echo "CURRENT APP not set, or directory does not exist - nothing to build!"
  else
    cd $CURR_APP 
    echo "Create subfolder in gitlab public folder"
    mkdir ../public/$CURR_APP
    npm install
    npm run build
    echo "Copy build folder to gitlab public folder"
    cp -p -r build/* ../public/$CURR_APP 
    #echo "Your web page will be at" $CI_PAGES_URL"/"$CURR_APP

  fi
  echo "Return to the root directory"
  cd .. 

cache:
  paths:
  - node_modules/

before_script:
  - pwd
  - python3 --version
  - node --version
pages:
  stage: deploy
  script:
    # This magical incantation will inject a build version just before </body>"

    - CI="" #Ignore warnings.  e.g. unused classes are warnings but will stop build w/o this

    # Float left on div to place at bottom with react components

    - sed -i "s|</body>|<div style="float:left"><small>Built on GitLab branch <code>$CI_COMMIT_REF_NAME</code> commit <code>$CI_COMMIT_SHORT_SHA</code> $(date)</small></div></body>|g" public/index.html

#    - echo "env"

#    - env

    - echo "Check current directory"
    - pwd
    - CURR_APP=$PROJECT_NAME2
    - *script-run-build 
    - CURR_APP=$PROJECT_NAME3
    - *script-run-build 
    - CURR_APP=$PROJECT_NAME4
    - *script-run-build 
    - echo "URL for CLIENT-2:"$URL_APP2
    - echo "URL for CLIENT-3:"$URL_APP3
    - echo "URL for CLIENT-4:"$URL_APP4
  artifacts:
    paths:
    - public

  1. Let’s break down the above config.
    • For image: we’re just using a standard nodejs image from Dockerhub - nothing special like we had on our previous projects.
    • The cache: key is for speeding up our builds - we don’t want yarn to have to download ~150mb of stuff every time we build, so we save the node_modules directory.
    • For stage: we’re using deploy instead of test - GitLab has various stages and so far we have only used test. There’s all kinds of logic you can build in there, e.g. “don’t deploy unless test passes”.
    • The script: line starting with sed has a magical command using Bash that needs explanation. When we build the site and put it on GitLab pages, we want to know what was actually posted. For example, a build might fail so then you’re looking at that previous commit’s build. Feel free to use, not use, or customize this as you see fix. This line isn’t strictly necessary, but trust me, you’ll be glad you have it when you realize you’re looking at an old build.
    • The npm run build makes a production build, which bundles and minify the project into as few and smallest files as possible with some backwards compatibility.
    • The rm command removes our React public folder since it would conflict with GitLab’s public folder.
    • The mv command moves our build to where GitLab expects it to be.
    • The artifacts: part tells GitLab pages to save the public folder after our build finishes - so it can be used for GitLab pages.
    • You should also know that, in order to post to a GitLab pages site, the job must be called pages - that’s how it knows to put everything on a static site.
  2. After reviewing the CI build settings, commit and push to your repo. Check that the build passes.
  3. Once the build has passed, go to your project on GitLab, and go to Settings > Pages to see the URL that your code is posted at. Go there and keep note of that URL for the future so your teammates can see your latest build. Note that there’s our build information at the bottom of the page, whereas we don’t have that in our development build. Also note that it’s UTC time, which is four hours ahead of New York’s time zone.

React.js Starter Code Walkthrough.

  • node_modules - this directory is infamous. Yes, after creating a basic React.js app that directory now has over 33 thousand files! This is all of the code that the framework depends on, which is the culimination of a massive community of open source developers. No need to ever touch this directory yourself - using yarn or npm commands essentially manages this directory. In a pinch, deleting this directory and reinstalling is the node.js equivalent of “have your tried turning it off and on again?". Also: no need to put this in your Git repo - hence our .gitignore file ignoring it.
  • .gitignore - you’ve seen this before. This one in particular is anticipating that we’re using a lot of things we haven’t turned on yet.
  • public/ is the directory where we keep our static content. Anything that just needs to be copied over to the final site should go here: images, metadata, etc. Anything that needs preprocessing, compiling, bundling, minifying, or any kind of munging does NOT go here.
  • public/favicon.ico - this is that little icon you see in your browser tab. Perhaps the only time in your life where people still use the .ico image format (other formats are allowed by the way, and ICOs are just bundles of PNGs with zooming metadata).
  • public/index.html - the root of our website. Most web servers are configured that when a url goes to a directory, then it opens up index.html. You will be porting your old code over to here, but then primarily working in the src/ folder as we start using React.js components for most things.
  • public/manifest.json - this is a configuration file that gives various metadata required for React to use some extra browser features, learn more if you like.
  • public/robots.txt - this is a file that is a convention for how a (friendly) search engine should treat your website. It is just advice for doing search engine optimization for Google, Bing, etc. This one happens to default to “index everything on our site”.
  • src/ is the root of our React app. When we get to using React.js, we’ll be living most of our development lives here. Notice how we have various file types in here.
  • src/App.css is our main Cascading Stylesheet. Why isn’t this in public/? Because React will actually check your CSS for validity, and you can also do some preprocessing with packages like SASS to make your CSS cleaner to read and easier to maintain.
  • src/App.js is the top-level React component. For now it does nothing.
  • src/App.test.js is the React equivalent of a unit test. One of the most useful parts of React is that it encourages (nay forces) you to break your system down into components, which naturally means that more of your system is testable.
  • src/index.js is the entrypoint to our React project. Note how this is what instantiates App.
  • src/logo.svg is in the src folder, but it could also probably be in the public/ folder. SVG files are XML, so React might do some validation against it too as part of the build process, so that might be why it’s here. Or, perhaps the code will want to modify the SVG on the fly, in which case the SVG internal code itself is accessible to React.js. Typically, we put SVG files into src/ and not public/ for this reason.
  • src/serviceWorker.js has some boilerplate for improving performance of the React runtime. It also does some extra work to make development easier locally, i.e. when deployed on localhost. In a real system you might tweak this to your needs, but we won’t be doing any work here.
  • src/setupTests.js is the entrypoint for the testing framework, in this case this is what invokes our testing framework Jest
  • package.json - this is used by yarn and npm to manage our packages, as well as some configuration options for React builds. This file and yarn.lock are consulted when managing node_modules. We made a small edit earlier for homepage - this setting tells React that we want our links to all be relative to the root directory, not absolute to the URL. This means that our site can be deployed at any URL path (e.g. both localhost:3000/ and example.com/foo/bar/baz/). This is especially helpful since GitLab pages deploys the site at a deeper path than our development server does. Learn more if you like.
  • yarn.lock is a file that “freezes” what version of the packages you are using. For example, your package.json might say use package foo 1.0, but then package foo comes out with 1.0.1 and then 1.0.2. So which one are you actually using? The yarn.lock file is the definitive authority on that. Yarn consults this file when figuring out what to put in node_modules.
  • README.md has lots of React-related stuff to help you on your way.