Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage in ESM environment #341

Open
Akryum opened this issue Oct 10, 2022 · 14 comments
Open

Usage in ESM environment #341

Akryum opened this issue Oct 10, 2022 · 14 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@Akryum
Copy link

Akryum commented Oct 10, 2022

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:

import * as flexsearch from 'flexsearch'
import charset from 'flexsearch/dist/module/lang/latin/advanced.js'
import language from 'flexsearch/dist/module/lang/en.js'

Node ESM:

import flexsearch from 'flexsearch'

const flexsearchRoot = path.dirname(require.resolve('flexsearch/package.json'))
  return new flexsearch.Document({
    preset: 'match',
    document: {
      id: 'id',
      index: [
        'text',
      ],
    },
    charset: await loadModule(`${flexsearchRoot}/dist/module/lang/latin/advanced.js`),
    language: await loadModule(`${flexsearchRoot}/dist/module/lang/en.js`),
    tokenize: 'forward',
  })

(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).

@rileyjshaw
Copy link

rileyjshaw commented Oct 25, 2022

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>
}

@emersonbottero
Copy link

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\[email protected]\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);^^^^^^

@emersonbottero
Copy link

If I add
type: module
manuanly in the package.json inside node modules it does work.

{
  "name": "flexsearch",
  "version": "0.7.31",
  "type": "module",
  ...
}

@schalkneethling
Copy link

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;

@emersonbottero
Copy link

it also brakes when I try to build.

@ts-thomas ts-thomas added bug Something isn't working help wanted Extra attention is needed labels Nov 4, 2022
@davidhq
Copy link

davidhq commented Dec 8, 2022

@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

@davidhq
Copy link

davidhq commented Dec 8, 2022

  • and webpack as well...

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

@productdevbook
Copy link

It doesn't work for me either, I couldn't succeed somehow

@Akryum
Copy link
Author

Akryum commented Mar 9, 2023

https://github.com/Akryum/flexsearch-es

@rileyjshaw
Copy link

https://github.com/Akryum/flexsearch-es

Thanks for publishing this! @ts-thomas, do you think any of @Akryum’s changes could find their way upstream?

@Tasin5541
Copy link

https://github.com/Akryum/flexsearch-es

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"],
  },
});

@Akryum
Copy link
Author

Akryum commented Mar 17, 2023

@Tasin5541 The code doesn't export a create function (the documentation and types seem to be wrong).

@danawoodman
Copy link
Contributor

danawoodman commented Jul 18, 2023

@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.

danawoodman added a commit to danawoodman/flexsearch that referenced this issue Jul 18, 2023
The existing docs show a relative path, not the actual npm module bundle path.

I believe this should be correct for ESM/ES6 type environments and will hopefully prevent confusion as found in nextapps-de#341 etc.
@PlayXman
Copy link

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,
  },
});

null2264 added a commit to null2264/Ghostbox that referenced this issue Sep 24, 2023
null2264 added a commit to null2264/Ghostbox that referenced this issue Sep 27, 2023
* chore: Initial vite migration

* lint: Fix vite eslint

* chore: Migrate HtmlWebpackPlugin

* chore: Migrate CopyPlugin

* chore: Replace webpack script with vite

* ci: Trigger for refactor/ branches

* fix: Snippets

* chore: Rename index.ejs -> index.html

* ci: `static/` -> `dist/`

* chore: Migrate ServiceWorker to Vite

* chore: Import locales at compile time

* chore: Exported locales should contain `data` property

* chore: Register SW

* ci: Keep it `static/`

* refactor: Set output dir from vite config

* chore: Add `require(...)` support back

* feat: Resolve and stuff

* fix: Move index.html

* fix: Resolve ambigous import

* fix: Browserify path

* chore: Remove crypto related stuff
I don't do crypto

* fix: Use `@akryum/flexsearch-es`

REF: nextapps-de/flexsearch#341

* fix: webpack -> vite-ignore

* fix: Vite env

* chore: Ignore some vite temp files

* revert: Vite env

* revert: Vite env

* chore: More vite env stuff

* fix: CSP
Imported CSS still doesn't work

* fix: Entrypoint shouldn't be a relative path

* fix: Adjust initial nonce

* chore: TS Checker

* fix: Adjust eslintignore

* lint: Adjust eslintignore

* fix: Adjust lint command

* chore: Disable eslint checker for now
For some reason it keep ignoring eslintignore (ironic)

* chore: It's actually ts checker that keep checking node_modules

* fix: lint command

* chore: Disable stylelint

* fix: Yarn can't be used for lint command

* chore: Temporarily disable eslint

* fix: CSP in dev mode

* chore: CSP adjustment
CSP may or may not be fine on prod... we'll see...

* fix: Slight adjustment

* fix: CSP forr vite-plugin-checker

* fix: Resolve warnings

* fix: More warning fixing

* fix: Yet another warning fixes

* fix: SW typing

* fix: It's webworker not dom

* chore: Remove webpack

* chore: Disable eslint and stylelint

* fix: Hopefully one last error fix

* chore: Update immer to v10

* fix: Regex

* chore: Update more deps

* chore: Downgrade toast to v2.4.0

* chore: Remove dangerfile

* fix: Dynamic locale import

* fix: Try use __webpack_nonce__ just in case

* fix: vite-plugin-require

* revert: Revert "fix: vite-plugin-require"

This reverts commit 7c4e15f.

* chore: Remove keymap temporarily

* fix: Goober

* fix: nonce

* chore: Temporarily disable hotkey

* fix: Properly null check textarea

* fix: NODE_ENV
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

10 participants