Open Akryum opened 2 years ago
I’m also having ESM issues in a Gatsby app:
// eslint error: Worker not found in 'flexsearch'
import { Worker } from "flexsearch";
// Build error: WebpackError: TypeError: flexsearch__WEBPACK_IMPORTED_MODULE_3__.Worker is not a constructor
const searchWorker = new Worker({ preset: "match" });
The weird thing is, Worker does exist in dev mode, and it’s a function. So there may be something going on during the build step with Webpack and this package’s module configuration.
I’ve tried pinning to 0.7.21
and 0.6
, and that didn’t help. I also tried various other import types, including:
import FlexSearch from "flexsearch"; // or…
import * as FlexSearch from "flexsearch"; // or…
const FlexSearch = require("flexsearch");
const { Worker } = FlexSearch;
and they all have the same problem.
EDIT
I had some success by preventing new Worker
from being called during SSR. Rather than creating searchWorker
in the module body as shown above, I created it from within a componentDidMount
-like hook as shown below:
import { Worker } from "flexsearch";
export default function ExampleComponent () {
const searchWorker = useRef(null);
useEffect(() => {
searchWorker.current = new Worker({ preset: "match" });
}, []);
<div>
<button onClick={() => searchWorker.current?.add("id", "value")}>Example</button>
</div>
}
I'm having the same issue.. how to import Index as an ESM module?
I'm using
import Index from "flexsearch/dist/module/index.js";
but on build I'm receiving using vite to create the bundle..
(node:10776) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use node --trace-warnings ...
to show where the warning was created)
build error:
C:\Users\emers\Source\Repos\mermaid-docs\node_modules.pnpm\flexsearch@0.7.31\node_modules\flexsearch\dist\module\index.js:1
import{SUPPORT_ENCODER,SUPPORT_CACHE,SUPPORT_ASYNC,SUPPORT_SUGGESTION,SUPPORT_SERIALIZE}from"./config.js";import{IndexInterface}from"./type.js";import{encode as default_encoder}from"./lang/latin/default.js";import{create_object,create_object_array,concat,sort_by_length_down,is_array,is_string,is_object,parse_option}from"./common.js";import{pipeline,init_stemmer_or_matcher,init_filter}from"./lang.js";import{global_lang,global_charset}from"./global.js";import apply_async from"./async.js";import{intersect}from"./intersect.js";import Cache,{searchCache}from"./cache.js";import apply_preset from"./preset.js";import{exportIndex,importIndex}from"./serialize.js";function Index(a,b){if(!(this instanceof Index))return new Index(a);let c,d,e;a?(SUPPORT_ENCODER&&(a=apply_preset(a)),c=a.charset,d=a.lang,is_string(c)&&(-1===c.indexOf(":")&&(c+=":default"),c=global_charset[c]),is_string(d)&&(d=global_lang[d])):a={};let f,g,h=a.context||{};this.encode=a.encode||c&&c.encode||default_encoder,this.register=b||create_object(),this.resolution=f=a.resolution||9,this.tokenize=e=c&&c.tokenize||a.tokenize||"strict",this.depth="strict"===e&&h.depth,this.bidirectional=parse_option(h.bidirectional,!0),this.optimize=g=parse_option(a.optimize,!0),this.fastupdate=parse_option(a.fastupdate,!0),this.minlength=a.minlength||1,this.boost=a.boost,this.map=g?create_object_array(f):create_object(),this.resolution_ctx=f=h.resolution||1,this.ctx=g?create_object_array(f):create_object(),this.rtl=c&&c.rtl||a.rtl,this.matcher=(e=a.matcher||d&&d.matcher)&&init_stemmer_or_matcher(e,!1),this.stemmer=(e=a.stemmer||d&&d.stemmer)&&init_stemmer_or_matcher(e,!0),this.filter=(e=a.filter||d&&d.filter)&&init_filter(e),SUPPORT_CACHE&&(this.cache=(e=a.cache)&&new Cache(e))}export default Index;Index.prototype.append=function(a,b){return this.add(a,b,!0)},Index.prototype.add=function(a,b,c,d){if(b&&(a||0===a)){if(!d&&!c&&this.register[a])return this.update(a,b);b=this.encode(""+b);const e=b.length;if(e){const d=create_object(),f=create_object(),g=this.depth,h=this.resolution;for(let j=0;j<e;j++){let i=b[this.rtl?e-1-j:j],k=i.length;if(i&&k>=this.minlength&&(g||!f[i])){let l=get_score(h,e,j),m="";switch(this.tokenize){case"full":if(2<k){for(let b=0;b<k;b++)for(let d=k;d>b;d--)if(d-b>=this.minlength){const g=get_score(h,e,j,k,b);m=i.substring(b,d),this.push_index(f,m,g,a,c)}break}case"reverse":if(1<k){for(let b=k-1;0<b;b--)if(m=i[b]+m,m.length>=this.minlength){const d=get_score(h,e,j,k,b);this.push_index(f,m,d,a,c)}m=""}case"forward":if(1<k){for(let b=0;b<k;b++)m+=i[b],m.length>=this.minlength&&this.push_index(f,m,l,a,c);break}default:if(this.boost&&(l=Math.min(0|l/this.boost(b,i,j),h-1)),this.push_index(f,i,l,a,c),g&&1<e&&j<e-1){const f=create_object(),h=this.resolution_ctx,k=i,l=Math.min(g+1,e-j);f[k]=1;for(let g=1;g<l;g++)if(i=b[this.rtl?e-1-j-g:j+g],i&&i.length>=this.minlength&&!f[i]){f[i]=1;const b=get_score(h+(e/2>h?0:1),e,j,l-1,g-1),m=this.bidirectional&&i>k;this.push_index(d,m?k:i,b,a,c,m?i:k)}}}}}this.fastupdate||(this.register[a]=1)}}return this};function get_score(a,b,c,d,e){return c&&1<a?b+(d||0)<=a?c+(e||0):0|(a-1)/(b+(d||0))*(c+(e||0))+1:0}Index.prototype.push_index=function(a,b,c,d,e,f){let g=f?this.ctx:this.map;if((!a[b]||f&&!a[b][f])&&(this.optimize&&(g=g[c]),f?(a=a[b]||(a[b]=create_object()),a[f]=1,g=g[f]||(g[f]=create_object())):a[b]=1,g=g[b]||(g[b]=[]),this.optimize||(g=g[c]||(g[c]=[])),(!e||!g.includes(d))&&(g[g.length]=d,this.fastupdate))){const a=this.register[d]||(this.register[d]=[]);a[a.length]=g}},Index.prototype.search=function(a,b,c){c||(!b&&is_object(a)?(c=a,a=c.query):is_object(b)&&(c=b));let d,e,f,g=[],h=0;if(c&&(a=c.query||a,b=c.limit,h=c.offset||0,e=c.context,f=SUPPORT_SUGGESTION&&c.suggest),a&&(a=this.encode(""+a),d=f(!e){e=Math.min(a.length,c);for(let g,h=0;h<e;h++)g=a[h],g&&(f=remove_index(g,b,c,d,e),!d&&!f&&delete a[h])}else{const c=a.indexOf(b);-1===c?f++:1<a.length&&(a.splice(c,1),f++)}return f}SUPPORT_CACHE&&(Index.prototype.searchCache=searchCache),SUPPORT_SERIALIZE&&(Index.prototype.export=exportIndex,Index.prototype.import=importIndex),SUPPORT_ASYNC&&apply_async(Index.prototype);^^^^^^
If I add type: module manuanly in the package.json inside node modules it does work.
{
"name": "flexsearch",
"version": "0.7.31",
"type": "module",
...
}
Not sure if this answers your questions, but this is how I import for example Document
in an ESM project:
import pkg from "flexsearch";
const { Document } = pkg;
it also brakes when I try to build.
@ts-thomas would replacing google-closure-compiler
with something else potentially solve the problem?
If you think yes, I can look into how to do it... I had some other problem with google-closure-compiler
not being able to compile because of some java version mismatch on OSX...
so if replacing this with something else would solve two issues at once, I'm willing to invest some time,let me know
maybe some more modern tool can replace both webpack
and google-closure-compiler
...
also is Babel needed at all? It is also obsolete, I believe
It doesn't work for me either, I couldn't succeed somehow
Thanks for publishing this! @ts-thomas, do you think any of @Akryum’s changes could find their way upstream?
I am getting FlexSearch.create is not a function
error on vite
const searchIndex = FlexSearch.create({
encode: "icase",
tokenize: "forward",
cache: true,
doc: {
id: "path",
field: ["name", "content"],
},
});
@Tasin5541 The code doesn't export a create
function (the documentation and types seem to be wrong).
@ts-thomas do you plan to support ESM? At this point, it seems the package isn't usable with most of the modern web frameworks if ESM is not a supported environment, unless I'm missing something.
EDIT: Apparently the following imports do work, at least in a Vite + Svelte project I'm working on:
import Index from "flexsearch/dist/module";
import Worker from "flexsearch/dist/module/worker";
import Document from "flexsearch/dist/module/document";
EDIT 2: I've created a PR #398 that updates the docs to explain how to import the ESM modules.
I had a hard time to make it running in a Typescript project, but importing the modules from src
surprisingly worked:
import Document from "flexsearch/src/document";
interface IndexedDocument {
id: string;
firstName: string;
lastName: string;
}
const docIndex = new Document<IndexedDocument, true>({
document: {
id: "id",
index: [ "firstName", "lastName" ],
store: true,
},
});
I'm not able to use the latest version (0.7.31) in an ESM environment, such as a Vite app (browser-side) or a native-ESM node app (with TypeScript). The document doesn't also doesn't have anything about this.
The situation was a little bit better in version 0.7.21 with imports like this:
Vite:
Node ESM:
(Notice we need a module loader such as jiti or vite-node to be able to load other files which are not marked as ESM).