[HN Gopher] Move on to ESM-Only
       ___________________________________________________________________
        
       Move on to ESM-Only
        
       Author : bpierre
       Score  : 102 points
       Date   : 2025-03-24 00:35 UTC (22 hours ago)
        
 (HTM) web link (antfu.me)
 (TXT) w3m dump (antfu.me)
        
       | airstrike wrote:
       | _> The Toolings are Ready_
       | 
       |  _> Modern Tools_
       | 
       |  _> With the rise of Vite as a popular modern frontend build
       | tool, many meta-frameworks like Nuxt, SvelteKit, Astro,
       | SolidStart, Remix, Storybook, Redwood, and many others are all
       | built on top of Vite nowadays, that treating ESM as a first-class
       | citizen._
       | 
       |  _> As a complement, we have also testing library Vitest, which
       | was designed for ESM from the day one with powerful module
       | mocking capability and efficient fine-grain caching support._
       | 
       |  _> CLI tools like tsx and jiti offer a seamless experience for
       | running TypeScript and ESM code without requiring additional
       | configuration. This simplifies the development process and
       | reduces the overhead associated with setting up a project to use
       | ESM._
       | 
       |  _> Other tools, for example, ESLint, in the recent v9.0,
       | introduced a new flat config system that enables native ESM
       | support with eslint.config.mjs, even in CJS projects._
       | 
       | I think the author and I must have very different definitions for
       | the word "ready"
        
         | vosper wrote:
         | How would you define "ready" here?
        
           | airstrike wrote:
           | Definitely "stable", but also "simple" and "straightforward"
        
             | thiht wrote:
             | So you need a bundler, a linter and a test runner. How's
             | that any different from the experience in other languages
             | where you need a compiler, a linter and a test runner?
        
               | airstrike wrote:
               | s/a/one
        
       | paulddraper wrote:
       | In my experience, the biggest obstacle to ESM in production
       | systems is every observability/tracing tool relies on require-in-
       | the-middle or in some other form CJS require().
        
         | o11c wrote:
         | Even "require at the start" (mandatory for transparent
         | polyfills) seems incompatible with the way ESM wants to do
         | things.
        
       | jauntywundrkind wrote:
       | They key thing is that require(esm) shipped in node 22, and is
       | being back ported to node 20.
       | 
       | Since Node 18 maintenance ends in less than a month, this means
       | all Node versions will have good esm support, including for
       | consuming esm-only libraries (which until recently did not work!)
       | 
       | This is noted somewhat in the article, but basically is the whole
       | story to me. Its now _possible_ to stop doing CJS libraries
       | entirely. And with that, I don 't see why we would do CJS at all.
        
         | 3np wrote:
         | There are still maintained and supported older versions of
         | node.js by the likes of Debian, Ubuntu, Enterprise Linuxes.
         | They backport security fixes and such during a longer extended
         | window but are unlikely to port ESM-require support. It may not
         | be relevant to you and obv nobody's obliging you to also
         | support those users, just saying it's not that binary.
        
           | mattmanser wrote:
           | Is that really "support those users"?
           | 
           | If they need to use a new library version, they can install
           | their own version of node instead of relying on the OS
           | supplied one.
           | 
           | All the OS version is doing is supplying the convenience of
           | not having to install it.
           | 
           | Or have I misunderstood how those versions of node are used?
        
             | 3np wrote:
             | Sometimes the entire reason why they are still on that
             | older LTS dist is because they still _need_ (e.g.) node 12
             | for some reason.
        
               | mattmanser wrote:
               | That really becomes a "not your problem" as a library
               | author.
               | 
               | If a user wants to use an old version of node, they'll
               | have to use an old version of the library that still
               | supports cjs.
        
           | rafaelmn wrote:
           | If you are pinning to unsupported node you should not expect
           | new npm packages to work, ESM or not.
           | 
           | However given my NPM experiences in the past, I would not be
           | surprised that someone updated to ESM in a revision bump.
        
         | forty wrote:
         | Funnily my conclusion was, on the contrary, that it's now
         | possible to ignore ESM entirely when using/targeting nodejs ;)
        
           | forty wrote:
           | (sadly at work, at this point we already have done the
           | useless work of migrateming to ESM for no good reason other
           | than having libs that were ESM only)
        
             | 9dev wrote:
             | ESM has heaps of benefits: being able to do static
             | analysis, or limiting the exposed modules in a package, for
             | example.
        
               | j-krieger wrote:
               | Tree-shaking also.
        
               | jampekka wrote:
               | Static analysis and tree shaking have been done with CJS
               | for about a decade.
               | 
               | https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76a
               | f7d...
        
               | wffurr wrote:
               | In a limited way due to side effects from the require
               | function.
               | 
               | Reading that rant, the author did not seem to take much
               | time to understand the rationale behind ES modules: " yet
               | for some completely unclear reason, ESM proponents
               | decided to remove that property" is just pure ignorance.
        
               | jampekka wrote:
               | > In a limited way due to side effects from the require
               | function.
               | 
               | In a limited way that covers something like 99.9% of CJS
               | usage. Bundling is based on static analysis.
               | 
               | If by side effects you mean running code, not just
               | declaring exports, ES6 import does these side effects
               | too.
               | 
               | Thinking that CJS can't be used for static analysis or
               | tree-shaking is the widest spread pure ignorance.
        
               | 9dev wrote:
               | The main argument in that post doesn't even hold; using
               | ESM, you can always using dynamic imports:
               | await import( someExpression )
               | 
               | Besides, static analysis _and_ tree shaking completely
               | break down if modules impose side effects from being
               | required, which is one of the main gripes of Python as
               | well. ESM _completely_ alleviates that.
        
               | jampekka wrote:
               | That forces dynamic imports (and is horrible ergonomics
               | as discussed in the post). CJS requires can be statically
               | analyzed to figure out whether a require can be static,
               | as is done e.g. in all bundlers.
               | 
               | ESM import runs side effects as well.
        
               | 9dev wrote:
               | We have had top-level await for a while now. I don't know
               | what's so horrible about this:                 const app
               | = express()       app.use("/users", await
               | import("./routers/users"))
               | 
               | ...if you're so inclined to do things _exactly_ as you
               | did in the past. I'm pretty sure bundlers will even
               | transform that into an ordinary module import.
               | 
               | The cases where you actually need dynamic imports are few
               | and far between. Are we actually talking about engine
               | limitations here, or is it just a few snowflakes that
               | insist on creating loggers like this?
               | require("debug")("acme")
               | 
               | What is so particularly pretty about that is beyond me.
               | 
               | > ESM import runs side effects as well.
               | 
               | At runtime, yes. Not during static analysis.
        
               | forty wrote:
               | I'm doing server code (which I guess is the main use case
               | for nodejs), I just COPY the project folder in the docker
               | and ship that. No need for bundling, shaking and other
               | annoyance.
        
               | 9dev wrote:
               | You'd likely still benefit from using TypeScript and
               | transpiling that to plain JavaScript (preventing _a lot_
               | of subtle bugs), and tree shaking to minimize your Docker
               | image size (yielding faster deployments).
        
               | WorldMaker wrote:
               | Tree-shaking also happens in GC heap space (both in the
               | server and in the browser): V8 and SpiderMonkey and
               | JavaScriptCore will all _eventually_ treeshake unused
               | code out of memory entirely. The ESM format was designed
               | to allow that. Modules actually only reference each other
               | through weak references and things like import * build
               | proxy objects of weak references designed for tree-
               | shaking.
               | 
               | Depending on how your application is structured, an ESM
               | version of a server-only Node application may _still_
               | benefit from the performance optimizations of the server
               | being able to do dead code elimination at runtime.
        
               | nailer wrote:
               | Also not having to debug two separate shipped codebases.
               | "The CommonJS version does X" is an annoying github issue
               | to fix.
        
         | moltar wrote:
         | Annoyingly you have to use an experimental flag. That just adds
         | too much friction.
         | 
         | Latest Node version added Node options as config feature. I
         | wish that was ported to every version of Node.
         | 
         | Otherwise you have to set NODE_OPTIONS which can often be
         | overwritten by some scripts in the execution chain.
        
           | uasi wrote:
           | require(esm) is no longer behind a flag in v22.12.0+ and
           | v20.19.0+.
        
       | Klaster_1 wrote:
       | On a side note, I recently experimented with native TS support in
       | Node.js and it felt like magic: no need for extra flags;
       | debugging and watch just work; types are simple to re-use between
       | browser and server. Erasable syntax seems like the way forward,
       | can't wait for it to land in browsers.
        
         | normie3000 wrote:
         | > can't wait for it to land in browsers
         | 
         | Presumably for download size and backward compatibility
         | everyone will still serve JS to browsers.
        
           | eddd-ddde wrote:
           | But it'd be nice not to /have to/. Specially when working on
           | new projects with no build step.
        
           | WorldMaker wrote:
           | Typescript Types don't add that much to download size and
           | generally compress _very well_.
        
         | madeofpalk wrote:
         | It is _really nice_. I 'm glad the Node and Typescript teams
         | finally starting making pragmatic decisions to actually be
         | useful.
         | 
         | Now typescript just needs some better defaults from tsc --init
         | to match :)
        
         | Shacklz wrote:
         | Same here - it's really quite something. The future is looking
         | good!
         | 
         | That being said, there are currently still some hurdles.
         | Necessity for explicit file-extensions in the imports is
         | definitely the big offender (it's invalid typescript syntax
         | without the allowImportingTsExtensions-flag).
         | 
         | The trend is definitely clear though, most devs want ESM, most
         | devs want types; it's just a matter of time until the ecosystem
         | adapts. I suppose for types to finally land in the browser,
         | TC39 will have to undergo the "progress is one funeral at a
         | time"-principle, which will probably take another while.
        
       | graypegg wrote:
       | Huh, oddly no mention of native browser support in the form of
       | <script type="module"> and importmaps! To me, that felt like the
       | last platform to offer ESM support.
       | 
       | I also feel like browser support "feels" more official than
       | support from bundlers.
       | 
       | Just weird to leave out a mention of that.
        
         | akoboldfrying wrote:
         | It's certainly nice, and makes possible Vite's very quick
         | reloads of developer code, but even Vite still makes (ESM)
         | bundles for performance reasons, both for production (with
         | everything, using Rollup) and for dev (with just the external
         | deps, using ESBuild).
         | 
         | My understanding is that HTTP 2 pipelining was supposed to make
         | requesting lots of ESM modules from the same site fast enough
         | that bundling could be consigned to history, but for various
         | reasons it didn't work as intended and it was ultimately
         | removed from most browsers.
        
           | dieulot wrote:
           | HTTP/2 "pipelining" (multiplexing) is still there and works
           | as intended; but bundling is still much more efficient.
           | 
           | This article delves into just that:
           | https://csswizardry.com/2023/10/the-three-c-concatenate-
           | comp... The first pair of waterfall graphics illustrates the
           | problem clearly.
           | 
           | (What you vaguely remember as not working as intended is
           | probably Server Push).
        
           | chrismorgan wrote:
           | HTTP protocol changes were never, ever, going to make
           | bundling unnecessary. No one actually involved in the things
           | said it would, or thought it would. It was less-deeply-
           | involved people misunderstanding things that led to that
           | popular impression.
           | 
           | HTTP/2's better multiplexing helps a little, but you've still
           | completely got the waterfall problem: so you have at an
           | absolute minimum of overhead the dependency graph depth times
           | the round-trip time--frequently multiple seconds.
           | 
           | HTTP/2 Server Push could have improved it in some regards, as
           | it can _in theory_ break out of the waterfall problem, but in
           | practice it would have required much more complex servers,
           | and was missing important pieces so that it was completely
           | useless anyway (a way for the client to tell the server what
           | resources it has cached), and they eventually just removed it
           | all round rather than inventing and implementing the missing
           | pieces, with which it _still_ would have been a good deal
           | less efficient to execute than bundling.
           | 
           | Minifying and bundling is just better, no matter what.
        
           | graypegg wrote:
           | Oh yeah I assumed so. I just thought it was weird to not
           | mention it in an article about ESM becoming the standard JS
           | modules format. Even if it's not the most performant use of
           | ES modules, I still think it's certainly the most official
           | "signal" of support to have it in all major browsers.
        
           | WorldMaker wrote:
           | > My understanding is that HTTP 2 pipelining was supposed to
           | make requesting lots of ESM modules from the same site fast
           | enough that bundling could be consigned to history, but for
           | various reasons it didn't work as intended and it was
           | ultimately removed from most browsers.
           | 
           | HTTP/2+ Pipelining works pretty well. (As others mentioned,
           | it was HTTP/2 Server Push that didn't quite survive in the
           | wild, which could have helped additional scenarios.)
           | 
           | I've been personally moving towards Vite's dev approach for
           | _Production_ (just external deps and big libraries with
           | esbuild) and little to no bundling in dev (only external deps
           | that don 't run out-of-the-box as ESM with an importmap). A
           | handful of small "local" files and couple big shared
           | libraries works very well in Production in my experience.
        
         | codedokode wrote:
         | Sadly ESM don't work with local files (file:// protocol).
        
           | graypegg wrote:
           | That would be expected for a browser environment though! I
           | don't want any module my browser imports to silently import
           | something off the filesystem without telling me.
        
           | WorldMaker wrote:
           | Most systems come with Python today, so starting an HTTP
           | server for local testing is often a one-liner like `python -m
           | http.server`. Anyone already working with Node has access to
           | one-liners like `npx http-server`. (Deno and Bun also have
           | one-liners.)
        
       | porridgeraisin wrote:
       | Any kind of migration breaks code. Every single line of
       | _practical_ code hit by a breaking change should be considered a
       | bug. Before the security theater takes the stage, let me clarify
       | by saying that I don 't mean we should not have breaking changes
       | at all, but that only by explicitly treating them as serious
       | bugs, can we even hope to set up a process to minimize them. Of
       | course, the minimization objective will have multiple other
       | variables -- security being one of them.
       | 
       | Therefore, when it is possible to not break _practical_ code, it
       | should not be done. This is the  "linux philosophy", if you will.
       | Among JS runtimes, Bun is a great example. In bun today, you can,
       | in the _same file_ (!!), with zero code changes, 100%
       | transparently:
       | 
       | 1. require() a module regardless of whether it is cjs or esm [1]
       | 
       | 2. _synchronously_ `import` a module regardless of whether it is
       | cjs or esm.
       | 
       | 3. do either of this with typescript or javascript
       | 
       | Some of these required changes in JavascriptCore, which were
       | implemented - it's good to see a lack of cribbing about "it needs
       | to be supported in upstream" and a focus on practical end-user
       | usage.
       | 
       | Any runtime/kernel that doesn't put this level of effort into not
       | breaking code is just not serious. While Node is at least moving
       | in the right direction, supporting require(esm) with some
       | restrictions, Deno is completely hopeless - CJS code is
       | completely unusable on Deno. The reasoning is crazy too - how
       | does it matter if ESM is the "standard", if millions of lines of
       | practical, real world code is using CJS? It does not matter that
       | popular libraries move to ESM. Even a single internal tool that's
       | locked into CJS for some reason means that a project cannot move
       | away from it easily. Then like someone mentioned below, many
       | "plugin architectures" and "command architectures" are pretty
       | much locked in to require(). The whole Deno project screams
       | "ideology > pragmatism". Hopefully, just like they came to their
       | senses w.r.t node compat [2], they implement CJS interop as well.
       | 
       | [1] You cannot require() an ESM module that uses top level await
       | 
       | [2] In contrast, bun's node compat story is very good, they run
       | the Node.js test suite on every commit to Bun, and pass a huge
       | majority of the test cases. Track the progress here:
       | https://bun.sh/docs/runtime/nodejs-apis
       | 
       | There is even some effort put into V8 APIs(in a JSC runtime!!).
       | This helps with using Bun with the usual debugger in the chrome
       | browser/VSCode, modules that use `node:v8`, etc,. Read about it
       | here: https://bun.sh/blog/how-bun-supports-v8-apis-without-
       | using-v...
       | 
       | There is also compat the _other way_ - there are the beginnings
       | of node /browser polyfills for Bun-only APIs:
       | https://github.com/oven-sh/bun/tree/main/packages/bun-polyfi...
        
       | shpx wrote:
       | VS Code still doesn't support ESM in extensions, you have to
       | transpile to CJS.
       | 
       | https://github.com/microsoft/vscode/issues/130367
        
         | mdhb wrote:
         | As a side note it was so depressing reading the release notes
         | of the latest VS Code. It was all just more and more AI slop
         | related nonsense. You could feel the enshitification happening
         | in real time. I don't think there was a single new feature in
         | there I was even remotely excited about.
        
       | Sloowms wrote:
       | ECMAScript modules
        
       | bilalq wrote:
       | The way this cutover is being handled is reminiscent of Python
       | 2->3. To this day, I still run into compatibility issues between
       | things that only work with ESM and things that only work with
       | CJS. It's frustrating, to say the least.
        
       | notanaverageman wrote:
       | Meanwhile I'm trying to adapt ESM only packages to CJS since Goja
       | (JS runtime library for Go) doesn't have ESM support. [1]
       | 
       | And yes I know that Grafana has a fork called Sobek that has ESM
       | support, but it is tailored for k6 and they don't have plans for
       | making it easier to use. [2]
       | 
       | [1] https://github.com/dop251/goja/issues/348
       | 
       | [2] https://github.com/grafana/sobek/issues/49
        
       | jakub_g wrote:
       | Did anyone make a large TypeScript codebase work with ESM + TS +
       | node (together with IDE support and yarn pnp support?)
       | 
       | The thing that is annoying with ESM is that it requires to have
       | extensions in imports, i.e. `import .. from '/foo.js'`.
       | 
       | This gets messy with TypeScript, where your files are named
       | `foo.ts` but you need to import `foo.js`.
       | 
       | The previous "best practice" in TS world was to have
       | extensionless JS imports, so this move would require a massive
       | codemod to update all imports in an entire codebase.
       | 
       | For now, we've been using `ts-node` with swc under the hood, but
       | without ESM. I tried `tsx`, but the compilation time of esbuild
       | is way too slow, some of our node CLI tools written in TS take
       | 15s to boot up, which is not acceptable (with `ts-node` it's
       | 3-4s) (tbh, it's probably partly a fault of our CLI framework,
       | which crawls all workspaces to discover all CLI tools, and as we
       | have a lot of them, tsx has a lot of useless work to do).
        
         | gauben wrote:
         | Hey! Not sure how modern your codebase is, but you can consider
         | the following tsconfig settings:
         | 
         | - rewriteRelativeImportExtensions: this will allow you to write
         | `import foo from './foo.ts'` and have tsc transform it to
         | `import foo from './foo.js'`
         | 
         | - erasableSyntaxOnly: this will error on non "erasable" syntax,
         | that is, TypeScript code that has a runtime output (e.g. enums)
         | 
         | With these two settings enabled, you'd be able to run
         | TypeScript code directly with Node: `node src/index.ts`, and
         | cut boot up time substantially
        
           | hombre_fatal wrote:
           | To add, those are the recommended tsconfig.json settings in
           | Node's docs on native TS stripping. Here are the rest:
           | https://nodejs.org/api/typescript.html#type-stripping
        
           | WorldMaker wrote:
           | Also there are eslint rules older than erasableSyntaxOnly
           | that can also be useful in doing a "rip-the-bandaid-off-
           | refactor" using all the lint warnings/warnings-as-errors to
           | add extensions everywhere in the case where your brownfield
           | also needs to be a version or two behind on Typescript.
        
         | paulddraper wrote:
         | It's pretty easy to find/replace everywhere that needs it.
         | 
         | In my experience the reason people don't is that it offends
         | their aesthetics.
         | 
         | Which I understand. But personally I don't program for
         | aesthetics.
        
         | theogravity wrote:
         | I use a custom loader to deal with this:
         | 
         | https://github.com/theogravity/fastify-starter-turbo-monorep...
         | 
         | Usage:
         | 
         | Search for loader.js refs.
         | 
         | https://github.com/theogravity/fastify-starter-turbo-monorep...
        
       | sarreph wrote:
       | > Although a significant portion of packages still use CJS, the
       | trend clearly shows a good shift towards ESM.
       | 
       | Does it?
       | 
       | The chart being used in the opening argument is far from
       | compelling. When I hold my phone sideways, it looks as though the
       | ESM portion is plateauing or feebly (at best) increasing. Maybe
       | by 2040 we'd see widespread ESM adoption?
       | 
       | Jokes aside, I prefer ESM (and would prefer if everyone else
       | preferred it), but leading with adoption rates is weak sauce.
        
       | codedokode wrote:
       | I am surprised they still use outdated syntax when there is a
       | standard for modules. Also, it is much better when you specify
       | full path to the file and do not have to remember the resolving
       | rules.
       | 
       | Also, last time I tried to use ESM in a browser with Vue and
       | unpkg without builders and web server, it didn't work (probably
       | because one cannot import modules from a local folder). I wish
       | support for ESM and localhost was improved also. I don't want to
       | use a webserver or a bundler because it is easier without them so
       | I switched to legacy scripts without modules.
        
         | tpm wrote:
         | > one cannot import modules from a local folder
         | 
         | Pretty sure this works and it is indeed possible to use ES
         | modules without builders and a webserver, I recently rewrote a
         | Node app this way (with Claude's help even because I'm a ES
         | noob). No idea about Vue and unpkg though, there could be an
         | issue with that.
         | 
         | edit: eh you mean like "import 'file://module.js'", but I don't
         | understand why would you need that when you can use "import
         | './module.js'"
        
           | codedokode wrote:
           | Doesn't work in a browser [1]:
           | 
           | > file: URLs are supported by many non-browser runtimes such
           | as Node, since scripts there already have file: URLs, but
           | they are not supported by browsers due to security reasons.
           | 
           | If you open HTML file directly in a browser, it cannot import
           | ES modules from a filesystem. It can import legacy scripts,
           | but they, as I understand, cannot import anything at all.
           | 
           | [1] https://developer.mozilla.org/en-
           | US/docs/Web/JavaScript/Refe...
        
             | tpm wrote:
             | You don't need file:// module URLs when you say open a
             | index.html from your local drive through
             | file://C:/index.html but then in that index.html you have a
             | 'script type="module" src="src/index.js"' and from there
             | you go through usual relative paths without protocol.
             | 
             | This works in Firefox, I have one project open like that
             | right now. Chrome blocks that because of their CORS policy,
             | but that's another issue, can be mitigated by some
             | commandline options (--allow-file-access-from-files --cors-
             | exempt-headers "*")
        
               | matt_kantor wrote:
               | > Chrome blocks that because of their CORS policy
               | 
               | Firefox has the same behavior (I just tested using
               | Firefox 136 on macOS). The error message says "CORS
               | request not HTTP"[0]. You might have disabled
               | `security.fileuri.strict_origin_policy` in about:config?
               | 
               | [0]: https://developer.mozilla.org/en-
               | US/docs/Web/HTTP/Guides/COR...
        
               | tpm wrote:
               | Yeah, happened long ago so I didn't remember it. Still
               | for dev env I think it's a reasonable tradeoff.
        
         | WorldMaker wrote:
         | While you can't use it without a webserver, today that
         | webserver can be a one-liner like `npx http-server` or `python
         | -m http.server` at least.
        
       | plopz wrote:
       | The main problem with es modules is mocking in tests. How do
       | people work around that issue?
        
         | codedokode wrote:
         | You don't use modules as a replacement for DI?
        
         | giorgioz wrote:
         | You either use Vitest for new projects or you use
         | jest.unstable_mockModule for old Jest tests
        
         | WilcoKruijer wrote:
         | Define an interface, mock the implementation. How people
         | outside of JS/TS have been doing it for years.
        
       | patwolf wrote:
       | I was working on a legacy CSJ project, and I tried to upgrade an
       | OIDC library, but the newer version would only work with ESM. I
       | decided to use that as an excuse to migrate our project to ESM.
       | However, I hit a bug using dd-trace with ESM. Over a year later,
       | that bug hasn't been resolved. I try to use ESM as much as
       | possible for new projects, but it's not always simple to migrate
       | existing projects to ESM.
        
       | darepublic wrote:
       | All these new bundling libraries (vite/rollup) always claim to
       | just work, chefs kiss, 100 emote. And then you actually try to
       | use them for basic use cases and you find yourself googling or
       | knee deep in the documentation. If at all possible I try to avoid
       | bundling libs altogether. That's the future I want. No more vite
       | or rollup or webpack.
        
         | thiht wrote:
         | Uh? That's completely alien to my experience with Vite. Setting
         | up a Vite/React/Typescript project with Tailwind/Tanstack
         | Query/Tanstack Router is an absolute breeze, you just follow
         | the docs. Adding ESLint/Prettier is also just following the
         | docs.
         | 
         | What problems did you encounter specifically? Did you report
         | them?
        
         | winrid wrote:
         | Vite is probably the only one that just works? If you follow
         | the first 3mins of Getting Started it works great.
        
       | bhouston wrote:
       | I've been ESM only for the last 2 years and it has been amazing.
       | Now to be fair, I am doing it on new projects so that probably
       | simplifies things, but it is very freeing and performant.
        
       ___________________________________________________________________
       (page generated 2025-03-24 23:02 UTC)