DEV Community

Cover image for RiotJS + ViteJS tutorial

Posted on • Updated on

RiotJS + ViteJS tutorial


RiotJS is getting popular but still lacking visibility compared to mastodons projects like Vue, React, and Angular.

However, Riot is my first choice when creating a front-end, here is why:

  • Minimal learning curve, Small API, Close to HTML/JS standards, no magic tricks, it's accessible to everyone
  • Performant and predictable
  • "Everything you wished native the web components API looked like" mentioned on their website, and I do approve!
  • Tiny build when gzipped (compared to other front-ends)
  • Good documentation

The development tooling is quite broad, and one of my favourites is Vite. However, I can't find any documentation or tutorial to run Riot with Vite! Let's fix that together.

This tutorial will go through all the steps to create a counter; the final result:

Image description

If you want to look at the final code, the GitHub repository:

Build and run Riot with Vite

Init and install packages

Create a new directory

mkdir riot-vite-setup && cd riot-vite-setup
Enter fullscreen mode Exit fullscreen mode

Init the node project

npm init
Enter fullscreen mode Exit fullscreen mode

Now you have to install the following npm packages:

npm install --save-dev riot vite rollup-plugin-riot
Enter fullscreen mode Exit fullscreen mode

Rollup-plugin-riot is a plugin that compiles Riot files within rollup processes. ViteJS uses Rollup under the hood as its default bundler for JavaScript modules. Without it, Riot can't be compiled and used by Vite.

Finally, create a Vite configuration file, vite.conf.mjs:

import { defineConfig } from 'vite'
import riot from 'rollup-plugin-riot'

export default defineConfig({
  root       : process.cwd() + '/client',
  plugins    : [riot()],
  build: { 
    minify       : 'esbuild', /** */
    target       : 'esnext' /** */
Enter fullscreen mode Exit fullscreen mode

Option details:

  • root: defines the project root directory (where index.html is located). In our case, it is located in client.
  • target: Browser compatibility target for the final bundle.
  • minify: Minify the final bundle, Esbuild is 20 ~ 40x faster than Terser and only 1 ~ 2% worse compression.
  • Lean more about Vite configuration:

Base project

All the front-end code will be located in the client directory. Let's create three files:

  • client/index.html: entry point of your front-end, it will mount the Riot application
  • client/index.riot: Riot application
  • client/c-button.riot: Custom button component used by the application.

At this stage, the root directory should look like:

Enter fullscreen mode Exit fullscreen mode

The client/index.html is pretty basic. It imports and mounts the Riot application:

<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>RiotJS + ViteJS</title>
    <div id="root"></div>
    <script type="module">
      /** Load riot.js **/
      import * as riot from 'riot'
      import App from './index.riot'

      const mountApp = riot.component(App)
Enter fullscreen mode Exit fullscreen mode

The client/index.riot imports the custom button c-button and defines three instances:

  • one to increase the counter
  • one to decrease the counter
  • one to print the counter
        <h1> Riotjs + ViteJS </h1>
        <c-button> { } </c-button>
        <c-button primary="true" onclick={ () => update({ total: + 1 }) }> Add </c-button>
        <c-button danger="true" onclick={ () => update({ total: - 1 }) }> Delete </c-button>
        /** Load the custom button **/
        import cButton from './c-button.riot';

        export default {
            /** Define the custom button **/
            components : {
            /** State of the counter **/
            state : {
                total: 0
Enter fullscreen mode Exit fullscreen mode

The client/c-button.riot contains a slot to change the text and props to change the style of the button (default/grey, primary/purple, or danger/orange):

<c-button >
    <button class="btn{ props.primary ? ' btn-primary' : '' }{ props.danger ? ' btn-danger' : '' }">
Enter fullscreen mode Exit fullscreen mode

Now we have everything to start a development server to get a preview of the app!

Run live preview

Start the development server, then access the live preview on http://localhost:5173/ :

npm run dev
Enter fullscreen mode Exit fullscreen mode

Et voilà, you should be able to increase/decrease the counter 🎉 You can make code changes, and the preview will be refreshed automatically.

🛟 If you need any help, leave a comment.

Build for production

Build the front for production:

npm run build
Enter fullscreen mode Exit fullscreen mode

Built files are located in the dist directory.


Using Vite makes the development of Riot application super easy:

  • No-brain configuration
  • efficient development server with HMR (Hot Module Replacement), allowing you to see changes in your code instantly without a full page reload
  • efficient build system with tree-shaking

Thanks for reading! Cheers 🍻


Top comments (5)

jonrandy profile image
Jon Randy 🎖️

I almost missed this. Big fan of RiotJS. Might want to add the #riotjs tag

jonrandy profile image
Jon Randy 🎖️

Although there does seem to be a maintained #riot tag, it appears all/most posts relating to it are under #riotjs. Maybe you should switch to that? Your post with the #riot tag appears to be the only one.

Also, could the dev team sort it out so #riotjs is the main tag for RiotJS? @michaeltharrington

michaeltharrington profile image
Michael Tharrington • Edited

Thanks so much for the call out, Jon!

We do indeed have some features to help us with this. There's a DEV feature called tag aliasing, where we can join two tags together, making one of the tags the main tag.

For instance, we've aliased #js to #javascript, which resulted in 2 things:

  1. If you add #js to a post, we automatically files the post under #javascript instead
  2. If you try to navigate to the tag landing page for #js (, you're going to be redirected to #javascript (

Like you pointed out, most folks have congregated under #riotjs so I think it does make sense to alias #riot to #riotjs. Good suggestion! I'll also be in touch with the mod of #riot to let them know about this adjustment.

steeve profile image

I just changed the tag, thank you!

steeve profile image

Thanks Jon! I just added the #riot tag ;)
I'm a big fan too, and I plan to write more about creating advanced apps. Riot is underrated and lacking of communication/visibility.