robinweser / fela

State-Driven Styling in JavaScript
http://fela.js.org
MIT License
2.27k stars 182 forks source link

Native ESM support #875

Closed chrisrzhou closed 3 years ago

chrisrzhou commented 3 years ago

Type: Question


Description

With the coming of the end of Node 10 LTS support, Node and browsers will fully supporting ES modules, is the Fela ecosystem considering pushing formally for ESM support like many other project authors?

I think doing this would involve major breaking change for ecosystem packages and would be disruptive, but it would also mean that Fela ecosystem would be formally using ESM, instead of faux-ESM implemented through bundlers (webpack, CRA etc).

I'm a huge fan of Fela, and was just wondering if Fela is looking to jump on the formal migration to ESM in the near future roadmap!

robinweser commented 3 years ago

Would you mind elaborating what we'd have to do to support that? All we do right now, is generating the ES build with Babel, haven't really dug into additional stuff though. Would love to make Fela ESM-first!

chrisrzhou commented 3 years ago

Happy to go into details in another channel since it's harder to explain in prose. It took myself around 1-2 weeks to fully understand the difference between faux-ESM vs ESM. Build tools (rollup, microbundle, webpack, babel) that generate a dist/index.module.js file isn't equivalent to being an actual ESM.

tl;dr A real ESM module is based on the following specs:

  1. "type": "module" in package.json (for Node to understand), and equivalently <script type="module" /> (for browsers to understand)
  2. files ending with .mjs (Node-only)

Anything not following the above is faux-ESM, and happens to behave as ESMs only by nature of the build tools that support it. For example webpack, rollup, microbundle conveniently process "module": "dist/index.module.js" in package.json to infer that the module is ESM. This is however not the standard spec, so a dependency on building/compiling is required to infer this as ESM.

If consumers are using build tools, it's not a big deal and these tools will handle reading the file as an ESM. It's the reason why build tools just work, because the ecosystem of consumers use these tools as well (e.g. CRA, Gatsby, Snowpack, almost every modern build tool).

A good way to test if a package is an ESM is to run it through node my-script.js calling the source code that you are testing (This is also a good way to test if we are writing JS without the use of additional plugins, and that the code is just standard JS).

Refactoring to ESM is probably a big effort and very likely a breaking change to consumers, since you have to ensure your dependencies are also ESM-compliant. I came across this in fela when I was authoring my package as an ESM, but realized that Fela is faux-ESM.

Not here to influence the direction of Fela but I think this ecosystem is great, and joining the movement of the broader JS ecosystem returning to standards will be exciting! It'll be a future of just shipping source code without compiling and building, and things just run (in Node, in browsers everywhere).

chrisrzhou commented 3 years ago

The very fast way to make Fela ESM without rewriting the code (for the sake of being ESM-pure)

  1. Keep the current bundling/compiling
  2. In package.json, update
    {
      "type": "module",
      "main": "es/index.js"`, // now points to the ESM
      "exports": { // allows CJS/require consumers to still consume
         "import": "./es/index.js",
         "require": "./lib/index.js"
       },
    }
  3. Ensure all dependencies (if any) are ESM
  4. If you decide that Fela will never support CJS (it'll most likely be dead since browsers/Node will formally support ESM and ESM can support CJS), then you can also drop the exports field in package.json in 2.

The expensive part is 3. since you do not have control over it and dependencies need to be (real) ESM for this to work. If an evaluation of the Fela ecosystem suggests that 3. is minimal, then there's a good chance of making Fela ESM-first! It would still mean a major breaking change, but the whole JS ecosystem is going through a disruptive phase with vibes from the Python2 to Python3 migration.

chrisrzhou commented 3 years ago

Closing because it's not a huge issue but looking forward to formal ESM support without build tools in the future!

phiberber commented 1 year ago

What about it today? I see Fela tries to support esm, but it still is using CommonJS libraries such as "isobject".

Actually, the need for the isobject dependency is pretty questionable, but putting that to the side, what are the plans to support esm currently?