thi-ng / umbrella

⛱ Broadly scoped ecosystem & mono-repository of 199 TypeScript projects (and ~180 examples) for general purpose, functional, data driven development
https://thi.ng
Apache License 2.0
3.41k stars 151 forks source link

[rstream] in the web worker scope #425

Closed bit-app-3000 closed 1 year ago

bit-app-3000 commented 1 year ago

worker.js (esm) esbuild


import { fromIterable, trace } from '@thi.ng/rstream'

self.onmessage = function ({data}){
  fromIterable([1,3]).subscribe(trace('worker'))
}

|>  unhandled error: undefined
postspectacular commented 1 year ago

I don't know enough about your project setup, but I've not once run into any issues with using any of the packages in a worker. There's no reliance on any globals, so my guess this is a config issue with esbuild (sorry, no 1st hand experience with it, only via Vite). Can you please put up a small project somewhere for debugging/reproduction?

postspectacular commented 1 year ago

@bit-app-3000 After a lot of digging, I found that esbuild does not support standard ESM import.meta look ups. This hasn't anything to do directly with thi.ng/rstream, but is required by the widely used assert() function of thi.ng/errors. To have esbuild deal with import.meta properly, we can write a little build plugin:

Plugin:

// plugin-import-meta-env.js

import { readFileSync } from "fs";

export default (prefixes = []) => ({
    name: "import.meta.env",
    setup({ onLoad }) {
        // only collect & expose selected (deemed safe!) env vars
        const env = { MODE: process.env.NODE_ENV };
        if (prefixes.length) {
            for (let k of Object.keys(process.env)) {
                if (prefixes.some((prefix) => k.startsWith(prefix))) {
                    env[k] = process.env[k];
                }
            }
        }
        const envFmt = `(${JSON.stringify(env)})`;
        // plugin hook (only apply to JS/TS files)
        onLoad({ filter: /\.[jt]sx?$/, namespace: "file" }, (args) => {
            const code = readFileSync(args.path, "utf8").replace(
                /\bimport\.meta\.env\b/g,
                envFmt
            );
            return { contents: code };
        });
    },
});

Then use a esbuild build script:

import { build } from "esbuild";
import pluginImportMetaEnv from "./plugin-import-meta-env.js";

await build({
    entryPoints: ["src/app.js", "src/store.js"],
    bundle: true,
    minify: true,
    outdir: "build",
    // can skip the looking for custom UMBRELLA prefix if you're just after using default behavior
    plugins: [pluginImportMetaEnv(["UMBRELLA_"])],
});

...and build via: node build.js

I've pushed some new releases (incl. the above linked commits), so also make sure to update your dependencies, just in case...

bit-app-3000 commented 1 year ago

thx for the help


found another workaround

--define:import.meta.env={}

can there be pitfalls?
postspectacular commented 1 year ago

Cool. Good to know...