Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to generate ESM for standalone validators #1523

Closed
realityking opened this issue Mar 30, 2021 · 12 comments
Closed

Option to generate ESM for standalone validators #1523

realityking opened this issue Mar 30, 2021 · 12 comments

Comments

@realityking
Copy link
Contributor

What version of Ajv you are you using?

8.0.1

What problem do you want to solve?

Importing CommonJS modules creates non-ideal code when bundling with Rollup or Webpack and let them not participate in tree shaking. Code will be smaller and more efficient when ESM is used for bundling.
This will also gain in importance as npm packages will soon ship more and more ESM code.

What do you think is the correct solution to problem?

There are two parts to be done here:

  1. Add an esm option to ajv compile/standaloneCode
  2. Ship ESM versions of the runtime files and have an exports map for Bundles and Node.js to pick them up correctly.

The first change is the more important one but both are necessary for the full effect.

Will you be able to implement it?

I'm not sure. I started looking through the code a bit and I see how to get started but I expect to get stuck at some point. I'd definitely need help down the line.

@epoberezkin
Copy link
Member

This does not seem in scope, there are other tools that do it. This is not the same argument as exists for supporting ES5 code - it is needed for run-time schema compilation in ES5 environments.

For build time compilation you can compile to CommonJS and then use some other tool to transpile to ESM that would then be passed to any tool that works better with ESM than with CommonJS. If anything, arguably, it is definitely more in scope of rollup or webpack to have better support for CommonJS that it is in scope of Ajv to generate ESM, but in any case another tool can be used.

@realityking
Copy link
Contributor Author

If anything, arguably, it is definitely more in scope of rollup or webpack to have better support for CommonJS that it is in scope of Ajv to generate ESM, but in any case another tool can be used.

Both Webpack and Rollup have invested a lot of time into this and it works from interoperability standpoint. It does however generate less optimal code (everything will be wrapped in a closure) and in the case of Webpack the module won't participate in tree shaking.

ESM is the strictest of all the module formats as every export and import has to be static. This makes it easiest to transpile into any other module format. With both browsers and Node.js converging on it as the shared standard, I believe it's where the future is heading. It'd be great to gain of some the benefits with standalone validators generated by AJV.

@epoberezkin
Copy link
Member

I understand - ESM is less flexible than CommonJS, so there is no general way to effectively transpile from all CommonJS to ESM. On another hand, majority of CommonJS modules have effectively static exports, so it could be possible to detect it during code analysis and when it is the case to avoid closures... Not 100% sure about it.

I am definitely supportive to move to ESM fully once it is a dominant module format - we're are not there yet. Let's see how much support this option has over the next couple of month - if many users need it, happy to add this option to standaloneCode.

The current workaround is relatively straightforward - you need to replace the code that is generated here and here - using grep, awk, or any other utility, if no JavaScript transpilers can effectively convert CommonJS to ESM. Alternatively, you can fork and change these two lines.

@epoberezkin
Copy link
Member

The files from runtime folder - the easiest is to compile them from typescript to ESM.

@SirLich
Copy link
Contributor

SirLich commented Jun 7, 2021

Hi! I normally view "bumping" a discussion like this as annoying, but you explicitly asked for "Let's see how much support this option has over the next couple of month".

I would personally find ES6 imports for standalone extremely useful!

I am using AVJ in a Vue3+Vite setting, which does not allow me to transpile at build-time (no webpack). I am currently using a VSCode addon to do it for me, but its all a little undesirable.

@kmoschcau
Copy link

I would also be interested in this. I am using AJV in an environment where I can't easily add dependencies without shipping the entire dependency with my code. So the standalone code is already a really nice feature. However that environment only uses ESM, so currently I have to resort back to string replacement or similar. It would be great if AJV would have at least an option for the code generation to generate ESM instead of CommonJS.

@thw0rted
Copy link

I just filed ajv-validator/ajv-cli#192, after opening this issue in a tab but before reading it. (Sorry!)

I would argue that, since AJV is written in TS, and TS transpiles seamlessly to ESM, it would make more sense to have "compile" / "standalone" generate a TS module with ESM-style exports. If users really need vanilla JS in ESM format, the CLI could pipe the output through tsc to achieve that.

@epoberezkin
Copy link
Member

ok - let's add this option to standalone.

I'm not sure what's the best way to add it though - it has the second optional parameter that can be an object, so you can't easily overload, and adding it as an Ajv option also feels weird as it would only affect standalone code...

Any better idea?

@epoberezkin
Copy link
Member

Maybe whoever wants to pass options object to standaloneCode as the 3rd parameter would have to explicitly pass undefined in place of the 2nd parameter, unless there is some other value to pass?

@thw0rted
Copy link

I don't have a good mental model of how the code options-object works (passed to the Ajv constructor). I use the lines property already, and it has an es5 option. Why not add a ts or esm option?

@epoberezkin
Copy link
Member

Because it is only relevant to who the code is exported, not to how it is generated, so it has no impact on Ajv itself, only in the standaloneCode function that generates exports…

We don’t have some other options though that would only be used for standalone code, so maybe it’s ok to add it there

rehanvdm pushed a commit to rehanvdm/ajv that referenced this issue Dec 20, 2021
…r#1523)

- Renamed exportEsm to esm
- Extracted common code
- Changed invalid export names to rather throw an error
epoberezkin pushed a commit that referenced this issue Dec 22, 2021
* feat: add option to generate ESM exports instead of CJS (#1523)

* feat: add option to generate ESM exports instead of CJS (#1523)
- Renamed exportEsm to esm
- Extracted common code
- Changed invalid export names to rather throw an error
@epoberezkin
Copy link
Member

merged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

5 participants