I think we have all been there. You have an idea for a new little side project and the stars finally align:

  • You have a day free.
  • Your IDE is up to date and you have a clear vision.
  • You've setup your repository on GitHub.
  • And if you're like me, you've just rolled a new React project using Vite for the first time.

Look. I know that create-react-app was given the boot a loooong time ago but, and it was easy enough to get the ball rolling and setup typescript and everything else I wanted.

BUT. And here comes the but. I was busy working on my online resume. You know. That typical engineer-with-a-github-profile-thing where you use your Github page to host a small about you with some links.

Like most of you; I had the genius idea to throw my CV/Resume/Collection of my Professional Bones™ in a repo with my little cute React App and call it a day.

onClick: () => {
    window.open("../../assets/resume.pdf", "_blank");
}

Locally, this works like a charm, however the moment my deploy pipeline wraps up its thing I realize with horror that I get a lovely 404 page.
File not found

Not to stress! This is pretty simple. Since I'm used a Webpack setup professionally (with a lot of customizations), I hadn't worked with Vite as a bundler before. In short, I just had to use Vite's way of handling assets and import my PDF document and use the import itself in my function:

import ResumeFile from "../../assets/resume.pdf";

onClick: () => {
    window.open(ResumeFile , "_blank");
}

Now you're probably wondering why is this called the "Vite Chronicals" if all I had to do was change my import and all is good? Becuase I am not satisfied! That's why! When I click on my shiny new resume button, the actual resume is opened on this URL: https://svbygoibear.github.io/assets/resume.pdf. What I want is it to open on https://svbygoibear.github.io/resume.pdf. I know I can just move the PDF itself to my root/public folder but I want to keep it under assets but when I bundle and host it I want it at the root.

Which bings me back to the bundler... For this I added some extra configuration on build. This is my before:

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

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [react()],
    base: "/"
});

And this is my after:

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

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [react()],
    base: "/",
    build: {
        rollupOptions: {
            input: {
                main: "index.html"
            },
            output: {
                assetFileNames: assetInfo => {
                    if (assetInfo?.name?.endsWith(".pdf")) {
                        return "[name][extname]";
                    }
                    return "assets/[name]-[hash][extname]";
                }
            }
        }
    }
});

The important part here is the output. Here I check if a file ends with PDF and I simply return it without the assets root. Does this work though?

Gif of success

Now for my next challenge. I want to (very temporarily mind you) use a JSON file with a sample "payload" of my resume and read the file, parse it to typed instance and pass that around my relevant components instead of hardcoding it. But I just know will have more fun with Vite.

Until next time!

All I want to say with this article is that even after 10 years of working as a Software Engineer, you will still make silly mistakes. Make them! This is how you learn.

Versions Used

node:  18.14.0
vite:  6.3.3
react: 18.3.1