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

Why put block level requires to global scope? #1352

Closed
jeffRTC opened this issue Jun 4, 2021 · 4 comments
Closed

Why put block level requires to global scope? #1352

jeffRTC opened this issue Jun 4, 2021 · 4 comments

Comments

@jeffRTC
Copy link

jeffRTC commented Jun 4, 2021

So,

I have a function like this,

async function foo() {
   const bar = require("some_lib");
   
   bar.print();
}

After bundling, the whole thing transforms into this,

var __require = (x) => {
    if (typeof require !== "undefined")
      return require(x);
    throw new Error('Dynamic require of "' + x + '" is not supported');
};

var __commonJS = (cb, mod) => function __require2() {
   return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};

var require_some_lib = __commonJS({});

async function foo() {
   const bar = require_some_lib();
   
   bar.print();
}

This is problematic because I serialize the function foo() at runtime and put it inside a web worker and when it runs at web worker, require_some_lib and it's dependencies like __commonJS , __require are undefined.

Is there an option to get the bundle output something like this?

async function foo() {
    var __require = (x) => {
        if (typeof require !== "undefined")
            return require(x);
        throw new Error('Dynamic require of "' + x + '" is not supported');
    };

    var __commonJS = (cb, mod) => function __require2() {
        return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
    };

    var require_some_lib = __commonJS({});
    const bar = require_some_lib();

    bar.print();
}
@evanw
Copy link
Owner

evanw commented Jun 5, 2021

Doing what you proposed (injecting a separate copy of the helper function library into every single function that uses them) would be very undesirable. It would likely cause a huge increase in code size and would make the generated code run slower as the JIT would process each copy of every helper function separately.

I can think of two ways of doing what you want:

  • You can build the web worker to a string, then embed that string in your app. This is the most reasonable approach because it won't break when your source code is processed by other JavaScript tools, since other tools will also do what esbuild is doing here (e.g. Babel transforms).

  • You can build the web worker to a string and then insert that source code inside a function wrapper. You can either do that manually or use esbuild's banner and footer features for this such as esbuild --bundle your-code.js "--banner:js=async function foo(){" --footer:js=}. The resulting code will still be vulnerable to issues when processed by other JavaScript tools, however, since most tools assume that you won't be extracting substrings of the code and trying to run them in a separate VM.

@jeffRTC
Copy link
Author

jeffRTC commented Jun 5, 2021

Code size and performance is not an issue for me. I want this just for a single function but fine if it get injected to every.

So, I assume currently there is no option built in for this?

@evanw
Copy link
Owner

evanw commented Jun 5, 2021

No there isn't one option for this but the banner and footer options make doing this trivial.

@jeffRTC
Copy link
Author

jeffRTC commented Jun 5, 2021

@evanw

Found this issue,

#312

Would be great if you can add worker bundling with in-line support so this issue automatically solves

@jeffRTC jeffRTC closed this as completed Jun 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants