GumGum Tech Blog
Published in

GumGum Tech Blog

Faster development experience with Vite, Hugo and Preact

An person sitting with the laptop in the middle of brow analog clock
Photo by Kevin Ku on Unsplash

Developing basic websites with Hugo is simple and fast, but what if we wanted to bring it to another level and use JavaScript frameworks like React or Preact? Integrating these two technologies can be tricky sometimes as you need to spend some time configuring it, and in the end it turns out that not everything is working as it should. For example, some Sass libraries using imports with ~ won’t compile, or saving a component refreshes the whole page and all the component’s state is lost making the developer experience miserable. These are some of the problems I’ve come across while integrating Hugo with Preact. My first thought was to use Webpack, Parcel and Snowpack, but none of these worked as I wanted them to. To my rescue I found Vite, a tool that is easy to configure, and solved all my issues I had previously, making the developer experience heaven! In this blog, I’ll show you how I solved the issues by integrating Vite into the project.

Integrating Vite with Hugo

Vite is a JavaScript build tool that provides a faster development experience. It serves code locally during development, and bundles assets for production. It’s similar to tools like Webpack or Parcel, but it comes with other benefits and is easier to configure. You can check the final project on my GitHub.

Let’s start by implementing Vite into a Hugo project

Vite and required plugins need to be added to your application. Note that they are added as dev dependencies.

$ npm i -D vite vite-hugo-plugin @preact/preset-vite npm-run-all onchange typescript

Vite configuration is relatively simple, and in this scenario we will use plugins to do all the hard work for us!

Let’s understand how Vite works before we jump into its configuration.

The first step is to build your Hugo application into the dist directory without bundling assets, then run the Vite build command to bundle assets from the dist and assets directories. The reason for that is Hugo renders pages to HTML, but not the assets (unless specified with Hugo Pipes). For bundling the assets, we use Vite which gives more flexibility over building files for production or running a website locally during development.

Diagram showing how Hugo works with Vite

Let’s start by creating a vite.config.ts file under the root directory of the application. The file should export Vite’s config. Vite provides helper functions to assist with the creation of configuration.

After creating the basic scaffolding, we can move to letting Vite know which directory is the root app directory, and where Hugo’s output build files are. It’s good to mention that the config file is executed by the Node.js environment, so we have access to __dirname and path.resolve .

const appDir = __dirname; // In this case the root dir is where config file is.const hugoOutDir = resolve(appDir, 'dist');

After that, we need to add preact and hugoPlugin to config, under plugins : PluginOption[] option

import preact from '@preact/preset-vite';
import hugoPlugin from 'vite-hugo-plugin';
// ... rest of the codedefineConfig({
plugins: [preact(), hugoPlugin({appDir, hugoOutDir})]

This is how vite.config.ts should look:

Final vite.config.ts file

After configuring Vite, let’s create scripts that will build our application or run in dev mode. To do that, we need to open package.json .

Configuration of the build scripts

To properly build our application, first we need to build our Hugo application hugo -d dist , and then Vite vite build .

“scripts” part of package.json

Running npm run build in console should output a similar result:

npm run build — output

Configuration of the development scripts

Development mode is trickier than building, as we need to listen to changes on Hugo files, and then rebuild files so that the Vite dev-server will refresh. To the rescue comes the npm library onchange that will listen to specific files and run hugo:build and Vite will know when to reload as it’s watching for changes in dist or assets directories (this part is configured using vite-hugo-plugin).

“scripts” part of package.json

Running npm run dev in a terminal should output a message with the url pointing to your local website.

npm run dev — output

Adding Preact app with TypeScript into a Hugo website

Preact is a faster alternative to React with the same modern API that aims to be 100% compatible with React.

Configuring TypeScript inside of the project

Configs are pretty basic, one thing to remember is to add, JSX config (needed while using Preact), and paths. It is worth mentioning that adding path to tsconfig won’t work as Vite needs to resolve that path (which can be done using config). By default the Hugo plugin resolves js/* path so there’s no need to do that.

Configuration of tsconfig.base.json

Base config from which all the other configs inherit, this could also be used to create additional config for Jest.


Configuration of tsconfig.json

Config file placed in assets/tsconfig.json for TypeScript configuration around the Preact application.


Create the Preact app

To start the final step, let’s create assets/js/src/app.tsx . In this example, we will test the HMR by creating a simple component with state.


Create the root component of the application in assets/js/index.tsx that will render the application into an element on the page.


The last and final step is to add the script into the website. For our case, create a Hugo page (eg Preact), then in layout/name_of_the_page_we_created/list.html, add a <script> tag with src /assets/js/index.tsx. Note that the file is added with a .tsx extension that Vite will automatically replace with the generated js file.


That’s it, the application is ready to run and have fun with! If you want to check out advanced usage of this app, I strongly recommend checking out and using this Hugo Preact theme that comes with all the configuration, tests, and an exampleSite you can use as a boilerplate!


At first I was skeptical to use Hugo with Preact as it felt like there was something missing. Writing pages was easy, but managing the assets that Hugo couldn’t process or writing complex components in Preact was painful. With each save, the page was reloading instead of doing the hot module replacement that any modern projects built on top of Webpack have. I didn’t feel like Webpack was a good solution for my project as it’s very complex and sometimes can get messy. This is where Vite caught my attention. Thanks to its great documentation, I was able to understand the mechanics of it and quickly get it implemented for my project.

We’re always looking for new talent! View jobs.

Follow us: Facebook | Twitter | LinkedIn | Instagram



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store