Migrating a JavaScript Project from Prettier and ESLint to BiomeJS
55 comments
·May 7, 2025jemmyw
lucideer
It got press because one of the founders was heavily involved in creating Yarn & very publicly critical of Yarn 2. That general repute (both positive & negative) brought attention to Rome. That's all there was to it.
tshaddox
At least in the JavaScript community (perhaps not the wider tech community) I would say that Sebastian McKenzie was even more well known as the creator of Babel.
sureIy
JS tooling has been a mess since its inception. Here came Rome with promises of it just working and doing everything at once. Of course people sucked it up.
Now whenever I read of "upcoming tools" I couldn't care less. Show me the tool and then we can talk. I'm still waiting for the features that Webpack 4 promised a decade ago.
dhruvrajvanshi
I think you're being too negative about why people got excited. It is quite a bit faster than eslint. Not saying it's a good food idea to use it. I think it asks too much out of me to migrate to it. If they had been even somewhat compatible with eslint, I'd have given it a shot.
jemmyw
They got excited before it existed, at the promise of it being faster
mrbluecoat
Every time I have to click twice instead of once during my once every ~3 years VSCode setup process, I think to myself "If only I could replace Prettier and ESLint with one tool, I could save about 5 minutes during my lifetime."
james2doyle
Running the tool is easy. Installing, configuring, and keeping it updated? Well, those tasks have taken up many lifetimes.
Replacing prettier and eslint in my projects will typically remove about 5 dependencies. Sometimes up to 10 if you have a lot of specific plugins.
Another amazing benefit is that because Biome is a compiled binary, it can run _without npm install_ which means you can use it in your CI for linting before running any expensive build steps.
Those things save me time.
andrewmcwatters
What's so cool is that everyone and their mother is trying to consolidate these tools to save those 5 minutes so that every year I can be advertised to by people like the folks behind Babel, et al, so that I can waste hours of my time moving projects over to something new.
exiguus
Over the past few months, I have migrated numerous projects to Biome and Dprint, and in some cases, back to ESLint and/or Prettier. Projects in plain TypeScript/JavaScript have worked out quite well. However, as soon as JSX/TSX with React or Angular came into play, we encountered lagging issues with popular plugins and configurations. The number of bugs increased, prompting us to revert to ESLint.
I recall that migrating an entire company style guide from ESLint to Biome was nearly impossible because it relied on many rules from other ESLint plugins. Writing these rules / plugins ourselves was too much effort. Perhaps someone else has experience with this and can share their insights?
I agree that performance is valuable, especially in token-based development where you push directly to the main branch. Having hooks and builds run on your local machine and experiencing a 30-second speed improvement is nice. However, in the case of migrating an entire company style guide, it might be more cost-effective to simply buy new laptops that can run everything faster.
Nevertheless, I have had very positive experiences with plain TypeScript projects. In such cases, I would do it again. Especially when you have to update from ESLint Version 8 to 9, taking a look at Biome might be a good investment of time.
egorfine
> BiomeJS started its life as a fork of the now-defunct Rome project
Looking at the pace of frontend development tooling I cannot help but loose trust and confidence with every step and every new release. Major ecosystem player decides to break all previous compatibility with the vast infrastructure accumulated over the years [1]; the main officially recommended linter released under a major brand goes silently abandoned [2]; etc, etc. I didn't even knew Rome died.
A wise queen once said, "it takes all the running you can do, to keep in the same place" [3]. She meant frontend web development.
[1] https://eslint.org/blog/2023/10/flat-config-rollout-plans/
90s_dev
This is the reason I stopped trying to write high-level tools that change every 1-2 years, and moved to creating/publishing low/mid-level tools that should still be relevant in 10 years.
In other words, instead of creating Jekyll, I created a library that makes it trivial to make your own Jekyll however it makes sense to do so that year.
kccqzy
You have choice. You can choose parts of the frontend ecosystem that is not crazy about tooling, like ClojureScript. You can follow a ten-year-old tutorial and it will still work.
egorfine
Not on modern node.js. Not with modern frameworks. So all the running I can do is a requirement, unfortunately.
kccqzy
You can choose not to use node.js. You can choose not to use modern frameworks. Remember that React came out more than ten years ago and doesn't count as modern; so even if you choose a ten-year-old React it's still very good as compared to vanilla JS.
progx
Prettier -> ESLint -> BiomeJS and back to Prettier.
Common standards are ok, but as soon as you want some small modifications, you will come back to prettier. Performance is not a real problem.
hombre_fatal
I think the best .prettierrc file is "{}" (all defaults).
Even as someone who will never write a semicolon myself in Javascript (and still won't), I had to admit that nothing is so important that it's worth straying from zero config.
dmix
Prettier pretty much tells you to not config it
tshaddox
For Prettier I agree that performance is not generally a problem, especially since you're usually only applying it one file at a time (except in CI, perhaps, although even there it probably only needs to be run on changed files). But I have worked on several projects where ESLint performance is a problem in local development.
DGCA
Joined a team that maintains a pretty popular TS library recently. The repo was using Biome. It was unanimously disliked by the team. Linting was broken for most people and in CI. I replaced it with Prettier + ESLint, everyone was into it, and we realized we had a bunch of issues that weren't getting reported due to it not working in CI.
sureIy
What do you mean by "linting was broken"? I seriously doubt this statement without context.
DGCA
I didn't set up Biome and can't tell you why it wasn't working, but people on the team couldn't get the VSCode extension to show lint errors in their editor (Cursor, primarily). I misspoke about there being a CI issue. It was more like disagreeing with their defaults, e.g. `useHookAtTopLevel` and `noUnusedVars` are off by default.
`useHookAtTopLevel` is especially confusing since other React hook rules are on, and `eslint-plugin-react-hooks` defaults its analogue to "error".
But yeah, no linting in the editor was kinda bonkers.
horsawlarway
Based on the title, I expected more from this.
It's not so much "migrating a javascript project" as it is "marketing material style compare/contrast".
Not touched at all is the actual migration process for any real project. Costs, upsides, problems, headaches, etc.
And ultimately, the sales pitch basically boiled down "it's faster because rust/threads". Which... is fine I guess, but just not all that compelling.
Prettier and ESLint are plenty fast in the sense that they process the file I just saved faster than I can react. Anything else I'm going to push off to CI anyways, where the difference between 10 seconds and 1 second is pretty meaningless.
So speed is great and all, it's just WAY down the list of things I actually care about. Show me the reduced config files after migrating a real project, or the reduced time copying boilerplate for configs. But... it doesn't look that exists based on this article, since it's basically just "ESLint and Prettier configs combined".
Why even show me the discrete lint/format steps if the whole pitch is that the tool combined them? Just show me the check command.
---
As a tool, this looks fine - would love to see a real successor to Rome, including the bundling step.
Otherwise this is a pretty bland & boring marketing pitch.
zoogeny
Just tangentially related, but a few days ago I did a quick analysis on lint/format options for a TypeScript project and I ended up picking eslint and prettier over BiomeJS. The main reason was eslint/prettier are a bit more battle tested and according to Gemini Pro, Biome is still adding new features to catch up to eslint/prettier which makes me feel it will be a bit less stable for now.
But what I wanted to comment on actually was eslint and how it nudged me down the path of ESM support. I had to fight and fight to get it to work with my Typescript project. The resolution proposed by the tool was strongly biased towards re-structuring my project away from commonjs modules towards the newer ESM. But when I started down that rabbit hole I found it frustratingly hostile to TypeScript based projects. I was playing whack-a-mole between my package.json, tsconfig, my vite config, my eslint config. Most of it had to do with ts-node and the esm module loader (or something). Eventually it wanted me to rename all of my imports with .js extensions?
In the end I just gave up and went back to commonjs and added strategic "ignores". The modern JS ecosystem has mostly been turn-key, but this was a remembrance of the old days where it felt necessary to wave dead chickens over things to get them to work. I would seriously consider BiomeJS in the (near) future if it's Typescript story was better than what I've experienced with eslint.
And as for ESM, right now it is leaving a really bad taste in my mouth. I will have to dedicate some time soon to figure out how to setup a very basic TypeScript project using ESM and incorporating the basic tools that I require.
dhruvrajvanshi
I went through exactly what you went through and by god it was frustrating.
Eventually I did get stuff to work, but in the process I became an expert in a bunch of tools that I never wanted to be an expert in. I just wanted to write my business logic :') It makes me long for Java tooling.
To top it all off, I don't think could've done a better job than the people responsible for this complexity.
> What did we learn from all this?
> I don't know.
> Well I don't know either.
> I guess to not do it again...fuck if I know what we did in the first place
I guess eventually all tools will converge to a de-facto mixed module/commonjs module resolution standard which roughly matches what tsx (the ts-node replacement, not the file extension) does.
sureIy
ESM is actually quite simple. The problem is just that people don't know the basics and tools are encumbered by years of cruft and varying behavior. Check out how many "module" and "moduleResolution" behaviors TypeScript alone has.
The trick is to start fresh and to know the basics:
- use type=module
- import with extensions
- use a sensible shared tsconfig (this is the hard part)
- don't use junk tools like webpack and jest
dhruvrajvanshi
> - don't use junk tools like webpack
I used to have that opinion, but now, going through a months long project modernizing our codebase's build tooling, I'm not so sure. Vite isn't so amazing either if you stray away from the happy path (html entry points). I guess no build tool is amazing. At the end of the day, the only thing I can say is all build tools suck. Write less build code if you can get away with it.
Eventually I had to settle on rspack (the spiritual successor to webpack) because vite wouldn't do what I wanted it to do. You could say it was the wrong tool for the job, but it took me a while to figure that out, given how scary it is to not use the frontend build tool. I still wish we could've used it because then we'd be using an industry standard tool.
Getting back to criticizing Vite (sorry have to vent haha) in my experience, vite's API is also built on weird foundations. It exposes rollup and postcss options in it's config, which sometimes do similar things as it's own config options. It generates tons of small chunks with no obvious way to control it without giving up on nice things.
myvoiceismypass
Also, should be noted that vitest does not require you to be using vite for bundling and is much much faster / easier to configure than jest these days. (It also has a jest-compatible API)
zoover2020
What is s sensible tsconfig according to you?
sureIy
I use @sindresorhus/tsconfig, but there are a handful of possible improvements over it (see open issues)
herpdyderp
I really wish there was viable replacement for Prettier with the same language support coverage. Every Prettier release introduces new breaking bugs for me, (I'm not talking about formatting updates I'm talking about formatting that never settles or outright crashes, etc.) and they never fix them. The plugin system for Prettier is also the worst I've ever seen, it's a nightmare to write a plugin.
haburka
Prettier is one of the hardest projects to maintain. There’s so much code necessary to format ALL of the languages. I haven’t checked out the plugin system.
Also the core philosophy of prettier is to basically ignore people’s aesthetic preferences about code. Which causes lots of flame wars in the issues.
They really do fix crashes if you submit PRs though. Do you not like contributing to open source but still feel empowered to complain about it? Opening a ticket with a good reproduction case is also contributing but sometimes it’s necessary to put a bit more effort into tools.
Eric_WVGG
> While Biome supports multiple languages, it lags behind Prettier in terms of coverage. Notably, HTML, Markdown, and SCSS are not yet supported
Seems like they started with the hard ones and are getting around to the easy ones? Or is linting HTML difficult because of cruft?
conaclos
Our HTML formatter is ready and will be part of the upcoming Biome v2 release.
nine_k
Formatting HTML is a much less painful and slow task than formatting TS. There are a few good and fast tools for that anyway. Also, you typically don't use a lot of HTML files along with substantial amounts of TS; the latter usually does JSX.
Formatting SSCS should be trivial compared to even formatting HTML, which is trivial compared to formatting TS. They took on the principal task first, and did not allow doing the trivial tasks early to inform any implementation decisions, which should be optimized for the hardest and most important task.
difosfor
Biome is still missing support for lots of eslint plugins that I like so I ended up with Biome plus just those cherry picked ESLint plugins and rules. It's not great..
https://voidzero.dev/ is also working on https://oxc.rs/ sounding nice since I already enjoy vite and it seems to have some funding but I fear it'll end up likewise..
sibeliuss
This migration worked great for us, but we ran into one hiccup, which led us back to prettier (while keeping linting, which has been working flawlessly): the current formatter (afaik) doesn't support embedded languages properly, so something like:
const foo = graphql` <some query> `
wont get formatted. In a big graphql codebase (where half the code IS graphql) its totally essential. Very much looking forward to this feature.
Otherwise, Biome has simplified our codebase config dramatically. So dreadful thinking of ESLint, and particularly ESLint 9.
rafram
> In terms of performance, Biome is over 15 times faster than ESLint, again thanks to its Rust-based, multi-threaded architecture.
No doubt also thanks to only having a tiny fraction of the feature set.
nine_k
If Biome becomes twice as slow when it implements everything, it will still remain many times faster than ESLint, and likely will still eat much less RAM.
I find Rome/Biome quite fascinating. Not the tools themselves. I just find it really interesting that Rome made so much noise and got so much press before they ever had anything worth talking about. People kept posting in work chats about it over the years: this will solve so many problems etc. What will? I'd ask. There's nothing there yet.
And did we ever need this tool? Prettier and eslint are different beasts, both pretty good, and integrate well together. But again, it's not the tools themselves that are interesting, it's the way Rome was talked about so much without existing. When prettier appeared it was just released: "here is a new tool to format things, it's much faster than what we had before." It then took a long time to permeate and become essential, and it improved along the way, became multi language etc. Prettier is a thing, a tool, it has no mission other than what it does. Rome was an idea without a tool, and it never came to fruition.
You could make some kind of conclusion about this, that oss projects based on grand ideas are doomed, you need code to be released first, to build on and grow. But I don't think that conclusion in itself is that interesting, certainly not novel. What's interesting is why did Rome happen, why did the people behind it drive it in that way? Why did so many get excited by it? It's so very similar to companies that hype themselves stratospherically and often fail. Except at least there is a point to their hype: get investment money and try and use that money to make the hype reality. I don't understand the purpose behind the same thing with Rome. It really itches at me to know more, to understand. To understand why it appealed so much to my peers, it's just linting and formatting, we have that already, and any new tool will start with rough edges. Sometimes you see similar a sort thing with projects and think it's based on aggrandizement of the dev behind it, but those projects peter out quickly. Rome kept it going for years.