Written by

So, you’re involved in Web Dev Frontend. We reck­on you’ve prob­a­bly got­ten mad over the last few years, as well as fac­ing JavaScript Fatigue phe­nom­e­non because of the rapid­ly grow­ing fron­tend ecosystem.

If so, then hang on the edge of your seat: in terms of fron­tend devel­op­ment the future is already here, and it’s shiny 🤩!

In the Early Ages Came JavaScript…

… and then every­thing went faster and faster. With the arrival of Node.js, JS has become the new game-chang­er. Being able to run JavaScript on both back­end and fron­tend sides meant being able to devel­op many new tools, new (small) libraries and new envi­ron­ments. Supported by the NPM Registry, it rapid­ly grew and is now the de fac­to lan­guage for any fron­tend dev tools, as well as for dis­trib­ut­ing dependencies.

Then came the reac­tive fron­tend frame­works, like React, Vue.js, or Svelte. With their bril­liant pat­terns and sep­a­ra­tion of con­cerns, they con­sti­tute the fastest UI libraries avail­able to devel­op com­plex inter­faces in the browser.

Finally, the PWA Era. We now devel­op Web apps using Web tech­nolo­gies, but not nec­es­sar­i­ly relat­ed to Web sites. They are apps, like any oth­er. Installable, they run in chrome­less browsers like Electron or WebViews, and are indis­tin­guish­able from native examples.

So now it’s 2020, and we’re think­ing out­side the brows­er: JavaScript runs any­where, we devel­op apps using web tech­nolo­gies, and we apply the same pat­terns as in native devel­op­ments. All with the same caveats: as the JS ecosys­tem grew, the depen­den­cies in our apps grew as well. We’re now com­pil­ing for the Web. Like in native developments.

But there’s a small, but sig­nif­i­cant, dif­fer­ence: we stream our apps. When you serve a PWA, you still rely on web prin­ci­ples. Your serv­er sends an HTML page that requests its assets (images, JS bun­dled chunks, fonts, CSS, and so on). We serve tons of Gb each day to our users’ browsers, and it’s time to stop that flow!

The Original Sin: the Packing

During the first days of the Web apps we had a new pat­tern to dis­trib­ute chunks of JavaScript across projects as small libs: CommonJS. It was so use­ful it became the stan­dard for dis­trib­ut­ing mod­ules in the Node.js envi­ron­ment. The main prob­lem was the inabil­i­ty of our brows­er VM to under­stand and exploit this format.

So we start­ed to devel­op load­ers, capa­ble of load­ing and inject­ing CommonJS mod­ules inside our main views source code. But this rapid­ly led to anoth­er flaw: we start­ed to serve too many depen­den­cies to the brows­er, bloat­ing the connection.

So we cre­at­ed bundlers, like Webpack. They were in charge of col­lect­ing all your app depen­den­cies and mod­ules and out­putting a sin­gle JS file your brows­er would be able to run. These quick­ly became pack­ers, allow­ing you to apply changes and opti­miza­tions to your builds, and add mech­a­nisms to import way more than just JS depen­den­cies, includ­ing all oth­er asset types!

Then we added pre-proces­sors and tran­spilers, to write from new lan­guages to JavaScript (like CoffeeScript, or TypeScript) fol­lowed by new tools for fur­ther opti­miza­tions, split­ting assets into small­er chunks and serv­ing them only when request­ed. Because per­for­mance mat­ters a lot…

Our dev stack is now more com­pli­cat­ed than it has ever been. We’re in an end­less race to add new tools that allow us to deal with the per­for­mance buck­et. We did this because we need­ed tools, but our tool­chain is now a hor­ri­ble bloat­ed process, which is extreme­ly com­plex to under­stand and one that takes an eter­ni­ty to start and com­pile each time you run a project or save a file.

Is this sit­u­a­tion even still legitimate?

Welcome to 2020: the Zero Build Pipeline

So, let’s go through the list. What do we have nowa­days in our toolbox?

  1. Native ES6 Modules: so long to the CommonJS for­mat, but its descen­dant, the ES6 Module, is way more effi­cient. It’s sup­port­ed native­ly by both Node.js and browsers. No rea­sons to avoid it anymore.
  2. Pre-built libs: TypeScript is in the course now 1), and we’ve got a lot of new libraries that are devel­oped with it. Even when built with VanillaJS, these mod­ules can be opti­mized out­side of our tool­chain and dis­trib­uted as is. No need to han­dle this on our project.
  3. A large ecosys­tem: NPM is one of the largest and most used depen­den­cy reg­istries. The entire JavaScript/TypeScript uni­verse is full of great tools, use­ful libs, and pret­ty helpers, ready to be used with­out the need to embed them.
  4. HTTP/2: Version 2 of the pro­to­col is wide­ly avail­able and sup­port­ed, and it shrinks a high num­ber of requests. Indeed, it’s prob­a­bly more effi­cient to serve a bunch of small files with HTTP/2 rather than a big bun­dled one, thanks to its opti­miza­tions. And it will improve caching policies.
  5. All our tools, from Unix to fron­tend ded­i­cat­ed util­i­ties, offer a CLI, which allows the build­ing of advanced pipelines.

So, this tool­box is rich in pos­si­bil­i­ties. It gen­uine­ly leads us to the Bare Modules Devtools. Here are the sim­ple ideas behind the concept:

  1. We use mod­ules as they are dis­trib­uted, in their ES6 Module for­mat, with­out pack­ing or bundling them anymore,
  2. We rely on HTTP/2 to serve assets effi­cient­ly to keep a high-per­for­mance rate,
  3. We keep to 0ms to start dev envi­ron­ment, by only serv­ing raw files and mod­ules and not mod­i­fy­ing them in a devel­op­ment context,
  4. We pre/­post-process our source files using CLI direct­ly (or with native tool capa­bil­i­ties) to avoid build­ing com­plex new toolchains.

Snowpack v2 just released in an ear­ly stage on May 5, and it’s exact­ly what we need­ed to imple­ment our con­cept! This new tool is both a dev tool, allow­ing you to run your apps in dev mode with no start­up time, no bundling and fast updates, and a build tool where you can define and pipe tools to pre­pare your assets for pro­duc­tion if needed.

You Know Nothing

Start by installing Snowpack as a dev depen­den­cy for your project:


And that’s all! It’s now ready to han­dle your devel­op­ment process.

Devtools

Snowpack will parse your project, look­ing for import state­ments, and then copy from the project’s node_modules direc­to­ry, or install them direct­ly, to a web_modules directory.

From here, you can serve your web mod­ule assets and import them into your page:


Your scripts need to be declared in the HTML with the type=module attribute to enable the ES6 Module mode. And your assets are import­ed from the web_modules directory.

Simply run snow­pack install from your project direc­to­ry, and see how your web_modules is pop­u­lat­ed with your depen­den­cies. You can also man­age them from your package.json file and with the snow­pack con­fig entries.

In devel­op­ment mode, this con­fig­u­ra­tion allows you to declare use­ful fea­tures, like mount direc­tives. They act like mount­able points, allow­ing you to serve all your want­ed assets from the built-in devel­op­ment server:


Then sim­ply run snow­pack dev to get a full devel­op­ment serv­er up and run­ning, serv­ing your assets, and refresh­ing at sav­ing. With the snowpack dev com­mand, there’s no need to update the paths your­self: sim­ply rely on the com­mon import * as React from 'react' in your JS files, and Snowpack will con­vert the import path for you.

During the build phase, Snowpack sim­ply copies your assets in a sta­t­ic for­mat, allow­ing you to deploy them any way you want. It also adds a --bundle flag, allow­ing you to pass your source files to Parcel and opti­mize your pro­duc­tion build using the exist­ing toolchains.

You can also define your own snow­pack scripts, to cus­tomize your build pipelines, like:


The old mod­el doesn’t work any­more. Thanks to our new and pow­er­ful tech­nolo­gies, we don’t need to pack and bun­dle our apps with their depen­den­cies. Instead, we can focus on devel­op­ment rather than tooling.

This approach presents a good phi­los­o­phy: it relies on exist­ing tools to keep to a cross-com­pat­i­ble effort (like work­ing with Parcel, Rollup, Babel… under the hood), it has zero lock-ins and you can fall back to any oth­er build tool when you need, and it’s fast to dev and run.

Snowpack is the first con­tender in this new uni­verse, with many cool fea­tures includ­ing import-maps, prox­y­ing requests, HMR, etc. No doubt we will see oth­er alter­na­tives quick­ly 2), and it’s a good time to jump in the train of the Bare Modules Development!

Notes

Did you know that you can run TypeScript on always­da­ta servers direct­ly thanks to Deno?
Vue.js has already start­ed to work on their own tool for Vue.js: Vite.