DEV Community

Cover image for Unhinged JS Tooling Setups in 2025
Sby
Sby

Posted on

Unhinged JS Tooling Setups in 2025

State of JS tooling

As you may have heard, the JS ecosystem is trying to move away from tooling written in JavaScript like eslint, prettier and even tsc for more performant options.

There are lots of tools being developed, from compilers to metaframework plugins but today let's focus on only the formatters and linters offered.

The big names around are biome, oxc and an announced Microsoft-developed tsgo.

The trade-offs

However, none of these tools have matured enough to fully supercede their JS counterparts just yet.
Just look at all the downsides you're getting with any tool you choose

Tool Shortcomings
oxlint
  • no type awareness
  • no plugin ecosystem
  • only lints the <script> part of .vue, .astro and .svelte files
  • configuration is unintuitive
biome
  • lackluster plugin ecosystem
  • only formats and lints the <script> part of .vue, .astro and .svelte files
tsgolint
  • an experimental prototype without dedicated movement for becoming a real tool
prettier
  • very slow
eslint
  • very slow
  • no one actually uses type aware rules, and if your dependencies don't abide by them, neither can you
  • configuartion is a pure mess, broke backwards compatability with a flat config and plugins take months and years to catch up

Minmaxing DX

So how can we take advantage of all this tooling without the downsides?

With lots of configuration. Here I present to you the setup you can modify for your needs.

package.json

We'll be using a single command script check that both lints and formats

{
  "scripts": {
    "check": "prettier -w . && biome check --write --unsafe . && oxlint -c .oxlintrc.json --fix . && eslint ."
  },
  "devDependencies": {
    "@biomejs/biome": "^2.1.2",
    "@prettier/plugin-oxc": "^0.0.4",
    "eslint": "^9.32.0",
    "eslint-config-prettier": "^10.1.8",
    "eslint-plugin-oxlint": "^1.8.0",
    "oxlint": "^1.8.0",
    "prettier": "^3.6.2",
    "typescript-eslint": "^8.38.0"
  }
}

Enter fullscreen mode Exit fullscreen mode

.prettierrc

Using oxc parser to for a slight speed up

{
  "useTabs": false,
  "tabWidth": 2,
  "singleQuote": false,
  "plugins": ["@prettier/plugin-oxc"],
  "printWidth": 100
}

Enter fullscreen mode Exit fullscreen mode

biome.json

Ignore files not in git

{
  "$schema": "https://biomejs.dev/schemas/2.1.2/schema.json",
  "vcs": {
    "enabled": true,
    "clientKind": "git",
    "useIgnoreFile": true
  },
  "files": {
    "ignoreUnknown": false
  },
  "formatter": {
    "enabled": true,
    "indentStyle": "space",
    "indentWidth": 2
  },
  "linter": {
    "enabled": true,
    "rules": {
      "recommended": true
    }
  },
  "javascript": {
    "formatter": {
      "quoteStyle": "double"
    }
  },
  "assist": {
    "enabled": true,
    "actions": {
      "source": {
        "organizeImports": "on"
      }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

.oxlintrc.json

{
  "$schema": "../node_modules/oxlint/configuration_schema.json",
  "plugins": ["import", "typescript", "unicorn", "promise", "node"],
  "tsconfig": "./tsconfig.json",
  "env": {
    "browser": true
  },
  "settings": {}
}

Enter fullscreen mode Exit fullscreen mode

eslint.config.mjs

Skip rules that oxlint already covers

import js from "@eslint/js";
import prettier from "eslint-config-prettier";
import oxlint from "eslint-plugin-oxlint";
import tseslint from "typescript-eslint";

export default tseslint.config(
  js.configs.recommended,
  ...tseslint.configs.recommendedTypeChecked,
  ...tseslint.configs.stylisticTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  {
    ignores: [
      ".git/*",
      ".gitignore",
      "node_modules/*",
      "target/*",
      "**/bun.lock",
      "**/eslint.config.mjs",
    ],
  },
  prettier,
  oxlint.configs["flat/recommended"],
  ...oxlint.buildFromOxlintConfigFile("./.oxlintrc.json"),
);

Enter fullscreen mode Exit fullscreen mode

Side note on Svelte

Svelte has its own tool it uses for linting, svelte-check, that comes with the svelte-kit template.
And as for the formatter, all it takes is prettier-plugin-svelte to get it working.
Those are slow and very basic but you'll die trying to set up anything else, don't even bother.

{
  "useTabs": false,
  "tabWidth": 2,
  "singleQuote": false,
  "plugins": ["@prettier/plugin-oxc", "prettier-plugin-svelte"],
  "printWidth": 100,
  "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}

Enter fullscreen mode Exit fullscreen mode

Conclusion

And that's it. Leave a comment if you know a way to optimize these further.
Though we all know, the real setup you'll end up using is no tooling at all LMAO.

Top comments (0)