petite-vue revisited

One key Vue feature is the browser-only build. It doesn’t require any build step, so it allows experimenting with Vue without having to set up any special environment. petite-vue takes this approach and provides a library for “sprinkling” interactivity on otherwise server-rendered or static HTML.

petite-vue uses the same familiar template syntax as Vue, but with a reduced feature set getting it down to about 7 KB gzipped compared to Vue’s 33 KB.

The project is still in early development and should be considered experimental, it works really well though. If you are looking for something similar that is already out of alpha, you can take a look at Alpine.js.

How does petite-vue work?

petite-vue enables us to add interactivity without ever touching a JavaScript file. Adding the script with the init keyword automatically initializes petite-vue:

<script src="https://unpkg.com/petite-vue" defer init></script>

We then create “regions” with the v-scope keyword. This is also the place to define local state for this specific region:

<div v-scope="{ count: 0 }">
	{{ count }}
	<button @click="count++">Increment</button>

Check out this basic menu button example.

Ready for complex apps

You can also use petite-vue for more “conventional” Vue apps. In this case the HTML acts as a template which we then use in JavaScript as our mounting point:

<form id="search"></form>

In our JavaScript file we can define complex methods and also use imported code defined elsewhere in our application:

import { createApp } from 'https://unpkg.com/petite-vue?module'

	results: [],

	async getResults (search) {}

This Wikipedia search example demonstrates what’s possible with petite-vue.

Progressive enhancement

Take a look at the following HTML:

	<li v-for="item in items">{{ item }}</li>

Until JavaScript has loaded, it will look like this:

  • {{ item }}

Let’s call it a flash of un-compiled content. Since petite-vue is really small, the flash shouldn’t take too long. But for slow network speeds or when JavaScript fails to load altogether, the UX isn’t that great.

The solution to this problem is the v-cloak attribute:

<ul v-cloak>
	<li v-for="item in items">{{ item }}</li>

The v-cloak attribute will be removed when petite-vue is ready. Pairing this with a bit of CSS hides the flash:

[v-cloak] {
	display: none !important;