evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
37.93k stars 1.13k forks source link

Using sqlite3 with esbuild #2674

Closed MohrJonas closed 1 year ago

MohrJonas commented 1 year ago

I'm trying to use sqlite3 with esbuild in my Obsidian plugin. The problem, however is, that sqlite3 can't find the native .node file

Any help would be appreciated. Thanks

evanw commented 1 year ago

If you are bundling a library that doesn’t work with bundlers, it should omit that library from the bundle using the external feature.

MohrJonas commented 1 year ago

Thank you very much for your reply. Alright, so I tried marking sqlite3 as external (here's my esbuild):

import esbuild from "esbuild";
import process from "process";
import builtins from "builtin-modules";
import inlineWorkerPlugin from 'esbuild-plugin-inline-worker';

const banner =
`/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
`;

const prod = (process.argv[2] === "production");

esbuild.build({
    banner: {
        js: banner,
    },
    entryPoints: ["src/Main.ts"],
    bundle: true,
    external: [
        "obsidian",
        "electron",
        "@codemirror/autocomplete",
        "@codemirror/closebrackets",
        "@codemirror/collab",
        "@codemirror/commands",
        "@codemirror/comment",
        "@codemirror/fold",
        "@codemirror/gutter",
        "@codemirror/highlight",
        "@codemirror/history",
        "@codemirror/language",
        "@codemirror/lint",
        "@codemirror/matchbrackets",
        "@codemirror/panel",
        "@codemirror/rangeset",
        "@codemirror/rectangular-selection",
        "@codemirror/search",
        "@codemirror/state",
        "@codemirror/stream-parser",
        "@codemirror/text",
        "@codemirror/tooltip",
        "@codemirror/view",
        "@lezer/common",
        "@lezer/highlight",
        "@lezer/lr",
        "node:fs",
        "node:process",
        "node:path",
        "node:url",
        "node:stream",
        "browser/Terminal",
        "sqlite3",
        ...builtins],
    format: "cjs",
    watch: !prod,
    target: "es2016",
    logLevel: "info",
    sourcemap: prod ? false : "inline",
    treeShaking: true,
    outfile: "main.js",
    plugins: [inlineWorkerPlugin()]
}).catch(() => process.exit(1));

Now the program complains that it can't find the sqlite3 module (which makes sense, because it's now excluded). Therefore, I assume that I have to load the module some other way now? Here is the relevant piece of my code (if it helps):

import {Database} from "sqlite3";

export default class ObsidianOCRPlugin extends Plugin {
    [...]
    override async onload() {
        const db = new Database(":memory:");
        db.close();
        [...]
    }
[...]   
}

Thanks again.

evanw commented 1 year ago

Therefore, I assume that I have to load the module some other way now?

Yes the sqlite3 module still needs to be installed and present on the file system alongside your bundle so that the node runtime environment can find it when it encounters require('sqlite3'). It's up to you to ensure that this is the case.