Deploying and building React projects to GitHub Pages with GH Actions
Tags: engineeringmonday, github, parcel, react
Published: 2021-08-02 08:30:45

For my private mini-projects, I prefer to use [Parcel bundler] (https://parceljs.org/) over [Create React App](https://create-react-app.dev/) just because there is less overhead and clutter to clean up. However, by using CRA and the [appropriate package] (https://github.com/tschaub/gh-pages), deploying can be very simple. This post will tell you how to set up build and deploy when using a custom project structure.

## Creating a React/Parcel project

By following steps from [this post](https://blog.jakoblind.no/react-parcel/) we can be up and running in a few minutes. As always with React, you are free to organize the project structure as needed.

### Build for GitHub Pages

1. Enable GH Pages inside repo settings (use **docs** folder, as detailed in [the documentation](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site) )
2. Specify a build script - Parcel should create built files inside `/docs` folder.
Example build script inside package.json: 

`"build-github": "rm -rf docs/* && parcel build index.html --public-url ./ -d docs"`

These two commands: 
1. delete the existing docs folder and all its contents (to make sure we don't have previously built files lying around)
2. run the Parcel build command, as always using *index.html* as entry point, but specifying the built files to go inside */docs* folder, while setting the output files to read from that folder (`./`)

To test this, we can try running `npm run build-github` command and committing the changes, pushing them to master. A green checkmark should appear on your GH repository near the latest commit, indicating all went well. The default URL template for GH Pages is `https://<your-github-username>.github.io/<your-github-repository>`

## Automating the build with every push to master

To avoid having to run that command manually, we should automate this step by using GitHub Actions, another free service from GitHub.

In your repository's project root, create a folder named `.github` and inside it another folder called `workflows`. There, you should create a file named `build.yml` (this name is optional).

Example build.yml file:
```yaml
name: Build gh-pages
on:
  push:
    branches: [ master ]
jobs:
  build-gh-pages:
    runs-on: ubuntu-latest      
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v1
        with:
          node-version: 12
      - run: npm ci
      - run: npm run build-github
      - name: Commit files
        id: auto-commit-action
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          commit_message: build project for github pages
      - name: Push changes
        if: steps.auto-commit-action.outputs.changes_detected == 'true'
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
      - name: No changes detected
        if: steps.auto-commit-action.outputs.changes_detected == 'false'
        run: echo "No changes!"
```

After pushing this file to your remote repository, GitHub will read it and follow steps inside it: on every push to the branch master, it will run the steps detailed in `build-gh-pages` job (name optional) - do a clean npm install (`npm ci`) and run the `npm run build-github` command we created earlier. Make sure you specify the correct node version for your project, as well as replacing the build-github npm command with your custom naming, if required. Feel free to modify the `commit_message` variable as well!

To test this, simply make some changes to your project and push them to the remote repository. An orange circle should appear near the latest commit message on GH repo page, where you can track the progress of the build process. Once ready, a green checkbox will replace the circle and your changes should be visible.

For me, this mini-automation process was a great introduction to GH Actions. I borrowed some code and inspiration from my colleagues [Davor](https://dev.to/shockwavee) and [Maroje](https://dev.to/wnbsmart) with only minor customization required. I hope it will help someone and spark an interest into the wonderful world of automation!