lucaong / minisearch

Tiny and powerful JavaScript full-text search engine for browser and Node
https://lucaong.github.io/minisearch/
MIT License
4.81k stars 137 forks source link

Tree-shaking consideration? #219

Closed Mister-Hope closed 1 year ago

Mister-Hope commented 1 year ago

Hi here, the Minisearch package is class based, meaning the whole library will be packed into runtime.

I am using this feature to provide client side search, so that the only apis I use is MiniSearch.loadJSON to load build time generated index, and MiniSearch.search to get search results. Under this, a lot of code will be never used, and I would like them to be removed.

Is there any plans to move this package in to "function-based" apis, so that we can tree-shake the code (e.g.: with rollup)?

Possible APIs

import {
  createIndex,
  loadJSONIndex,
  loadIndex,
  search,
  add,
  toJSON,
} from 'minisearch';

// new Minisearch()
const index = createIndex({
  // options
});

// MiniSearch().loadJSON()
const index = loadJSONIndex(indexString, {
  /// options
});

// MiniSearch.loadJS()
const index= loadIndex(documents, {
  /// options
});

// index has some state on it, like `isVaccuming` `termCount`

// apis should interact with index so that unused ones get tree-shaked

// MiniSearch.search()
search(index, query, {
 // search options
})

// MiniSearch.add()
add(index, document)

// MiniSearch.discard()
discard(index, id)

// MiniSearch.discardAll()
discardAll(index)

// other apis should be similar, with an extra index argument as first one

Motivation

This package is called minisearch , so I think size can be important.

lucaong commented 1 year ago

Hi @Mister-Hope , I understand the appeal of a function-based API, and I like the functional style, but this would be a huge breaking change at this point. While requiring each function separately would make it possible to require only what needed, the whole of MiniSearch is below 10kB (with no dependencies) when compressed, so the need for tree-shaking is limited.

Functional and class-based APIs both provide advantages and disadvantages, none of them being intrinsically superior. If the index was implemented with an immutable data structure, so that add, discard, etc. returned an immutable copy of the index, I would definitely have chosen a functional API. But the MiniSearch index is stateful (which provides performance benefits), and the class-based API has the advantage of providing namespacing for functions, making it very clear at a glance what methods belong to the library, versus helper functions implemented in the specific application.

Ultimately, such a function-based API could have been a reasonable way to structure the library, but so is the class-based style. The benefit of requiring each function separately is limited given the small size of the whole library, and a redesign that completely breaks backwards compatibility would impose too big of a cost to the thousands of projects currently using MiniSearch.

I do appreciate the suggestion, and I do think that your design has its merits. I simply think that the trade-offs do not make it worth.

Mister-Hope commented 1 year ago

Thanks for explaining, I will release a function-based package by forking this repo and sync changes upstream (here).

The package will probably named as slim-search, and source code repo are at https://github.com/Mister-Hope/slimsearch

I already refactor the code, and I will release an initial version once I finish editing docs.

Once I am finished, I hope you can give a reference link at readme about the forked project😉

Mister-Hope commented 1 year ago

Released slimsearch@v0.0.1

Mister-Hope commented 1 year ago

Hi bro, sharing some feedbacks to you. With function-based slimsearch, using loadJsonIndex,search and autoSuggest ONLY at client, the final packed size of package code has be reduced 50% comparing with minisearch.

slimsearch is almost the refine version of minisearch, with only different in apis. 🎉 Since the stringify index is the same, users may use slimsearch as first choice if they are building app with bundlers.

Specially they import a static index to provide search features, which means no new instance, add, replace, discard, remove and vacuum. This should cover around half of the use cases