RiotJS + ViteJS tutorial

Steeve - Nov 15 '23 - - Dev Community

Introduction

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: https://github.com/steevepay/riotjs-vite-setup

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', /** https://vitejs.dev/config/build-options.html#build-minify */
    target       : 'esnext' /** https://vitejs.dev/config/build-options.html#build-target */
  }
})
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: https://vitejs.dev/config/

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:

package.json
package-lock.json
vite.config.mjs
client/index.html
client/index.riot
client/c-button.riot
Enter fullscreen mode Exit fullscreen mode

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

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>RiotJS + ViteJS</title>
  </head>
  <body>
    <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)
      mountApp(document.getElementById('root'))
    </script>
  </body>
</html>
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
<app>
    <div>
        <h1> Riotjs + ViteJS </h1>
        <c-button> { state.total } </c-button>
        <c-button primary="true" onclick={ () => update({ total: state.total + 1 }) }> Add </c-button>
        <c-button danger="true" onclick={ () => update({ total: state.total - 1 }) }> Delete </c-button>
    </div>
    <script>
        /** Load the custom button **/
        import cButton from './c-button.riot';

        export default {
            /** Define the custom button **/
            components : {
                cButton
            },
            /** State of the counter **/
            state : {
                total: 0
            }
        }
    </script>
</app>
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' : '' }">
        <slot></slot>
    </button>
</c-button>
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.

Conclusion

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 🍻

Resources

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .