Vite in a simple html+js use case

marcinwosinek

Marcin Wosinek

Posted on June 4, 2021

Vite in a simple html+js use case

In this series, I'll take a look on a simple usecase of js+html application, build with various js bundlers. This time, it's time for vite.

Vite

So vite itself is rather a development server/tooling than a js bundler. It's splitting completely the use cases of development server & production build. For example, in webpack you normally run a complete bundling process in dev server - maybe skipping some optimization, but besides that production build & development server are approached in a similar way. Vite in development compiles files separately & servers them unbundled. This saves us from waiting for the whole project to be rebuild after every change we do on the code side. The production build is done with rollup - the integration is seamless so from the point of view of the developer it could be done with any other bundler.

This series focus on a production build - therefore, it can be a bit unjust for vite, as it's ignoring the aspect that is main focus of this tool.

The app

application screenshot

same as other articles of this series, simple app with 1 component with template & data in separate files.

Code

The main html file, defines entry points of the application. Each value of <script src> or <link href> will be compiled by vite. It's similar approach to parcel.js, and a bit refreshing after having to specify entry points manually for so long in webpack.



<!-- index.html -->
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Contact App</title>
    <link rel="shortcut icon" href="#" />

    <script type="module" src="./src/index.js"></script>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body></body>
</html>


Enter fullscreen mode Exit fullscreen mode

After build, in the output folder (dist/index.html) we get:



<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Contact App</title>
    <link rel="shortcut icon" href="#" />



  <script type="module" crossorigin src="/assets/index.1d9c2da7.js"></script>
  <link rel="stylesheet" href="/assets/index.03175e43.css">
</head>
  <body></body>
</html>


Enter fullscreen mode Exit fullscreen mode

with each original import replaced by build assets.

Main js file:



// src/index.js
import "./contact-list/contact-list";


Enter fullscreen mode Exit fullscreen mode

no surprises here

The component

The component is broken down into 3 files - so code, template & data goes to best matching code type - JS, HTML & JSON.

Main component file:



// src/contact-list/contact-list.js
import template from "./contact-list.html?raw";
import contacts from "./data.json";

const contactList = document.createElement("div");

contactList.className = "contact-list";

contacts.forEach((entry) => {
  const element = document.createElement("div");
  element.className = "contact";

  element.innerHTML = template;

  element.querySelector(".name").innerHTML = entry.name;
  element.querySelector(".phone").innerHTML = entry.phone;

  contactList.appendChild(element);
});

document.body.appendChild(contactList);


Enter fullscreen mode Exit fullscreen mode

Let's take a closer look on import template from "./contact-list.html?raw". The ?raw makes vite import the value as string. It's similar approach to defining loaders inline in webpack, but here seems to be the only way to tell vite how to treat different files. Pretty unfortunate, if we expect migrating between different build tools.

The html file we import:



<!-- src/contact-list/contact-list.html -->
<h2 class="name">name</h2>

<p class="phone">phone</p>


Enter fullscreen mode Exit fullscreen mode

JSON files are understood by vite by default. We just define src/contact-list/data.json, the data file:



[
  {
    "name": "Christopher L Sanders",
    "phone": "769-232-1807"
  },
  {
    "name": "Frances J Nolte",
    "phone": "901-287-0419"
  }
]


Enter fullscreen mode Exit fullscreen mode

and the import works as expected - no config, no plugins & no ? magic words needed.

Build dependencies & configuration

For a successful build of the above code, we just need vite package. To install it, you can run:



$  npm install --save-dev vite


Enter fullscreen mode Exit fullscreen mode

For easy access to build script, you can add following line to package.json:


 js
  "scripts": {
    // other scripts
    "build": "vite build --base=./"
  }


Enter fullscreen mode Exit fullscreen mode

The --base=./ forces vite to use relative path for the browser side imports. Without it, your build code would work only on the top level of the domain. As long as you use the default entry file - index.html you don't need more configuration in our simple use case.

If all were set up correctly, the build will pass:



$ npm run build

> vite@1.0.0 build
> vite build

vite v2.3.6 building for production...
transforming...
✓ 6 modules transformed.
rendering chunks...
dist/index.html 0.34kb
dist/assets/index.03175e43.css 0.23kb / brotli: 0.14kb
dist/assets/index.1d9c2da7.js 0.44kb / brotli: 0.21kb

Enter fullscreen mode Exit fullscreen mode




Complete code & application example

If you want to see the application in action in the browser you can see it here:
https://marcin-wosinek.github.io/js-html-comparison-vite/dist/

and for the working code example you can go here:
https://github.com/marcin-wosinek/js-html-comparison-vite

💖 💪 🙅 🚩
marcinwosinek
Marcin Wosinek

Posted on June 4, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related