mrkeyoor.com_
Sun 20 Sept 21:41 UTC
npmDataupdated 20 Sept 2026

fuse.js review

Fuse.js 7.5.0 is an in-process fuzzy matcher for arrays of strings or objects. It builds an index in the browser or Node, ranks approximate matches across weighted and nested fields, and can return character ranges for highlighting. Full builds also understand extended operators, typed object queries, logical expressions, and multi-token searches with corpus-aware weighting. It does not store documents or call a search service. Our complete browser import was 26 KB minified and 9.4 KB gzipped, with bundled TypeScript types and no dependencies. Version 7.5.0 leaves method signatures alone but corrects four scoring faults, so field normalization, key weights, tied limits, and short exact matches can produce a different order than 7.4.

Verdict

Fuse.js 7.5.0 added one package and 1 MB in 0.6 seconds in our sandbox, while its full browser import measured 9.4 KB gzipped with no audit findings. That is a fair cost for typo-tolerant local search, but server-owned data or language-aware retrieval needs a real search backend.

We installed it

Lab card: what happened when we installed fuse.jsScreenshot of fuse.js documentation
Install✓ · 0.6s1 package on disk · 1 MB
ImportESM import works · require() works · ESM package with exports map
Browser9.4 KBgzipped (26 KB minified), bundled with esbuild
TypesTypeScript types bundled
Known vulns00 critical · 0 high · 0 moderate · 0 low (npm audit)

Answers from our run

Does fuse.js install cleanly?

Yes. In a fresh container with an empty cache, npm install fuse.js finished in 0.6s, leaving 1 package and 1 MB on disk. npm audit reported no known vulnerabilities.

How much does fuse.js add to a browser bundle?

9.4 KB gzipped (26 KB minified) when the whole package is bundled for the browser with esbuild. Importing only part of it is usually smaller.

Does fuse.js work with both ESM and CommonJS?

Yes. Both import 'fuse.js' and require('fuse.js') worked in Node 22 in our run. The package is published as ESM with an exports map.

Does fuse.js include TypeScript types?

Yes, type declarations ship inside the package, so no @types install is needed.

fuse.js or minisearch: which should you use?

minisearch: Pick it for a browser-side inverted index with prefix matching and document-oriented search. Fuse.js 7.5.0 added one package and 1 MB in 0.6 seconds in our sandbox, while its full browser import measured 9.4 KB gzipped with no audit findings.

When should you not use fuse.js?

The searchable records are private or too large to send to every browser. Fuse runs beside the data and provides no remote index.

API stability4/5The 7.5.0 release preserves the constructor, `search()` results, collection mutation methods, and index serialization helpers. Its ranking output is less fixed than its callable surface. The release corrects word counting in multiline fields, normalizes key weights, keeps the right top N when scores tie, and honors `minMatchCharLength` on an exact-match shortcut. Teams that snapshot scores or order must review upgrades even within major 7.
Docs5/5fusejs.io documents every scoring option, the score theory, extended and logical syntax, token search, object operators, index methods, and Web Worker restrictions. The README gives current examples and identifies small-to-medium client datasets as the intended scale. No page can choose a threshold or field weights for an unknown corpus, so relevant misspellings and known bad matches still need a local evaluation set.
Maintenance5/5The GitHub repository is unarchived, was pushed on August 9, 2026, and reports one open issue or pull request. Version 7.5.0 shipped on July 13 with four issue-linked ranking corrections and an explicit warning about changed scores. Earlier 7.4 patches repaired CommonJS and worker declaration coverage. The small open queue and recent packaging fixes are strong signs that current release paths are being exercised.
Ecosystem5/5npm recorded 13,671,439 downloads for the latest completed week, and GitHub shows 20,457 stars. Package exports cover ESM and CommonJS, full and basic builds, minified entries, a worker controller, and a worker script. The package bundles declarations for both module systems. It remains intentionally local, so this ecosystem does not include a hosted index, authentication layer, or server-side scaling path.

Use it if

  • A picker, command menu, documentation panel, or settings screen needs typo tolerance over records already present in the client.
  • Several object fields should contribute different weights to one ranked result list.
  • The interface needs inclusive match ranges so it can mark the characters that matched.
  • You can construct or restore one index and update it when the local collection changes.
Skip it if

Setup reality

We installed fuse.js 7.5.0 in a fresh Node 22 Bookworm sandbox. npm finished in 0.6 seconds and left one package using 1 MB. The package has 0 direct dependencies and 0 peer dependencies; npm audit returned 0 findings at every severity. It is 452 KB unpacked, includes TypeScript declarations, and declares Node 10 or later. Both require() and ESM import worked despite type: module.

There are no accounts, secrets, or configuration files. Relevance settings are the setup work. includeScore exposes a value where 0 is best, while threshold decides which distances survive. Location penalties can suppress a valid word late in a long field, so test ignoreLocation on your corpus. Version 7.5.0 normalizes field weights correctly and counts tabs and line breaks as word boundaries; update ordering snapshots after upgrading.

Index construction happens when new Fuse(records, options) runs. Do that outside render and input handlers. Use add() and remove() for small mutations, or setCollection() for replacement. A build can serialize Fuse.createIndex() and the browser can restore it through Fuse.parseIndex(). That saves index-building time at startup, though the browser still needs the source records associated with each result. An empty query returns an empty list.

FuseWorker sends work to Web Workers and makes search() asynchronous. Call terminate() when its owner is disposed. Functions such as getFn, sortFn, and key-level getters cannot be transferred to a worker. Token search is also unavailable there because it relies on corpus statistics that the worker path does not support in 7.5.0. The basic export omits token, logical, and extended search, so test the same export that ships.

Patterns

Fuzzy-search titles and authors search-object-fields

import Fuse from 'fuse.js'

const books = [
  { title: 'The Lock Artist', author: 'Steve Hamilton' },
  { title: 'JavaScript: The Good Parts', author: 'Douglas Crockford' },
]

const fuse = new Fuse(books, { keys: ['title', 'author'] })
const results = fuse.search('javscript', { limit: 5 })

A result carries the original object in `item` and its collection position in `refIndex`.

Expose scores and narrow fuzzy matches calibrate-scoring

const fuse = new Fuse(records, {
  keys: ['title', 'summary'],
  includeScore: true,
  threshold: 0.3,
  ignoreLocation: true,
  minMatchCharLength: 2,
})

A score of 0 is the closest match. Calibrate the 0.3 threshold with expected typos and known irrelevant queries from your data.

Give title matches more influence weight-indexed-fields

const fuse = new Fuse(records, {
  keys: [
    { name: 'title', weight: 2 },
    { name: 'tags', weight: 1.5 },
    { name: 'body', weight: 1 },
  ],
})

Fuse 7.5.0 fixes weight normalization for object and keyless logical queries, which can reorder results produced by 7.4.

Read a nested name and string array index-nested-values

const fuse = new Fuse(people, {
  keys: [
    ['profile', 'displayName'],
    'skills',
  ],
})

const results = fuse.search('database')

An array path avoids ambiguity when a property name contains a dot. Arrays of strings are indexed as values of that field.

Collect ranges for safe highlighting render-match-ranges

const fuse = new Fuse(records, { keys: ['title'], includeMatches: true })
const [hit] = fuse.search('javscript')

for (const match of hit?.matches ?? []) {
  console.log(match.key, match.indices)
}

Each range includes both endpoints. Escape the original string before inserting highlight markup into HTML.

Use typed object search operators query-with-operators

const results = fuse.search({
  title: {
    $startsWith: 'old',
    $not: { $contains: 'draft' },
  },
})

Object operators work in the full build without `useExtendedSearch`. Unknown operators and illegal nesting throw instead of falling back to fuzzy search.

Match every word independently search-query-tokens

const fuse = new Fuse(articles, {
  keys: ['title', 'body'],
  useTokenSearch: true,
  tokenMatch: 'all',
})

const results = fuse.search('express midleware')

`tokenMatch: 'all'` requires all query tokens to match. Token search is absent from the basic and worker paths in 7.5.0.

Join field conditions with boolean logic combine-boolean-queries

const results = fuse.search({
  $and: [
    { title: 'javascript' },
    { $or: [{ author: 'crockford' }, { tags: 'language' }] },
  ],
})

Logical conditions address keys in the index configuration and require the full package export.

Keep an existing index in sync mutate-live-index

fuse.add({ id: 42, title: 'New handbook' })
const removed = fuse.remove((item) => item.id === 12)

if (replacedEverything) fuse.setCollection(nextRecords)

`add()` and `remove()` change the current index. `setCollection()` replaces the data and rebuilds its index.

Restore an index generated during the build restore-built-index

const keys = ['title', 'body']
const raw = await fetch('/search-index.json').then((r) => r.json())
const parsed = Fuse.parseIndex(raw)
const fuse = new Fuse(documents, { keys }, parsed)

The key configuration and document order must be the same ones supplied to `Fuse.createIndex()` at build time.

Move expensive searches off the main thread run-in-web-worker

import { FuseWorker } from 'fuse.js/worker'

const searcher = new FuseWorker(records, { keys: ['title', 'body'] })
const results = await searcher.search('release notes')
searcher.terminate()

Worker searches return promises. Function options cannot cross the structured-clone boundary, and the worker must be terminated when unused.

Test one pattern against one value match-single-string

import Fuse from 'fuse.js'

const result = Fuse.match('javscript', 'JavaScript handbook', {
  threshold: 0.3,
})

if (result.isMatch) console.log(result.score, result.indices)

`Fuse.match()` avoids constructing a corpus index. It rejects token search because one string has no document-frequency statistics.

Alternatives

PackageRegistryPick it when
minisearchnpmPick it for a browser-side inverted index with prefix matching and document-oriented search.
flexsearchnpmPick it when query throughput over a larger memory-resident index is the main concern.
@orama/oramanpmPick it when local search also needs filters, facets, or vector search features.
@leeoniya/ufuzzynpmPick it for fuzzy matching over a flat string list with a narrower API.

More data guides

numpy · fsspec · pandas · sqlalchemy · pyarrow · lxml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.