I hope to see this direction take hold, as I just started teaching a few basic Vue exercises, but with a cdn link. The npm route is too convoluted for media students and doesn’t work well with our shared hosting options.
I’m hopeful that more people will start publushing on https://jsr.io and that it adds support for searching by platform. (It has platform icons, which is a start.)
Have you ever heard about importmap? Rails was pushing the #NOBUILD tag during its lastest release. This video explains importmap outside Rails and how Rails integrates it on the framework: https://youtu.be/nwyLgb7UumU?si=ClxwTO-04k01WYN5
The pain I felt some years ago was exactly this. But believe it or not, there is another beautiful world of no build I've just entered recently https://github.com/rails/importmap-rails
I've been doing this for a living since 1999, when did devs start patting themselves on the back for introducing concepts to JS associated with compiled PLs and did this have anything to do with asking for bigger salaries
My big open question is how to deal with deploys and bowser caching of js. My latest project is vue without build tooling but I haven’t found a reliable way to break browser cache
I really like the pattern where you bake the truncated SHA256 hash of the file contents into the filename itself, then when you ship a new version caches bust automatically because the filename changes
importmaps should theoretically make that pattern a whole lot easier to use
one question I have is whether the ES module "import" spec has support for bundled JS files in any way and if not, why not?
import maps are useful but I feel like having to download dozens of files is kind of rough, was the idea that HTTP/2 server push was going to save us from that?
Not today. There’s a Module Declarations proposal that would add “syntax for named, inline JS modules, which can be used for bundling multiple modules into a single JavaScript file.” https://github.com/tc39/proposal-module-declarations
It’s currently stage 2 and was a major topic among bundler authors in TC39 tooling calls in the first half of 2023 when I was attending on behalf of ESLint, but I haven’t joined since then, so I don’t know if there are recent updates.
37signals is doing well on using importmap on their systems. They have real evidence that it works in practice. I'm also using them on a project and I'm very happy, but it isn't in production yet.
I _think_ H2 server push was supposed to help, but that spec died as far as I know.
Loosely put, ESM has a split between syntax + _some_ defined behavior, and the rest being implementation-defined. That's how we ended up with browser ESM support quickly, and Node taking years.
As a lib maintainer (Redux), I can vouch that _publishing_ packages is an incredibly hard problem space as well. I wrote a long post last year about frustrations getting better ESM+CJS compat:
Trying to consistently consume an ESM file from an arbitrary package is hard _because_ there's so much variation in how packages are published (included artifacts and definitions).
For RTK 2.0 I did drop UMD files and switched to a pre-bundled ESM module for browser use.
how about a cdn that transpiles packages to a single package type and format? e.g., no matter what you upload it gets converted into the universal standard format easily consumed.
I think https://esm.sh is supposed to be that mostly already. However, I don't know how it's implemented, and I can foresee a lot of potential incompat issues.
I genuinely don't know how it wraps or transpiles CJS-only packages like React atm.
unrelatedly it's been hard for me to accept that to understand why this problem is so hard, I actually do need to learn some things about the Node ecosystem's history
(my natural inclination is to think "well I'm writing code for the BROWSER why should I have to think about NODE?")
- No module spec for JS like other langs
- Community invented:
- AMD: waterfall async browser loading
- CJS: sync Node loading
- NPM included with Node as default package manager, then got used for client packages with bundlers running in Node
- ES spec defined ESM syntax
today JS is consumed and used in a myriad of runtimes and environments, all with different requirements and constraints.
So, unlike other langs that had built-in concepts of packages from day 1, for JS it's been a mish-mash of different formats and wildly evolving toolchains.
Yeah I've got caught by that too! Took me a long time to accept that node_modules/ in a folder structure was actually nothing to do with Node, it was a weird artifact of npm history
Right, but when you use npm install to get a client-side JavaScript library you can end up serving that from your public server from the node_modules/ directory without any involvement of Node at all
It's absurd but I still struggle understanding ES modules.
I have a monorepo project somewhere that has every imaginable combination of package.json and tsconfig module compiler option because random dependencies don't work with something or other.
Now try doing it for a jupyter extension that you want to work in semi-jupyter environments like VSCode notebooks and Google colab. I’m punting and porting to anywidget, which solves it with sucrase, a js-in-js bundler that runs on every import.
Javascript feels like it's the pile of wires in a box in my garage that I'll never throw away. Every time I come back to it when I need a random HDMI cable, there are more cables, it's more tangled up than the last time I saw it, and it takes longer to do what used to be quick and easy.
The related problem of publishing an NPM is equally maddening. People complain about Python’s obscure packaging story, it is _nothing_ compared to NPM.
I’m truly hoping that https://jsr.io takes off as a new default to use over npm since they allow you to distribute for everyone without knowing the complexities of tsconfig and packaging yourself
I had a small taste of this for the first time earlier this year building a GNOME extension where libraries must be vendored in—what an annoying problem. Thankfully I was using a single, simple library and it was easy enough to manually edit, but the whole ESM/CommonJS split is awfully messy.
hi https://esm.sh maintainer here. what if i compile https://esm.sh to a CLI that builds esm on your computer, let's say `npx https://esm.sh build react react-dom --dir=vendor`, then you can use the modules via `import * from "./vendor/react.mjs"`, with importmap you can use `import * from "react"`
+1 for https://esm.sh by @jex.me. You can bundle, override individual dependency versions, alias dependencies, and a bunch of other stuff by just using the URL params. Super convenient. But 100% agree that the JS ecosystem is a mess in this regard.
This feels like a backend problem to me. I don't write frontend bits day to day, but why wouldn't a server process handle the complexity of managing packages and serve the rendered text/javascript based on a simple request pattern? The frontend stays "native."
There are a bunch of solution that do that, but I don't want them. I want to be able to write and serve moderately complex JavaScript applications that are just static HTML and JavaScript on static hosting - that way I know they'll continue working forever
Comments
importmaps should theoretically make that pattern a whole lot easier to use
import maps are useful but I feel like having to download dozens of files is kind of rough, was the idea that HTTP/2 server push was going to save us from that?
Loosely put, ESM has a split between syntax + _some_ defined behavior, and the rest being implementation-defined. That's how we ended up with browser ESM support quickly, and Node taking years.
https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/
Trying to consistently consume an ESM file from an arbitrary package is hard _because_ there's so much variation in how packages are published (included artifacts and definitions).
For RTK 2.0 I did drop UMD files and switched to a pre-bundled ESM module for browser use.
I genuinely don't know how it wraps or transpiles CJS-only packages like React atm.
If a package has 100s of tiny dependencies I'd definitely prefer to build that into a single dependency though!
That’s pretty much guaranteed.
You can check https://packagephobia.com first before you npm install.
(my natural inclination is to think "well I'm writing code for the BROWSER why should I have to think about NODE?")
- No module spec for JS like other langs
- Community invented:
- AMD: waterfall async browser loading
- CJS: sync Node loading
- NPM included with Node as default package manager, then got used for client packages with bundlers running in Node
- ES spec defined ESM syntax
So, unlike other langs that had built-in concepts of packages from day 1, for JS it's been a mish-mash of different formats and wildly evolving toolchains.
It reads from this directory when resolving import/require statements.
https://nodejs.org/api/esm.html#resolution-and-loading-algorithm
https://observablehq.com/@observablehq/module-require-debugger
I have a monorepo project somewhere that has every imaginable combination of package.json and tsconfig module compiler option because random dependencies don't work with something or other.
I don't even understand why we have options
@stevekrouse.com wonder if this would speed up Val execution with specific exports?