Replies: 22 comments 16 replies
-
1 is a tough one. Being able to run existing ESLint plugins, on the surface, is extremely attractive just in terms of quick adoption. But without the ability to also write your own, I believe you'd hit a very real ceiling. Large projects, and especially large corporate projects are often going to need to write some set of custom rules specific to their codebase and their organization's standards. For the product i work on, for instance, we have our own plugin, with 20-30 custom rules specific to our needs. But we also make use of well-established community plugins (e.g. @typescript-eslint, @graphql-eslint, etc). Without both of those things, it'd be very hard for us to consider it. If we're saying, which is the least bad between the two, I'd encourage you to lean into the benefits of what you've built and take advantage of the performance gains. If it's a compelling enough product, and people are able to port over their eslint plugins, it may take longer for adoption to ramp up, but you wouldn't hit up against that ceiling. |
Beta Was this translation helpful? Give feedback.
-
AI makes the task of porting code a whole lot less daunting. It also rapidly increases the quantity of code per commit and per codebase. For both of these reasons I would vote for erring on the side of performance over backwards compatibility. |
Beta Was this translation helpful? Give feedback.
-
In order to improve adoption, maybe it would be better to start with ESLint compatibility in mind to leverage the existing ecosystem, but design Oxlint’s architecture to leave the door open for a high-performance Rust API.
💡 In an initial adoption phase, you could create a tool (a CLI?) to convert ESLint rules into Oxlint's format. Integrating Oxc into ESLint:
To smoothen the transition, it would be beneficial to work with the ESLint team to integrate Oxc components into ESLint, replacing ESLint’s slowest parts (parser, traversal) with Oxc components. You could execute ESLint rules in Node.js but with Oxc-preprocessed data, so the slowest part of ESLint is bypassed. Rust-based rules: Introduce a Rust API for new/custom rules. Possibly with the help of transform tools (ESLint's format into Oxlint's format) to increase adoption. Supporting both sides, at least in the short and mid-term, would allow users to choose between:
Can this step be automated perhaps?
Maybe we can have both? |
Beta Was this translation helpful? Give feedback.
-
I don't mind migrating my own ESLint rules, but I wonder how the bigger communities (React, Storybook, etc.) act. I need to be able to use their rules. So ESLint compatibility is needed I guess, if they don't adopt Oxlint directly. But I wonder if it could also be the other way around. Make ESLint able to load the Oxlint-js-based rules? Some middle ground for rules that both linters can load to not split the community or at least have some transition phase. |
Beta Was this translation helpful? Give feedback.
-
I'm thinking you should go with the ability to custom plugins using JS, but not support the ESLint API/plugins. One reason is that this would force you to support whatever ESLint supports in a compatible way, potentially down to bugs and anomalies, both in terms of plugin API and potentially in how configuration works.
Obviously, communication between multiple tools to have a similar API would be nice, so ongoing communication would be great. I think it makes more sense to have documentation, guides and/or tools to make it easy to convert from/to the ESLint API. I imagine you're asking this question because you would like to make the API from scratch, and really want to know how much of a deal breaker it would be for people to not support ESLint rules and it's ecosystem. I can't answer to the latter, but technologically I would advise not tying yourself down. |
Beta Was this translation helpful? Give feedback.
-
my two cents as a maintainer of various ESLint plugins and contributor to many more... as oxc maintainers, if your goal is: Adoption If you want to drive adoption up massively, you need an ESLint compat layer. There will be a long tail of plugins for a very long time, if not forever, which do not get ported to oxc whether it be rust or JS. By having a compat layer, you get all of this for free and many more people are likely to make the switch. Performance If you're happy to never be the de facto linter and care more about performance, implement your own JS interface instead. The major plugins will be ported across, and people who use the long tail of everything else can decide if to drop those rules or stay on ESLint. This will probably result in much faster JS-based rules than with an ESLint compat layer. It'll also mean a much smaller API to maintain, most likely. My suggestionMy suggestion is that you create the ESLint compat layer but with some constraints. Don't aim to support every possible ESLint plugin, aim to support most of them. This way, you can disallow certain patterns and parts of the API from being used to get some performance gains. If a plugin wants to support oxc, they can then move off those patterns/APIs. The obvious disadvantage of this is that you, as maintainers, have a greater burden on supporting ESLint compat from then on (e.g. as ESLint changes API over time). If your aim is adoption, though, that is the cost. |
Beta Was this translation helpful? Give feedback.
-
Compatibility with ESLint can be a lower priority, it would be nice to have it eventually though. Similar to Bun's approach with NodeJS compat, they aim for 100% compat sometime in the future. |
Beta Was this translation helpful? Give feedback.
-
From brainstorming with @43081j: Instead of making oxclint eslint plugin compartible, I suggest thinking about writing oxclint plugins and adding a layer to convert them to simple eslint compartible plugins (if possible). This way oxclint can maintain performance and the ecosystem can migrate to oxclint in small steps and in parallel. |
Beta Was this translation helpful? Give feedback.
-
Current eslint rules cover what I need, and the config is straightforward and quite well-known. So unless the new config is significantly more straightforward, I don't want that. If there is, yeah, I'd convert. An automation would be great though 😃 Oxlint's benefits over eslint:
The option to prefer oxlint's implementation where possible and fallback to eslint's implementation would be pretty good. At first glance (with admittedly little domain knowledge), I would expect this to be fairly easy to accomplish. I imagine eslint is pretty stable at this point too, so I'd expect not much danger of the rug getting pulled out from under you. |
Beta Was this translation helpful? Give feedback.
-
I have a suggestion to approach the Oxlint plugin issue from a data-driven angle. What if we start by taking a quantitative look at the plugins? The basic idea is that not all ESLint plugins require the same effort to migrate—some might be quick fixes, while others may depend heavily on ESLint’s nuts and bolts.
Using these two metrics oxlint can approach the adoption goal in a quantitative way. If simple plugins or oxlint builtin plugins can cover > 90% usage, we probably should choose the more performant but non-compatible API. |
Beta Was this translation helpful? Give feedback.
-
We adopted Vite for SvelteKit early on because it was compatible with Rollup and that's been a driver of Vite's success. For this situation I believe adoption is even more tied to compatibility. There are so many more lint rules than Rollup plugins. Users can't switch until all their rules are supported. And many plugin authors will never be motivated to port their rules to a different API. |
Beta Was this translation helpful? Give feedback.
-
Adoption >>>> Speed. Once the tool is widely adopted, we can switch gears to a performant first-class API. Honestly, we should always have a JS plugin API so people can experiment and build POCs on their own. As a non-Rust JS developer, it bothers me that I can't build my own plugins for my niche use cases (and propose the idea to the community). To me, this slows innovations. |
Beta Was this translation helpful? Give feedback.
-
One thing to note is that some JS may always be required thus limiting how much you can squeeze out of the perf route. E.g. if you want to lint Svelte files, you'll always have to call the Svelte compiler, which is written in JS. This means the loss in perf by going with eslint compatibility may not be super noticable for those users. |
Beta Was this translation helpful? Give feedback.
-
I'm pretty sure we need both. Otherwise, many projects will be stuck in a position where they need to run both ESLint and Oxlint. This doesn't really make sense, as ESLint will still require a lot of time and memory. For these projects, it will be much easier to stick to just ESLint without complicating the situation with two different tools. But it's also nice to have a new API that can be used by plugin authors who have the time and expertise to make their plugins faster |
Beta Was this translation helpful? Give feedback.
-
Just wanted to share this really interesting technique that permits to get rid of the Rust <-> JS serialization overhead for cases like JS linter plugins. Speeding up the JavaScript ecosystem - Rust and JavaScript Plugins I don't know if this would work for Oxlint, but it's well worth exploring and apparently it's how Deno linter is implemented. This technique can keep your linter fast, at the cost of more constraints, and may not easily be compatible with the ESLint ecosystem (but apparently that was Deno's goal so maybe it's fine) |
Beta Was this translation helpful? Give feedback.
-
Personally I think it makes the most sense to focus on compatibility with existing eslint plugins, instead of trying to create a new plugin api that is faster, but requires people to rewrite or adapt existing plugins. It already took many years for the majority of linter plugins to adapt to flat config or migrate from tslint -> eslint etc, and introducing a new plugin api that plugin authors would have to support in addition to the existing eslint api, would be a lot of overhead to introduce. For context, I work on a large app with ~30k typescript files and dozens of custom eslint rules, and we are constantly trying to do everything we can to keep our tooling as fast as possible. For the transform -> bundle -> minify pipeline, it makes perfect sense to make this as fast as possible, as it involves processing nearly every file in the repo when we build for production or serve the app for development. For linting (and formatting), you generally only need to process a very small subset of changed files at a time during editing / pre commit / CI (assuming you are not using lint rules with typechecking / eslint-plugin-import rules). The only time you would really need to lint or format everything in the repo is when changing linter config or upgrading plugins, which is something that happens fairly irregularly and doesn't really matter if it's slow. As an example, we recently switched from using the prettier cli, to the dprint prettier plugin, which essentially just runs prettier in parallel via rust, and that has been more than sufficient to make formatting changed files in the pre commit hook / CI feel almost instant, without having to lose any compatibility with prettier formatting, and we were able to switch to it in less than an hour. There was no practical need for us to make things any faster, and start having dprint format typescript files using rust for example. I think the same would be true for switching from eslint -> oxlint, where being faster is good, but achieving the maximum possible performance at the expense of compatibility probably isn't worth it (i.e. we would be unlikely to be motivated to switch if we had to adapt all of our lint rules to work with oxlint) |
Beta Was this translation helpful? Give feedback.
-
I personally would prefer having the most performant rules possible, at least for those that need to infer types or work with the file system. If you want faster adoption, compatibility with ESLint plugins will be most important. It took effort to convince people in my company to give oxlint a try. I am not sure if they are completely sold yet on it yet and I they constantly remind me that ESLint can do X or Y. Yes, we can run both together and we do. More effort could be spent on making the pairing of both tools seamless, but if oxlint is to be a successor and not just a companion to ESLint, it has to make ESLint irrelevant. |
Beta Was this translation helpful? Give feedback.
-
Regarding the first point, from my perspective, usability is more important. For example, our company's projects want to migrate to oXlint, but we are limited by many existing custom ESLint plugins. It's difficult to push for changes to the underlying plugins across the entire company. For many older projects in particular, it's hard to get them to make any changes at all. In order to attract a large number of users initially, we could first ensure compatibility with ESLint. This would allow a large number of users to try oXlint and experience its speed. At some future time, when the user base has grown significantly (through migration of existing users and adoption by new projects), we can consider dropping compatibility with ESLint as part of a major version upgrade. (I'm not sure if this is feasible, since it would require all plugins to be upgraded accordingly, which sounds quite challenging.) |
Beta Was this translation helpful? Give feedback.
-
Please support ESLint Stylistic! It's the biggest block to fully migrate to Oxlint. |
Beta Was this translation helpful? Give feedback.
-
i support compatibility with eslint instead of a new api. like bun -> node |
Beta Was this translation helpful? Give feedback.
-
In terms of compatibility with ESLint, has a https://eslint.org/docs/latest/extend/custom-parsers#all-nodes |
Beta Was this translation helpful? Give feedback.
-
=> Both ability to write my own custom linter plugins, and running some existing ESLint plugins without (too much!) modification
=> Depends a lot on the specifics, if there would be some small differences, e.g. API naming or such, it probably would be fine. But I think generally having 1:1 API support for ESlint would be the better choice. Making oxlint a plug-in replacement is worth a lot. That said, maybe it might make sense to have two APIs, a modern plugin API and a slower legacy ESLint API?
=> Ease of migration is worth some performance hit. At least for general adoption. I think eventually people will start complaining that the legacy eslint plugins are slow, but maybe that can then be tackled by a more modern plugin API that's faster? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Oxlint is a pure Rust based JavaScript linter, and the community has been requesting linter plugins written in JavaScript from the very beginning.
Now, we're confident that we have solid foundations on which to build, and can embark on making this a reality.
It's time to discuss with the community what we should build, as there are many possible approaches — each with different trade-offs.
Key Questions for the Community
1. What do you need from Oxlint?
or
Advantages of Oxlint aiming for ESLint-compatibility:
Advantages of Oxlint diverging from ESLint, and implementing slightly different APIs:
2. Would you be willing to port your ESLint plugins to a different API?
3. How important is performance vs convenience?
Background - how we would approach ESLint compatibility
The approach we could take is:
This is a similar alternative to the original idea to the Complete rewrite of ESLint discussion, before Oxlint became a serious project.
This approach could take a long time to implement, as it requires close collaboration with the ESLint team and deep integration work.
Beta Was this translation helpful? Give feedback.
All reactions