I migrate from ESLint, Prettier to Biome

History

A couple days ago, I saw Biome from forum, I looked through the website and looks promising. This might become Es-Lint replacement I guess.
The history was when I running ESLint on my project but still got a warning message, my package was deprecated & need to update soon. Seem this happened too often, and sometimes I got confused between ESLint & Prettier configurations, sometimes not compatible or conflict with each other. So I think it's time to look for an alternative.

After deep read Biome website documentation, history & their story. I decided to migrate my small project to Biome. But after all I need some test how fast & how simple their process to migrate my current project using (EsLint & Prettier) into a single Biome configuration.



Migrate process

The migrating process is very quite simple actually, all you need to do is install Biome & run their command. Biome also provides how to migrate from ESLint and Prettier with your current configuration of ESLint & Prettier with ease process migration.

Setup:

Here is steps to migrate my current ESLint & Prettier:

  1. Install Biome npm install --save-dev --save-exact @biomejs/biome
  2. Run their migrate command npx @biomejs/biome migrate eslint --write
  3. Biome will generate new file with our current ESLint & Prettier settings. biome.json
My generated biome.json file
{
	"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
	"vcs": {
		"enabled": false,
		"clientKind": "git",
		"useIgnoreFile": false
	},
	"files": {
		"ignoreUnknown": false,
		"ignore": ["./dist"]
	},
	"formatter": {
		"enabled": true,
		"useEditorconfig": true,
		"formatWithErrors": false,
		"indentStyle": "tab",
		"indentWidth": 4,
		"lineEnding": "lf",
		"lineWidth": 100,
		"attributePosition": "auto",
		"bracketSpacing": true,
		"ignore": [
			"**/node_modules",
			"**/dist",
			"**/.env",
			"**/.gitignore",
			"**/.prettierignore",
			"**/.browserslistrc",
			"public/css",
			"public/font",
			"public/fonts",
			"public/js",
			"**/*.snap",
			"**/*.gif",
			"**/*.jpeg",
			"**/*.jpg",
			"**/*.png",
			"**/*.svg",
			"**/*.ico"
		]
	},
	"organizeImports": {
		"enabled": true
	},
	"linter": {
		"enabled": true,
		"rules": {
			"recommended": false,
			"complexity": {
				"noExtraBooleanCast": "error",
				"noMultipleSpacesInRegularExpressionLiterals": "error",
				"noUselessCatch": "error",
				"noWith": "error"
			},
			"correctness": {
				"noConstAssign": "error",
				"noConstantCondition": "error",
				"noEmptyCharacterClassInRegex": "error",
				"noEmptyPattern": "error",
				"noGlobalObjectCalls": "error",
				"noInnerDeclarations": "error",
				"noInvalidConstructorSuper": "error",
				"noNewSymbol": "error",
				"noNonoctalDecimalEscape": "error",
				"noPrecisionLoss": "error",
				"noSelfAssign": "error",
				"noSetterReturn": "error",
				"noSwitchDeclarations": "error",
				"noUndeclaredVariables": "error",
				"noUnreachable": "error",
				"noUnreachableSuper": "error",
				"noUnsafeFinally": "error",
				"noUnsafeOptionalChaining": "error",
				"noUnusedLabels": "error",
				"noUnusedVariables": "error",
				"useIsNan": "error",
				"useValidForDirection": "error",
				"useYield": "error"
			},
			"style": {
				"useBlockStatements": "off"
			},
			"suspicious": {
				"noAsyncPromiseExecutor": "warn",
				"noCatchAssign": "error",
				"noClassAssign": "error",
				"noCompareNegZero": "error",
				"noControlCharactersInRegex": "error",
				"noDebugger": "error",
				"noDuplicateCase": "error",
				"noDuplicateClassMembers": "error",
				"noDuplicateObjectKeys": "error",
				"noDuplicateParameters": "error",
				"noEmptyBlockStatements": "error",
				"noFallthroughSwitchClause": "error",
				"noFunctionAssign": "error",
				"noGlobalAssign": "error",
				"noImportAssign": "error",
				"noMisleadingCharacterClass": "error",
				"noPrototypeBuiltins": "warn",
				"noRedeclare": "error",
				"noShadowRestrictedNames": "error",
				"noSparseArray": "error",
				"noUnsafeNegation": "error",
				"useGetterReturn": "error",
				"useValidTypeof": "error"
			}
		}
	},
	"javascript": {
		"formatter": {
			"jsxQuoteStyle": "double",
			"quoteProperties": "asNeeded",
			"trailingCommas": "all",
			"semicolons": "always",
			"arrowParentheses": "always",
			"bracketSameLine": false,
			"quoteStyle": "double",
			"attributePosition": "auto",
			"bracketSpacing": true
		}
	}
}
  1. Add new script Biome lint/formatter to integrate with npm script, this script below will automatically fix & format code.
"scripts": {
	"format": "npx biome check --fix --unsafe"
},
  1. Optional: you can remove all related ESLint & Prettier configuration to maintain your project keep clean.

Result:

After migration step completed, I tried run formatter the result very extremely fast as they promised.
Formatter result



Drawback

“There is no ivory that is not cracked” is a proverb that describes perfection. The project is young and can’t compete against giants such as Prettier, ESLint, Webpack, Vite, ESBuild, etc.. I still encounter problems such as:

  • Formatter not fully completely fix as my desire (missing some rules).
  • Still lack of majority programming language. (26/12/2024)

Formatter result

Wrapping up

Honestly I really like this tool, it’s so lightweight, fast and simple. I will consider to use this tool in the future.

But Biome still young tool to compete 1:1 with big projects such as ESLint, Vite, etc.. But when I read their commitment, roadmap, download trend, and Biome can beat challenge from prettier. Seems We can give a chance for this project to beat the competition & blossom. Keep stay tune.

For more detail information you can read completely at Biome documentation.