Adventures building Open Source software

Javascript, ESM, and tools

I’m using Javascript, Typescript, and Node a lot these days as part of my work at Shopify and Gestalt and I’m really loving it. In particular, its module system because it allows extensibility in ways it’d be more challenging with compiled languages or interpreted languages like Ruby that have a shared namespace where the code is loaded into. Vite is an excellent example.

It hints that there might be a future where additional tooling and the indirection that comes with it its not necessary, but if you dig into that idea a bit, you realize it’ll never be possible. At least in the years to come. Tooling will remain necessary to polyfill the code to adapt it to various runtimes (e.g Deno). It’ll also be needed for UI frameworks that have built their template solutions upon Javascript (e.g JSX), remove type annotations from Typescript code, and accommodate NPM packages that don’t comply with CommonJS conventions to ensure interoperability with ESM.

This is not unique to the Javascript ecosystem. Compilers also transform and optimize code into binary to be able to run it in the target platform. When building for Apple platforms, there’s an artifact akin to sourcemaps, dSYMs, to be able to link stacktraces with the source code. The difference is that other ecosystems make it a core element of the programming language and that allows a more integrated experience. Achieving a similar level of cohesiveness in the Javascript world feels like juggling. You can integrate various tools under a framework to achieve a well-integrated experience, but you end up with a brittle setup that falls apart easily. This explains the well-known “delete nodemodules”_ and install dependencies again in the hope that the package manager will restore the state.

Despite how much I’d love to see a broader adoption of ES modules in the NPM ecosystem, and more conventions and standards pushed down to the Javascript foundation, I’ll doubt that’ll happen in the near future, and this influences how we build GestaltWe’ll do what’s in our hands to minimize tooling indirection manifesting as bugs or breaking project setups. Rails is better positioned there thanks to the Ruby, but we can leverage some Javascript capabilities to approximate the Rails experience. For example, we can provide a foundational set of utilities that are automatically polyfilled by the framework depending on the deployment targets. This is something can’t be done easily if frameworks encourage projects to import Node APIs directly.

Instead of dreaming with a future where tools are not necessary, we are embracing tooling and leveraging it to provide Gestalt users with a reliable and integrated developer experience. I think Gestalt will blow your mind like not many frameworks have been able to do.