#3 [Stackless] JavaScript's hidden package manager
Hi reader!
This is issue #3 of The Stackless Newsletter.
Praise for packages. Last week, I wrote, “In a world without packages, there would be no easy way to include other people’s code in our projects.” I explained that Node and NPM are “aftermarket products” added to server-side JavaScript to make it possible to use modules of other people’s code. With build tools like Webpack or Rollup, developers use Node and NPM to create bundled JavaScript files for browser JavaScript.
The “hidden” JavaScript package manager. It turns out that build tools are no longer needed for browser JavaScript. It’s not widely recognized, but ES6 JavaScript imports, available in all major browsers since last year, can do everything needed for JavaScript package management. Let’s look at how to use ES6 JavaScript imports. It makes JavaScript development much easier.
Weird and wonderful imports in JavaScript. Developers with experience in other programming languages scratch their heads when they see the JavaScript import statement. For example, in Ruby, we can require 'money'
and then use any method from a library’s public API, like Money.parse("£100")
. That’s because languages like Java, Python, and Ruby make all methods “public” by default. JavaScript does not support “public” and “private” functions. Instead, the creator of a module must explicitly designate a function for export
to make it available for use. That leads to a more complicated import statement. We could say the JavaScript community aims for a “stricter, more encapsulated module system.”
Import statements. Each import statement has five parts:
- the
import
keyword - curly braces containing a list of functions exported from a module
- an optional
as
for renaming a function - a
from
keyword - a source for the module
One fine example. Here’s an example that’s useful for stackless web development; in this case, a custom HTML tag. The Polymer Project’s lit-html package contains an html
function that makes it possible to write HTML that contains JavaScript expressions. Lit-html is a fast, efficient templating language for JavaScript.
import { html } from 'https://jspm.dev/lit-html';
Unlike Ruby, which needs only a require
keyword and a module name, the JavaScript import statement identifies the function we want to use and specifies its source. With Ruby or Node, we use a separate tool to install the package into our local development environment. With browser JavaScript, the “hidden package manager” loads the module from a URL when the browser encounters the import statement. That’s almost all that is needed.
Is it really a package manager? Package managers do three things: downloading, file management, and dependency management. In our example, the browser does two of these things. It downloads the module from a repository and installs it in the browser’s cache. But it doesn’t manage dependencies without some help. If we know a module’s behavior has changed between versions we will want “version pinning.” To get that, we can specify a version in the URL, like this:
import { html } from 'https://jspm.dev/lit-html@1.3.0';
It depends. It’s not ideal to specify both a module source and version in every import statement. For a small project, it’s manageable with search and replace if you need to make changes. It’s better to use a “bare specifier” for any module, like this:
import { html } from 'lit-html';
With build tools like Webpack and Rollup, you can use bare specifiers and the tool adds specificity during a build process, reading version information from a lockfile. Of course, that takes time (it’s an extra compilation step) and it’s annoying to install and configure the extra build tools. For dependency management, you can now use bare specifiers in Chrome 89 (released March 2, 2021) using a feature named import maps. The new feature acts like a lockfile, allowing you to specify a source and version for each module plus all dependencies. I’ll show how to use import maps in an upcoming issue.
Please hit reply to let me know if this issue was useful. I want to hear from you!
Best wishes from Bali,
Daniel
Web links of the week
JavaScript Import Explained The Mozilla MDN Web Docs are the best source of “what” and “how” for JavaScript modules and JavaScript import, though they don’t explain the “why” of module design. So I wrote JavaScript Import Explained to give you the “why.”
Cloudflare Pages Free hosting for static sites, deployed from GitHub, now in public beta. I’ll be looking more closely at this alternative to Netlify or Vercel in coming weeks.
Worklog: February 2021 I publish a monthly summary and daily worklog about my Yax.com project. It’s a candid, behind-the-scenes look at what I’m doing.