Svelte Components in Hugo
Making interactive components simple in Hugo.
Svelte is a javascript (non-)framework for creating interactive components.
Svelte components are defined in self-contained .svelte
files, which describe all of the CSS styles, HTML markup, and javascript functionality necessary for the component to run.
The Svelte compiler is then run on these .svelte
files, and produces vanilla JS from them, which can be used anywhere.
This article details how to integrate Svelte components into a Hugo site.
Installing Dependencies
All of the paths starting with /
in the remainder of the article refer to the root of your Hugo site's repository.
Rollup is a javascript "module bundler". We can configure it to automatically find Svelte files in a particular directory, and compile them into /static
.
As long as Rollup runs before Hugo, we can then include those compiled JS files into the Hugo site as if we had defined them by hand in the /static
directory.
In order to start using Svelte, install yarn
and use yarn init
to set up package.json
with some initial values.
Install Rollup and the plugins we'll be using:
Install Svelte and its associated Rollup plugin:
Install Typescript (typescript is optional, just a personal preference):
Directory Structure
The rollup config file can be stored anywhere, but I chose the following directory structure in my Hugo site for simplicity:
Configuring Rollup
The next step is configuring Rollup, so that it knows where to find Svelte components, and where to install their compiled vanilla javascript files.
This article from codeandlife.com made setting up Rollup for embeddable Svelte components much easier.
My rollup.config.ts
file looks as follows:
This code searches the svelte/components
directory (configurable via the COMPONENT_DIR
variable) for .svelte
files, and returns separate Rollup configs for each one.
For each file, the buildOptions
function returns a configuration object that tells Rollup a few things:
- build
embed.js
- replace all
%%%SVELTE_FILE_PATH%%%
instances with the path to the current.svelte
file - run the svelte compiler
- output to
/static/components/{filename}.js
i.e./static/components/SomeComponent.svelte.js
In order to understand how the above set of steps plays out, we also need to take a look at embed.js
:
This javascript file imports a Svelte component from some path (which is filled in by Rollup), and renders it to the DOM, directly above where the current <script>
tag is (the current <script>
tag is acquired via document.currentScript
).
Combining these two parts, we should be able to embed compiled Svelte components by simply including a script tag that looks like <script src="/components/MyComponent.svelte.js"></script>
.
We'll take a look at making that even easier in the next section.
Setting up the Hugo Shortcode
The next step is to setup a Hugo "shortcode" to make embedding Svelte components from content pages easier than manually creating <script>
tags. Simply add to /layouts/shortcodes/svelte.html
:
The <noscript>
tag includes a message to show to browsers where javascript is disabled.
With that svelte
shortcode added, Svelte components can be added from content pages very simply:
{{ .Get 0 }}
is replaced by Hugo's templating engine with the first argument to the shortcode (in this case, HelloFromSvelte
), and we are left with:
Since Rollup compiled /svelte/components/HelloFromSvelte.svelte
, and imported it into embed.js
with output at /static/components/HelloFromSvelte.svelte.js
, the resulting script
tag is javascript that has the necessary code to create a div
right above the script
tag and then mount the Svelte component into that div.