react-github-pages icon indicating copy to clipboard operation
react-github-pages copied to clipboard

React with React Router boilerplate for GitHub Pages


This is deprecated, please use Single Page Apps for GitHub Pages

A generic solution that works with all single page apps, not just React

React for GitHub Pages

Live example

React for GitHub Pages is a lightweight solution for deploying React single page apps with React Router browserHistory using GitHub Pages.

I love React with React Router. Need complex views with lifecycle methods and dynamic routing? Done. Need a simple site with a few fixed routes? Use functional stateless components and JSX. Done. And I love GitHub Pages. git push on a gh-pages branch and it's live on a great CDN (for free), does it get any easier than that? But unfortunately GitHub Pages doesn't play nice with React, until now...

Why it's necessary

GitHub Pages is a static server that doesn't support single page apps. When there is a fresh page load for a url like example.tld/foo, where /foo is a frontend route, GitHub Pages returns a 404 because it knows nothing of /foo. This only affects fresh page loads, however, as navigating to /foo from within the single page app is not a problem because the server never receives a request for /foo. (Note you could use hashHistory instead, but really no one wants to use hashHistory with its janky urls and incompatibility with #hash-fragments, e.g. example.tld/foo becomes example.tld/#/foo?_k=yknaj, ugh).

Also, GitHub Pages are always available at example.tld/my-repo-name, even when a custom domain is in use. Accessing the site at /my-repo-name will cause frontend routing to break, so when the site is accessed at /my-repo-name, a redirect to just the domain with no path is required.

How it works

When the GitHub Pages server gets a request for a path defined with frontend routes, e.g. example.tld/foo, it returns a custom 404.html page. The custom 404.html page contains a script that takes the current url and converts the path, query string and hash fragment into just a query string, and then redirects the browser to the new url with only a query string and no path or hash fragment. For example, example.tld/one/two?a=b&c=d#qwe, becomes example.tld/?redirect=true&pathname=%2Fone%2Ftwo&query=a=b%26c=d&hash=qwe.

The GitHub Pages server receives the new request, e.g. example.tld?redirect=true..., ignores the query string and returns the index.html file, which loads the React single page app. The root React Router route has an onEnter hook that calls a function to check for a redirect in the query string. If a redirect is present in the query string, it's converted back into the correct url and React Router redirects to the url which loads the respective routes and components. (Note that these redirects are only needed with fresh page loads, and not when navigating within the single page app once it's loaded).

The other issue of GitHub Pages always being available at /my-repo-name is handled by the same root route onEnter hook function, which checks for the /my-repo-name path and redirects to just the domain (with no path) if needed.

Usage instructions

For general information on using GitHub Pages please see GitHub Pages Basics, note that pages can be User, Organization or Project Pages

  1. Clone this repo ($ git clone https://github.com/rafgraph/react-github-pages.git)
  2. Delete the .git directory (cd into the react-github-pages directory and run $ rm -rf .git)
  3. Instantiate the repository
  • If you're using this boilerplate as a new repository
    • $ git init in the react-github-pages directory, and then $ git add . and $ git commit -m "Add React for GitHub Pages boilerplate" to initialize a fresh repository
    • If this will be a Project Pages site, then change the branch name from main to gh-pages ($ git branch -m gh-pages), if this will be a User or Organization Pages site, then leave the branch name as main
    • Create an empty repo on GitHub.com (don't add a readme, gitignore or license), and add it as a remote to the local repo ($ git remote add origin <your-new-github-repo-url>)
    • Feel free to rename the local react-github-pages directory to anything you wnat (e.g. your-project-name)
  • If you're adding this boilerplate as the gh-pages branch of an existing repository
    • Create and checkout a new orphaned branch named gh-pages for your existing repo ($ git checkout --orphan gh-pages), note that the gh-pages branch won't appear in the list of branches until you make your first commit
    • Delete all of the files and directories from the working directory of your existing repo ($ git rm -rf .)
    • Copy all of the files and directories from the cloned react-github-pages directory into your project's now empty working directory
    • $ git add . and $ git commit -m "Add React for GitHub Pages boilerplate" to instantiate the gh-pages branch
  1. Set up your custom domain - see GitHub Pages instructions for setting up a custom domain
  • Note that you must use a custom domain if you are setting up a Project Pages site in order for GitHub Pages to serve the custom 404 page, however, if you are creating a User or Organization Pages site, then using a custom domain is optional (if you don't use a custom domain delete the CNAME file)
  • Update the CNAME file with your custom domain, don't include https://, but do include a subdomain if desired, e.g. www or your-subdomain
  • Update your CNAME and/or A record with your DNS provider
  • Run $ dig your-subdomain.your-domain.tld to make sure it's set up properly with your DNS (don't include https://)
  1. Set your repo name in index.js, this should match your repository name as it is listed on GitHub
  2. Set your domain name in index.js, if you are using a custom domain then this should match the domain in your CNAME file (except include the https://), if you are not using a custom domain, then this will be https://<your github username or orgname>.github.io
  3. Run $ npm install to install React and other dependencies, and then run $ webpack to update the build
  4. $ git add . and $ git commit -m "Update boilerplate for use with my domain" and then push to GitHub ($ git push origin gh-pages for Project Pages or $ git push origin main for User or Organization Pages)

The example site should now be live on your domain

Creating your own site
  • Write your own React components, create your own routes, and add some style!
  • Change the title in index.html and the title in 404.html to your site's title, also remove the Google analytics script from the header of index.html (the analytics function is wrapped in an if statement so that it will only run on the example site's domain (https://react-github-pages.rafgraph.dev), but you don't need it, so remove it or replace it with your own analytics)
  • Change the readme and license as you see fit
  • After you update your code run $ webpack (or $ webpack -p for production, or -d for development) to update the build, then $ git commit and $ git push to make your changes live
Miscellaneous
  • The .nojekyll file in this repo turns off Jekyll for GitHub Pages
  • Need form submission on your static site? Use Formspree
  • One of the awesome things about the GitHub Pages CDN is that all files are automatically compressed with gzip, so no need to worry about compressing your JavaScript, HTML or CSS files for production