Snowpack 3 in a simple html+js use case
Tags: javascript, webdev
Published: 2021-06-05 15:11:44

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 [snowpack](https://www.snowpack.dev/).

# Snowpack

Similar to vite, it focuses on improving development experience by avoiding bundling. Snowpack takes this concept slightly further, and by default its production output is unbundled as well. For bundling we have few options build in, experimental bundling with esbuild, recommended webpack plugin or rollup plugin.

In this series, we focus on production build & on having as little configuration as needed for the use case - very likely I'm overlooking main benefits of development server & build tool flexibility.

# The app

![application screenshot](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xacwuk055mv5c4cdot9z.png)

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

# Code

Snowpack has interesting approach to picking files to be build. Instead of having configuration files for setting entrypoints or parsing html to see what was references as other bulders, it's just build all files it's finding in our codebase. It keeps the relative paths in the build output folder as well - so we just need to make sure our html is referencing right files on the source side, and it should work in the build output as well.

The main html:
```html
<!-- 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>
```

it's copied as it is to the default output folder `./build/`.


Main js file:

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

# The component

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

```js
// src/contact-list/contact-list.js
import template from "./contact-list.htm";
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);
```

similar to vite, here we had to do a small tweak to our template file. If we configure raw/string loader for all HTML files, it will break our top level `index.html`. As snowpack plugins seems allow for loader configuration only by the extensions, the best approach seems to be just change the templates from `.html` to something else - here I picked `.htm`.

The template file we import:
```html
<!-- src/contact-list/contact-list.htm -->
<h2 class="name">name</h2>

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

JSON files are understood by snowpack by default. We just define `src/contact-list/data.json`, the data file:
```json 
[
  {
    "name": "Christopher L Sanders",
    "phone": "769-232-1807"
  },
  {
    "name": "Frances J Nolte",
    "phone": "901-287-0419"
  }
]
```

# Build dependencies & configuration

For building, we will have default configuration + 1 plugin. The installations needed are:

```bash
$ npm install --save-dev snowpack snowpack-plugin-raw
```

For easy access to build script, you can add following line to `package.json`:
``` js
  "scripts": {
    // other scripts
    "build": "snowpack build"
  }
```

The configuration, in the `snowpack.config.json` files:
```json
{
  "plugins": [["snowpack-plugin-raw", { "extensions": [".htm"] }]]
}
```

The the output of a sucessful build:
```bash
$ npm run build

> snowpack@1.0.0 build
> snowpack build

[18:08:13] [snowpack] ! building files...
[18:08:13] [snowpack] ✔ files built. [0.03s]
[18:08:13] [snowpack] ! building dependencies...
[18:08:13] [snowpack] ✔ dependencies built. [0.00s]
[18:08:13] [snowpack] ! writing to disk...
[18:08:13] [snowpack] ✔ write complete. [0.01s]
[18:08:13] [snowpack] ▶ Build Complete!
```

# 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-snowpack-3/build/

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