javascript

Migrating A JavaScript Project from Prettier and ESLint to BiomeJS

Damilola Olatunji

Damilola Olatunji on

Migrating A JavaScript Project from Prettier and ESLint to BiomeJS

Prettier and ESLint have long been indispensable tools in the JavaScript ecosystem for ensuring code consistency and quality. They have become staples in the toolchains of JavaScript projects worldwide.

However, a new player has emerged to challenge their dominance: BiomeJS. This ambitious project seeks to combine the functionality of both tools into a single, high-performance solution for code formatting and linting.

By combining these capabilities, Biome aims to simplify workflows, reduce configuration complexity, and significantly boost performance, thus positioning itself as the next generation of JavaScript tooling.

In this article, I'll introduce the BiomeJS project, explore its setup, and help you decide if migrating from Prettier and ESLint is the right move for you.

What Is Biome?

BiomeJS started its life as a fork of the now-defunct Rome project, but has since evolved into its own distinct toolchain focused on providing a fast, integrated development experience.

It currently provides two solutions for JavaScript developers:

  1. A Prettier-like code formatter.
  2. A powerful linter that's inspired by ESLint.

By combining these tools into a single solution, Biome minimizes the need for multiple configurations, thus creating a more seamless experience for developers.

It is also built with a modern architecture, using Rust for speed and multi-threading, making it more than an order of magnitude faster than its predecessors.

In this way, it represents not only a replacement but also a significant leap forward in simplifying and optimizing the JavaScript development workflow.

Comparison with Prettier

Biome's formatter, like Prettier's, offers only a few configuration options. Its output is mostly compatible with Prettier — though there are some differences — and it formats about 25 times faster because it's multithreaded and written in Rust.

While Biome supports multiple languages, it lags behind Prettier in terms of coverage. Notably, HTML, Markdown, and SCSS are not yet supported, and frameworks like Vue, Astro, and Svelte have only partial support.

Comparison with ESLint for JavaScript

Many of Biome's linting rules are inspired by ESLint and other popular linters, and organized into specific categories. Like ESLint, these rules are fully configurable, allowing you to disable any rule or enable only a subset.

You can customize how rule violations are handled, choosing whether they trigger warnings or errors, and whether automatic fixes should be suggested. For example:

JSON
{ "linter": { "rules": { "correctness": { "noUnusedVariables": { "level": "error", "fix": "none" } }, "style": { "useConst": { "level": "warn", "fix": "unsafe" } } } } }

Biome's linter also extends beyond JavaScript/TypeScript by supporting other languages. It includes several CSS linting rules from stylelint-config-recommended with more in development. For a full list of supported rules, refer to the Biome documentation.

In terms of performance, Biome is over 15 times faster than ESLint, again thanks to its Rust-based, multi-threaded architecture.

Getting Started with Biome

Although Biome isn't written in JavaScript, its executable is distributed through the NPM registry, so you can easily install it through your preferred package manager:

Shell
npm install --save-dev --save-exact @biomejs/biome

After installation, you can access the biome executable by running:

Shell
npx biome --version # Version: 1.9.2

Biome doesn't require a configuration file to get started, allowing you to use it immediately after installation.

For demonstration purposes, here's a sample JavaScript file you can experiment with:

JavaScript
// index.js function sayHello(name){if(name){console.log("Hello, "+name+"!");}else{console.log("Hello, World!");}}let person="John";sayHello(person);

Formatting with Biome

To format code, you can use the format command like this:

Shell
npx biome format index.js

By default, the format command operates in a dry-run mode, displaying the proposed changes in the terminal with unformatted code in red and the corrected version in green.

Screenshot of Biome's format command in dry-run mode

If you're happy with the changes, apply them using the --write flag:

Shell
npx biome format --write index.js

You will see a confirmation message like this:

Shell
Formatted 1 file in 840µs. Fixed 1 file

Linting with Biome

Biome can also lint your project files with the lint command:

Shell
npx biome lint index.js

If there are linting problems in the file, you will see the following output:

Screenshot of linting output

Linting issues are categorized into three levels: info, warn, and error. The lint command exits with a non-zero code for error-level issues, but you can treat warnings similarly by using the --error-on-warnings flag:

Shell
npx biome lint --error-on-warnings

The linting output provides detailed explanations for why a rule was triggered and how to resolve the issue.

Each issue is annotated with the file name, line number, the rule that was violated, and a human-readable description of the rule. The problematic code is highlighted with red markers, and for "fixable" issues, the suggested fix is shown in green.

Biome offers two types of fixes for linting issues:

  1. Safe fixes which are guaranteed to preserve the semantics of your code.
  2. Unsafe fixes which may change the semantics of your program.

To only apply safe fixes, use the --write flag as follows:

Shell
npx biome lint --write <path/to/files_or_dir>

For unsafe fixes, add the --unsafe flag:

Shell
npx biome lint --write --unsafe <path/to/files_or_dir>

Combining Formatting and Linting

Biome also allows you to format, lint, and apply fixes in one step using the check command:

Shell
npx biome check <path/to/files_or_dir>
Shell
npx biome check --write --unsafe <path/to/files_or_dir>

Now that you're familiar with Biome's basic commands, let's move on to integrating it with your text editor.

Integrating Biome in Code Editors

Biome is designed to integrate seamlessly with code editors, allowing you to receive linting feedback as you type and automatically format code on saving.

At the moment, first-party extensions are provided for VS Code, IntelliJ, and Zed. You can also explore third-party extensions for editors like Vim, Sublime Text, and others. In this section, I'll be working with Visual Studio Code.

Screenshot of official VS Code extension

To use BiomeJS in Visual Studio Code, search for "Biome" in the extensions panel, click on the entry, and hit the Install button.

Once installed, you'll immediately see linting errors highlighted in supported files:

Screenshot of BiomeJS linting errors in VS Code

To automatically apply suggested fixes on saving, let's configure VS Code's "Actions on Save" setting. Open the command palette with CTRL+SHIFT+P (or CMD+SHIFT+P on macOS), search for "User Settings", and select Preferences: Open User Settings (JSON):

Screenshot of User Settings option

In the settings.json file, add or update the following configuration:

JSON
{ "editor.codeActionsOnSave": { "quickfix.biome": "explicit" } }

This setting ensures that Biome automatically applies "safe" fixes when a supported file is saved. Currently, the extension doesn't support unsafe fixes, so these must be applied via the command line or the code actions menu:

Screenshot of code actions menu for applying Biome fixes

Biome can also format your code automatically on save. To enable this, update your settings.json file with the following:

JSON
{ "editor.formatOnSave": true, "editor.defaultFormatter": "biomejs.biome" }

The editor.formatOnSave option enables automatic formatting on saves, while editor.defaultFormatter specifies Biome as the default formatter.

If you'd like to enable Biome formatting for specific file types, use this configuration:

JSON
{ "editor.formatOnSave": true, "editor.defaultFormatter": "prettier", "[javascript]": { "editor.defaultFormatter": "biomejs.biome" } }

In this setup, Prettier is used as the default formatter for all file types, while Biome is applied specifically for JavaScript files.

With these settings, Biome will automatically fix and format your code whenever you save a file.

Screenshot of formatted code in VS Code

Configuring Biome for Your JavaScript Project

You can configure Biome through CLI options or by creating a biome.json file at the root of your project. Biome will automatically search for this configuration file in the current directory and parent directories up to the filesystem root.

This feature is particularly useful in larger projects or monorepos, as it allows for project-specific settings depending on the folder structure.

The easiest way to create a Biome configuration file is by using the init command:

Shell
npx biome init

This will generate a biome.json file in your current directory with default settings like:

JSON
{ "$schema": "https://biomejs.dev/schemas/1.9.2/schema.json", "vcs": { "enabled": false, "clientKind": "git", "useIgnoreFile": false }, "files": { "ignoreUnknown": false, "ignore": [] }, "formatter": { "enabled": true, "indentStyle": "tab" }, "organizeImports": { "enabled": true }, "linter": { "enabled": true, "rules": { "recommended": true } }, "javascript": { "formatter": { "quoteStyle": "double" } } }

If you prefer to include JSON with comments in your configuration, use the --jsonc flag to create a biome.jsonc file:

Shell
npx biome init --jsonc

Here's a breakdown of the default settings:

  • Schema: Ensures compatibility with a specific version of Biome. You can also point it to a relative path:
JSON
{ "$schema": "./node_modules/@biomejs/biome/configuration_schema.json" }
  • VCS: Biome's VCS integration is turned off by default.
  • Files: Biome will process all files in your project and won't ignore any unknown file types.
  • Formatter: Code formatting is enabled, and tabs are used for indentation.
  • Organize Imports: Automatic import sorting and organization is enabled.
  • Linter: Linting is enabled, using Biome's recommended set of rules.
  • JavaScript: Double quotes are used for strings in JavaScript and TypeScript files.

You can further customize the configuration by modifying biome.json according to your project's needs. Explore the full list of supported configuration options in the official Biome documentation.

Migrating from Prettier and ESLint

If you're transitioning from Prettier or ESLint, there's no need to start your Biome configuration from scratch. Biome provides a migrate command that reads your existing configuration files and attempts to port the settings into Biome:

Shell
biome migrate eslint --write biome migrate prettier --write

For more detailed instructions and guidance, refer to the ESLint and Prettier migration guide.

Ignoring Linting or Formatting Errors

It is sometimes necessary to bypass linting or formatting rules for specific lines of code. Using the biome-ignore comment, you only need to place a comment on the line before the code you want to exclude.

To prevent certain lines from being formatted, use:

JavaScript
// biome-ignore format: <explanation>

For example:

JavaScript
// biome-ignore format: ignore this function function sayHello(name){if(name){console.log("Hello, "+name+"!");}else{console.log("Hello, World!");}}

Similarly, you can ignore linting rules through:

JavaScript
// biome-ignore lint: <explanation> // biome-ignore lint<rule>: <explanation>

For instance:

JavaScript
// biome-ignore lint: lint/style/useConst: prefer let let person = "John"; console.log(person);

To ignore entire files, configure the files.ignore, linter.ignore, or formatter.ignore settings in your biome.json file:

JSON
{ "files": { "include": ["src/**/*.js", "src/**/*.ts"], "ignore": ["**/*.min.js"] }, "linter": { "ignore": ["**/dist/*"] }, "formatter": { "ignore": ["bundle.js"] } }

Integrating Biome in Existing Projects

When adding Biome to an existing project, you may want to apply all formatting and linting fixes across the entire codebase and commit the changes in a single commit. However, if this isn't practical, you can limit the formatting and linting to only the changes made since the last commit.

To enable this functionality, you need to activate Biome's VCS integration and specify the vcs.defaultBranch field in your configuration:

JSON
{ "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true, "defaultBranch": "main" } }

With this configuration, you can use the --changed option to process only the files modified since the last commit:

Shell
npx biome check --changed

This ensures that Biome only checks and applies fixes to files recognized as having changed by your version control system.

Setting Up a Pre-commit Hook

As of Biome v1.7.0, you can exclusively process staged files using the --staged option, eliminating the need for external tools like lint-staged:

Shell
npx biome check --staged

To automate this, add a script to your package.json file:

JSON
{ "scripts": { "lint:staged": "biome check --error-on-warnings --no-errors-on-unmatched --staged ./**/*.{js,ts}" } }

Next, set up husky to run the lint:staged script before committing changes:

Shell
# .husky/pre-commit npm run lint:staged

For more detailed examples and additional recipes, refer to the Biome documentation.

Setting Up a Continuous Integration Workflow

Running linting and formatting checks on each pull request helps ensure that only code that meets your project's standards is merged into your codebase.

You can automate this by integrating Biome into your Continuous Integration (CI) pipeline. If you're using GitHub Actions, you can set up the official setup-biome action as follows:

YAML
# .github/workflows/biome.yml name: Code quality on: pull_request: jobs: biome: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Biome uses: biomejs/setup-biome@v2 with: version: latest - name: Run Biome run: biome ci .

Once configured, any issues found by Biome will be displayed inline within pull requests to prevent new issues from slipping in.

Should You Switch to Biome?

Biome.js language support

Biome offers a refreshing take on development tooling by consolidating both linting and formatting into a single dependency with a unified configuration file. This reduces the complexity of managing multiple tools and allows teams to get started quickly, thanks to its strong default settings.

A key advantage of Biome, besides the huge performance gains, is its clear, user-friendly error messaging, which often includes guidance on how to resolve issues. Compared to ESLint, these error messages are more readable and help developers adhere to coding standards with less frustration.

However, Biome also has its limitations. Its reliance on JSON (or JSONC) for configuration can feel restrictive, especially for dynamic setups, where using JavaScript would offer more flexibility.

Biome.js language support

Switching to Biome may also result in less than optimal support for certain file types such as Vue, Markdown, YAML, and others, which could be a drawback if you work extensively with those formats.

Ultimately, the decision to switch depends on your project's needs. If Biome supports your most frequently used files, and you value improved performance, simplicity, and a unified toolchain, then it's certainly an attractive alternative.

You can also get the best of both worlds by using Biome for the file types it fully supports, while continuing to use Prettier/ESLint for the rest until Biome becomes more mature.

Wrapping Up

In this post, we covered the ins and outs of Biome, compared it to Prettier and ESLint, and saw how to configure and integrate Biome into projects. We also touched on some of its limitations.

I hope this has given you a better insight into Biome and whether you should choose it for your next JavaScript project.

Thanks for reading!

Wondering what you can do next?

Finished this article? Here are a few more things you can do:

  • Share this article on social media
Damilola Olatunji

Damilola Olatunji

Damilola is a freelance technical writer and software developer based in Lagos, Nigeria. He specializes in JavaScript and Node.js, and aims to deliver concise and practical articles for developers. When not writing or coding, he enjoys reading, playing games, and traveling.

All articles by Damilola Olatunji

Become our next author!

Find out more

AppSignal monitors your apps

AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!

Discover AppSignal
AppSignal monitors your apps