[Solved] React app bundled with Parcel would not deploy correctly in GitHub Pages
Tags: react, parcel, github, deployment
Published: 2023-02-08 20:01:39

I was learning ReactJS, making my first dynamic-ish frontend and I was happy enough with that little project as a first React project. It worked perfectly in the local dev server provided by Parcel. I bundled the project and run a simple HTTP Python local server with the command:

```python
python -m http.server 3000
```

It worked perfectly.

So I was ready to deploy the app in GitHub Pages, see if I could even do that. I pushed the changes and the `dist` folder as well, configured a default GitHub Actions script for a static webapp deployment and waited. It did not work, the js and css files were not being received and the console showed a couple of 404 errors. I found out that the page was trying to pull files from my root url, that being [https://gabrieldiem.github.io](https://gabrieldiem.github.io). So I tried making a couple of changes to the GitHub Actions script but I couldn't make it work.

After that I turned to a package called [gh-pages](https://www.npmjs.com/package/gh-pages), which pushed the bundled files to a new branch and deployed the Github Pages website from there, and I gave it a try.

First I tried deploying a simple create-react-app app to know what I was trying to do was even possible (I was **not** using create-react-app btw). And it worked! So it had to be something about my bundling config.

I found out that I had to add to the package.json the entry:


```json
"homepage": "http://gabrieldiem.github.io/Portfolio_like_project"
```


With _Portfolio_like_project_ being the repo name. So I bundled the project as I was doing before with the script:

```json
"build": "parcel build src/index.html"
```

And set up the gh-pages required scripts:

```json
"predeploy": "npm run build",
"deploy": "gh-pages -d dist"
```

I gave it another try, same as before, it did not work again.
Then I tried a couple things with absolute routes and ended up in a GitHub issue of the Parcel repo saying that Parcel and absolute routes don't mix well. So I ditched that. Okay, maybe hardcoding the absolute route directly into the HTML and JS, I ditched that as well (not only because it was awful but also because it didn't work).

Eventually found out that what could solve my problem was to add a `--public-url` flag to the parcel bundle script so it ended looking like this:

```json
"build": "parcel build src/index.html --public-url /Portfolio_like_project/"
```

Again, not using absolute routing, instead using the relative route of the root url, which I guessed was https://gabrieldiem.github.io so adding the repo name would make the fetching request of the js and css files work properly.
This time it kind of worked. I solved the problem of the requests ending in a 404 error, so it was serving the files as it should. The problem was I still had a blank page staring at me, nothing at all was displayed.

By this time, I had already spent a couple of hours making pointless changes, debugging, bundling in different ways (with no cache access, without optimizations, etc) and reading tons of docs, Stack Overflow posts and GitHub issues. I took a little rest and came back to it. I kept investigating and found these two posts that gave me the key of what was happening:

[Building a Static Single Page Application with JavaScript, for GitHub pages and more …](https://medium.com/swlh/building-a-static-single-page-application-with-javascript-for-github-pages-and-more-eb568b436bea#8f76) written by Weiyuan.

[So you want to host your Single Page React App on GitHub Pages?](https://itnext.io/so-you-want-to-host-your-single-age-react-app-on-github-pages-a826ab01e48) written by Brendan McIlhenny.

And the key was that besides the general routing of the application, I had also used the React components `BrowserRouter`, `Route` and `Link`, so it appeared that the breaking point could have been there. Spoiler alert: it was.

So I fixed the routes and prepended a `/Portfolio_like_project` to the destiny routes of Routes and Links, deployed it and it worked! I was happy that it was finally live and I managed to find the ways things work. 

Until, I run the dev local server and it crashed, which was logical because it couldn't find the files and routes pointed by the new location I prepended before. I tried a couple of workarounds and settled with the next solution:

- I created a `.env` file which contained the relative path I wanted to add:


```javascript 
BASE_RELATIVE_PATH="/Portfolio_like_project"
```


- I created a new js file which was in charge of detecting if I was in production mode and at the same time not in localhost, the code looks like this:


```javascript 
const isEnvProduction = process.env.NODE_ENV === 'production';

const isEnvNotLocalhost = window.location.hostname !== 'localhost' && !window.location.href.includes('127.0.0.1');

const baseRelativePath = (isEnvProduction && isEnvNotLocalhost) ? process.env.BASE_RELATIVE_PATH : '';

export default baseRelativePath;
```


A little note here: Parcel sets the NODE_ENV variable to 'production' or 'development' depending on the build (if it's been built and bundled, or if it's running on the dev server, respectively). So I took advantage of that. If I was in a production environment I prepended the relative path and if I wasn't I prepended an empty string.
Then all I had to do was use this basePath before every redirection, like this:


```javascript 
import baseRelativePath from 'path.js';

<Link to={`${baseRelativePath}/`}>Home</Link>
<Route path={`${baseRelativePath}/`} element={/*some element*/} />
```


After making that change I managed to make the app work in a local development, local production and remote production environment. Success!

It is not the most elegant solution though, making a template literal for every path in order to prepend this basePath sounds like something that could be solved in other way. As a React beginner I find it good enough for the moment, and I hope I can find a better way of doing this, if I do I will be pasting a link for the update here. As for now, it is staying like this.

Thanks for reading! And if you came here and I managed to help you, I'm glad I could serve you useful 😊.