Deploy Vite React with React Router App to GitHub PagesA Comprehensive Guide to Deploying Vite-React Projects on GitHub Pages

Introduction

Deploying a Vite React app with React Router can seem like a daunting task if you haven't done it before. Sure, the Vite documentation offers some pointers, but what about the intricacies? What do you need to know if you're using React Router? That's exactly what this blog post aims to provide: a comprehensive guide to deploying your Vite React with React Router app to GitHub Pages.

We will cover the initial setup, the specific configurations needed in the Vite config file, how to automate deployments with GitHub Actions, and more. By the end of this article, you'll be armed with the knowledge to deploy your Vite React app seamlessly.

Configure Vite Config File

The first step in deploying your Vite React app to GitHub Pages is to modify the vite.config.js (or vite.config.ts) file. You'll want to add a property called base, which should be set to your repository name. For instance, if your repository name is my-vite-react-app, your config should look something like this:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig(({ command }) => {
    const config = {
        plugins: [react()],
        base: '/',
    };

    if (command !== 'serve') {
        config.base = '/my-vite-react-app/';
    }

    return config;
});

In the code snippet above, notice that we set the base to / by default. However, when not in serve mode (e.g., during the build), we set it to /my-vite-react-app/. This ensures that the URLs are correct when the app is deployed to GitHub Pages.

GitHub Actions for Continuous Deployment

For an automated and continuous deployment pipeline, GitHub Actions are your go-to choice. First, navigate to your repository on GitHub and go to the "Settings" tab. From there, click on "Pages," and then set the build and deployment source to "GitHub Actions."

Next, create a .yml file in the .github/workflows/ directory of your repository to define the GitHub Actions workflow. You can name it anything you like, but for this guide, let's call it deploy.yml. Inside this .yml file, you'll define a workflow to run the build and deploy tasks, like so:

# deploy.yml
name: Deploy to GitHub Pages

on:
    push:
        branches:
            - main
    pull_request:
        types: [synchronize]
    workflow_dispatch:

# Set the GITHUB_TOKEN permissions to allow deployment to GitHub Pages
permissions:
    contents: read
    pages: write
    id-token: write

# Allow one concurrent deployment
concurrency:
    group: 'pages'
    cancel-in-progress: true

env:
    NODE_VERSION: 18.17.1
    GENERIC_LIBRARY: frontend/generic-library
    BASE_URL: ${{ secrets.BASE_URL }}

jobs:
    deploy:
        name: Deploy
        runs-on: ubuntu-latest
        environment:
            name: github-pages
            url: ${{ steps.deployment.outputs.page_url }}
        steps:
            - name: '📥 checkout repository'
              uses: actions/checkout@v3
              with:
                  fetch-depth: 0

            - name: '🔄  Cache node_modules'
              uses: actions/cache@v3
              with:
                  path: ~/.npm
                  key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
                  restore-keys: ${{ runner.os }}-node-

            - name: '🔧  Setup NodeJS ${{ env.NODE_VERSION }}'
              uses: actions/setup-node@v3
              with:
                  node-version: ${{ env.NODE_VERSION }}
                  cache: 'npm'

            - name: '🔧 Install npm@latest'
              run: npm i -g npm@latest

            - name: '🔧 Install dependencies'
              run: npm install

            - name: '🏗️ Build'
              run: npm run build

            - name: '🔧 Setup Pages'
              uses: actions/configure-pages@v3

            - name: '📦 Upload artifact'
              uses: actions/upload-pages-artifact@v2
              with:
                  path: './dist'

            - name: '🚀 Deploy to GitHub Pages'
              id: deployment
              uses: actions/deploy-pages@v2

This workflow will trigger every time you push to the main branch. It checks out your code, sets up Node.js, installs dependencies, runs the build command, and then deploys the dist folder to Github Pages.

Setting Up React Router

If you're using React Router in your Vite project, you'll need to update the router's basename to match the base setting in your Vite config. Vite provides an environment variable called import.meta.env.DEV, which you can use to determine whether the app is running in development mode.

// App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';

function App() {
    return (
        <BrowserRouter basename={import.meta.env.DEV ? '/' : '/my-vite-react-app/'}>
            <Routes>
                <Route path="/" element={<HomePage />} />
                <Route path="/about" element={<AboutPage />} />
            </Routes>
        </BrowserRouter>
    );
}

Here, we set the basename to / when running in development mode and to /my-vite-react-app/ when building for production. This ensures that the URLs generated by React Router align with those generated by Vite.

Or if you use routes as components:

// index.jsx
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import App from './App';
import ConceptCards from './path/to/ConceptCards';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const routes = [
    {
        name: 'Concept Cards',
        path: '/concept-cards',
        component: ConceptCards,
    },
    {
        'other routes': '...',
    },
];

const router = createBrowserRouter(
    [
        {
            path: '/',
            element: <App routes={routes} />,
        },
        ...routes.map((route) => ({
            path: route.path,
            element: <route.component />,
        })),
    ],
    { basename: import.meta.env.DEV ? '/' : '/my-vite-react-app/' }
);

ReactDOM.createRoot(document.getElementById('root')).render(
    <React.StrictMode>
        <RouterProvider router={router} />
    </React.StrictMode>
);

Common Pitfalls

When deploying a Vite React app with React Router to GitHub Pages, there are a few common pitfalls to watch out for. First, make sure that you've set the base property in your Vite config file to match the repository name. If you don't, you'll run into issues with React Router's basename property.

Second, and a very important tip, ensure that every time you want to get to one pf the defined routes you use the Link component from react-router-dom and not the a tag. If you use the a tag, the page will reload and you'll get a 404 error. (Note: it took me a while to figure this one out.)

Use Cases and Web Development Projects

Deploying a Vite React app to GitHub Pages has its advantages, especially for smaller projects, portfolio websites, or documentation sites. This method is cost-effective (it's free!), quick, and easy to set up.

For instance, if you're a student or job-seeker, you could build a portfolio website using Vite and React Router and host it on GitHub Pages. Not only does it showcase your coding skills, but it also demonstrates your understanding of CI/CD pipelines through GitHub Actions. Similarly, startups or smaller companies may use this approach for landing pages, project documentation, or MVPs to quickly get their projects online without incurring additional costs.

Caveats

Before you rush off to deploy your Vite React app to GitHub Pages, there are a few caveats you should be aware of. Understanding these will help you make informed decisions and potentially save you from future headaches.

Firstly, this method ties you to GitHub Pages' hosting. While it's a robust and reliable platform, you won't have as much control over server configurations as you would with a more dedicated hosting solution. If your project requires specific back-end logic or server-side rendering, GitHub Pages will not be sufficient.

Secondly, if you try to serve the dist directory locally after running npm run build, you may encounter a blank page. This is because the base property in the Vite configuration is set to align with GitHub Pages' subdirectory structure. Local servers may not be able to interpret this configuration in the same way, leading to potential issues.

Additionally, using package managers other than npm or yarn may introduce uncertainties. As of this writing, GitHub Actions do not natively support other lock files like pnpm-lock.yaml from pnpm. So, it's advisable to stick with npm or yarn, making sure to include the package-lock.json or yarn.lock in your repository.

Finally, keep in mind that the root path of your deployment depends on your repository name. If you decide to rename your GitHub repository, you must also update the base in vite.config.js and basename in your React Router configuration to match the new repository name. Failing to do so will break your application routing and asset linking.

By being aware of these caveats, you'll be better prepared for a smooth deployment experience. While GitHub Pages offers a fantastic solution for hosting static sites, it's important to understand its limitations based on the specific needs of your project.

Frequently Asked Questions (FAQ)

In this section, we aim to address some of the most frequently asked questions about deploying a Vite React app with React Router to GitHub Pages. Let's delve into some of the common queries that might come up during this process.

Why am I seeing a blank page when I serve the dist directory locally?

If you see a blank page when serving the dist directory locally, it's likely due to the base configuration in your vite.config.js file. This is set up to work specifically with GitHub Pages and may not align with how local servers interpret the root directory. You may need to modify the base property temporarily to test the build locally.

Can I use a package manager other than npm or yarn?

As of the current writing, GitHub Actions only supports npm and yarn due to the recognized lock files (package-lock.json for npm and yarn.lock for yarn). While you may use other package managers locally, for GitHub Actions to work seamlessly, it's recommended to stick to npm or yarn.

What should I do if I rename my GitHub repository?

If you rename your GitHub repository, remember to update the base property in vite.config.js as well as the basename in your React Router configuration. Neglecting this will lead to broken routes and linked assets on your deployed app.

Why do I get a 404 error on child routes when refreshing the page?

This issue arises because GitHub Pages tries to locate an HTML document matching the child route (like /about) but can't find one, as it's a single-page application. To work around this, you can copy your index.html to a 404.html during the build process. This way, GitHub Pages will redirect 404s to the correct application route.

Is it possible to host my Vite React app on other platforms like Netlify or Vercel?

Yes, you can host your Vite React app on other platforms like Netlify or Vercel. However, you'll need to update your configuration settings to suit the hosting environment of your choice. If you are transitioning from GitHub Pages, ensure that you modify the base and basename configurations to match your new root directory.

We hope this FAQ section has been helpful in clearing up any questions you may have. Feel free to reach out if you have more questions that were not addressed here.

Troubleshooting

Deployment Fails on GitHub Actions

Symptom: The GitHub Actions workflow for deployment fails, throwing errors in the process.

Solution: Double-check the syntax in your .yml file. Make sure that all the steps in your workflow are correctly formatted and that you've included all the necessary environment variables.

Note: If you have environment secrets, ensure they are added to GitHub under your repository's "Settings > Secrets."

Blank Page After Deployment

Symptom: You navigate to the deployed URL and see a blank page.

Solution: This could be due to several issues. Check the browser's console for any error messages, which could provide clues. Ensure that your base setting in vite.config.js matches the base URL of your deployed project.

Router Errors

Symptom: After deployment, routing doesn't seem to work, and you see a 404 error when navigating to other pages.

Solution: Make sure your routing base path is set correctly, particularly when you're using GitHub Pages, which has a different root than your local environment. Confirm that your BrowserRouter or RouterProvider has the correct basename set.

Assets Not Loading

Symptom: Your JavaScript, CSS, or image files are not loading correctly on the deployed version.

Solution: Ensure that your asset paths are relative and not absolute. This ensures that they can be found regardless of the base URL of the site. Also, check the base setting in your Vite configuration file.

Local Testing Shows Errors

Symptom: When you run your app locally with npm run dev, you see errors that you don't encounter on the deployed version.

Solution: This could be due to environment-specific issues. Make sure that you're using the same Node.js and npm versions as specified in your package.json and that all dependencies are correctly installed with npm install.

Each of these troubleshooting tips is a common issue you may encounter, but the list is by no means exhaustive. Always refer to the documentation and consider seeking community support for issues that aren't covered here.

Conclusion

Deploying a Vite React app with React Router to GitHub Pages involves

a series of steps, each crucial for a seamless experience. By properly configuring your Vite settings, setting up a GitHub Actions workflow, and updating React Router's basename, you ensure a robust and automated deployment process.

Remember, this approach is particularly useful for smaller projects where quick deployment and cost-effectiveness are key. Whether you're building a portfolio or a startup MVP, mastering these steps will equip you with a skill that's increasingly important in the modern web development landscape.

What's Next?

Congratulations, you've successfully deployed your Vite React app with React Router to GitHub Pages! But the journey doesn't stop here. Software development is an ever-evolving field, and there are always ways to improve and expand your project. Here are some suggestions for what you might consider doing next:

Learning Advanced Routing Techniques

While basic routing is often sufficient for simpler projects, understanding more complex routing strategies can help you create more dynamic and user-friendly applications.

Code Splitting

Vite provides out-of-the-box support for efficient code splitting. Learn how to leverage this feature to make your application load faster, improving the user experience.

Adding Backend Services

A front-end application often becomes more useful when it can interact with a back-end service. Consider learning about serverless architectures or setting up a RESTful API to give your app more capabilities.

SEO and Accessibility

Now that your app is live, think about how people will find it. Learning the basics of SEO can make your app more discoverable. Additionally, ensuring your app is accessible will make it usable by a wider audience.

Automated Testing

If you haven't already, implementing automated tests can help you ensure your app remains functional as you add new features. Frameworks like Jest or the React Testing Library can be integrated into your existing workflow.

Contribution Guidelines

If your project is open source, you might consider adding contribution guidelines and other community-friendly documentation to encourage others to contribute to your project.

Monitoring and Analytics

Consider integrating analytics to monitor user engagement and error tracking to catch any issues in real-time. This data will provide invaluable insights into how your app is being used and where you can improve.

Whatever you choose to pursue next, keep learning and building. Each new project or feature is an opportunity to grow as a developer. Best of luck on your coding journey!

References