Vite 2, a DX jump into the future

Vite is a next-generation frontend tool. It generates optimized builds using the battle-tested bundler rollup. But during dev, bundling is avoided with files served on-demand over native ESM. It has Hot Module Replacement (HMR) that stays fast independently of your codebase size.

This post discusses why the instant feedback loop unlocked by Vite is so important and what is new in the next iteration of Vite, which is currently in beta. Be sure to check out the new Vite docs site, built with VitePress.

Frontend tooling is evolving

Vite's novel approach to web dev tooling, together with @web/dev-server and Snowpack, paved the way to a renaissance in dev tools exploration. Removing bundling during dev through JIT transpilations of files in a dedicated server allowed these projects to offer an incredible fast feedback loop while developing without losing the state of art optimizations like bundling and minification for production builds.

The release of WMR from the Preact team solidified this path and brought new ideas to the table. In particular, their universal plugin format based on rollup plugins let them and other devs share the same transform code in dev and build time. Vite 2 continues this exploration, incorporating what is proving to work well in Snowpack and WMR and taking the opportunity to apply what has been learned in the past months.

All of these tools are framework agnostic, you can use Vite to develop React with fast refresh for example. But, interestingly, the teams behind Vue, Preact, and Svelte are at the forefront of this new generation of dev tools. Vite is being developed by Evan You and the Vue community, WMR is an effort from the Preact ecosystem and the Svelte guild will surely get more involved in Snowpack dev now that they have chosen it for Svelte Kit. I think this marks an inflection point for UI frameworks, and we will see a lot of innovation in DX, SSR, and SSG in the future.

TIP

If you are new to this new breed of tools, Evan You's talk at VueToronto is a good place to start. There is also a Toolsday episode with Jason Miller about WMR and a The Web Platform episode with Fred K. Schott about Snowpack. Another great talk is Futuristic Web Development by Rich Harris, about why Svelte is also embracing this approach.

Powered by VitePress

This page is built using VitepPress, which now uses Vite 2. It is a great way to experience the developing flow that Vite unlocks. VitePress is a Vue-powered static site generator that is pushing the boundaries in both DX and performance. Because of the use of templates in Vue, static blocks can be detected to avoid hydration penalties. Dynamic Vue components can still be interleaved in markdown.

The post is converted into a vue component so the composition API can be used to add reactive state to your documents. Components can also be imported and used in the markdown. VitePress is still able to identify the static parts of the post and only include the minimal code needed to hydrate the dynamic blocks.

<script setup>
import FiltersPlayground from './FiltersPlayground.vue'
</script>

# CSS Filters Playground

Use the component in your markdown docs

<FiltersShowcase/>
Vue in Markdown, CSS Filters Playground

When you are playing with the sliders, you may arrive at a pleasant result by exploration. It is possible because you see the results of your changes instantly. If you need to wait even a few seconds when changing the values, it can't work. The same idea applies to Vite. It enables us to craft our apps or pages with a tight feedback loop. We see the result of our changes immediately, and it opens the door to workflows that were not possible before.

What is new in Vite 2

You can check the discussion that Evan started with the rationale for this next iteration. For a complete list of features check the Vite docs. It already supported most of the common dev flows out of the box, like JSX, Typescript, importing CSS and JSON, and also powerful features like importing wasm files and inline Web Workers. What follows is a list of the biggest changes and new features in the new release.

Vite docs

Vite has a new docs site built with VitePress. This is a great example of the dogfooding that is prevalent in the Vue ecosystem. In this case, previously with VuePress and now with Vite and VitePress, they can find issues and optimizations in vue core by pushing the envelope of what a SSG based in Vue can achieve.

The Features page is an excellent place to learn about Vite 2 out of the box features. If you are migrating from Vite v1, check the dedicated migration page. There is also a Config reference available. There is also a Comparisons page that is a good place to learn about the different tradeoffs that Vite is taking compared to other tools.

There is an official Awesome Vite List for community plugins, apps using Vite, and other interesting resources around the Vite ecosystem.

Framework agnostic core

All Vue related handling has been moved to a dedicated plugin, that plays by the same rules as the plugins for other frameworks like React, Preact, and Svelte. The react plugin is also part of the monorepo. The new monorepo organization of the repository showcases this move:

packages
  create-app
  playground
  plugin-legacy
  plugin-react-refresh
  plugin-vue-jsx
  plugin-vue
  vite

New universal plugin format

The new vite plugins format, inspired by the work of WMR, enables to share plugins code at dev and build time. From Vite's source docs:

Vite plugins support a subset of Rollup plugin API with a few extra vite-specific options. A valid vite plugin is also a valid Rollup plugin. On the contrary, a Rollup plugin may or may NOT be a valid vite universal plugin, since some Rollup features do not make sense in an unbundled dev server context. That said, as long as a rollup plugin doesn't have strong coupling between its bundle phase and output phase hooks then it should just work (that means, most of them). By default, the plugins are run during both serve and build. When a plugin is applied during serve, it will only run non output plugin hooks (see rollup type definition of Rollup Plugin Hooks). You can think of the dev server as only running const bundle = rollup.rollup() but never calling bundle.generate().

This new plugin format allows Vite to reuse a log of plugins from the rollup ecosystem and also share more code with WMR. I am maintaining a list of Vite compatible official rollup plugins at Vite Rollup Plugins.

Error overlay

Following other tools, Vite will now display an error overlay in the browser when there is a compiler error or failed resolve in the code. This feature can be disabled using hmr: { overlay: false } in vite.config.js

Lib mode

Vite now supports building libraries. Changes to the source code will be watched by Vite, so for browser-centric libs, you can have a great dev experience and optimized builds. The following config defaults to building the library in both 'es' and 'umd' format. 'cjs' and 'iife' can be added using formats.

vite.config.js

const path = require('path')

module.exports = {
  build: {
    lib: {
      entry: path.resolve(__dirname, 'src/main.js'),
      name: 'LibName'
    }
  }
}

Multi entry mode

There can now be multiple entry points, and Vite will perform auto code splitting for JS and CSS when building them.

vite.config.js

const { resolve } = require('path')

module.exports = {
  build: {
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        nested: resolve(__dirname, 'nested/index.html')
      }
    }
  }
}

Strong caching of npm deps

When importing npm dependencies, they will now be using disk or memory cache after the first load. The cache will auto invalidates if you upgrade the dependency to a newer version, but the imports will not even hit the dev server once they are cached by the browser.

Other highlights

There are a lot of other important improvements in the new version. These are some of the enhancements that are not expanded in this post:

  • Middleware mode, allowing Vite to run as part of existing express compatible servers
  • Default to modern only, Opt-in to legacy mode
  • Revised config format
  • Smaller and faster install
  • Improved JS API
  • HMR API alignment with other tools
  • Improved alias and resolving
  • Better vue perf (single request in most cases)
  • Support native esm config files
  • Auto restart server on config and .env changes
  • Support for Vue JSX with HMR
  • Support using variables in dynamic imports, like await import(`./views/${view}.js`)

Feeling the speed

As Evan You has said, you need to try it out to get a feeling of the raw speed that Vite is capable of. To scaffold a new vite App you can use

yarn create @vitejs/app

You will be prompted to choose a project name and a template

√ Project name: · next-gen-app
Scaffolding project in path/next-gen-app...
? Select a template: ...
> vanilla
  vue
  vue-ts
  react
  react-ts
  preact
  preact-ts

Once the app is created, start the dev server with

cd next-gen-app
yarn
yarn dev

Modify the files with the browser open to see your modifications be reflected instantly. A nice way to test how fast Vite updates the app is to toggle auto save, and then play with CSS or modify the files. It should feel like you are directly using the browser dev tools (in VS Code, you can enable it using Cmd+Shift+P then type "Auto Save" and fire the File: Toggle Auto Save action).

If you would like to see how it works for a real application, at Leniolabs_ we have been using Vite to craft Layoutit Grid and we recently migrated it to Vite 2 as part of the work we are doing for grid v2. You can clone the repo and play with the dev server.

An immediate connection

There will continue to be a lot of healthy cross-pollination between the Vite, Snowpack, and WMR. These tools are paving the way for a future where we can get back to have that lost magical experience of an instant feedback loop between our code changes and our pages. Like Bret Victor said in his marvelous talk Inventing on Principle, creators need an immediate connection to what they are creating.

A good example of this principle in practice was the release of tixy.land by Martin Kleppe, a minimalist creative coding environment. When you change the function, you see the visual creation instantly. Interesting results can be found by playing and tinkering with the variables. Tons of examples were shared, and it inspired similar experiments like Polar by Anthony Fu. Apart from showcasing the importance of the immediate connection between the code and the result, Polar was developed and built with Vite. Rahul Kadyan is using Vite to implement VueDX Preview, a real-time preview for Vue 3 components in Visual Studio that gets us closer to the creative environments that Bret Victor was advocating for.

Vite is well-positioned to keep pushing the boundaries of web dev tooling. It is hard to explain how much of a leap forward in DX these tools bring to the table. If you haven't tried it yet, give it a spin, it'll be worth it.




Other posts

Ignorable Watch
VueUse's ignorableWatch, useRefHistory and watch flush modes

History and Persistence
useRefHistory and useLocalStorage as building blocks to create new composables

Mark Raw Optimization
Using markRaw to optimize VueUse's useRefHistory composable