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 __export function handle 「lodash-es/debounce」 module wrap with an additional function #1477

Closed
Ezrealzbb opened this issue Jul 28, 2021 · 5 comments

Comments

@Ezrealzbb
Copy link

Ezrealzbb commented Jul 28, 2021

Context

This is a npm package A peerDependency with「lodash-es」package;there is inner source code:

// tracker.ts
import { debounce } from 'lodash-es';
class ImageTracker {
  collectResolvedImagesInfoBatchly: any = debounce(this.collectResolvedImagesInfo, 3000);
  collectResolvedImagesInfo() {}
}
export const docImageTracker = new ImageTracker(ImageType.DOC_IMAGE);

// index.ts
import * as packageA from 'A';

function test() {
  console.log(packageA);
}

test();

we use esbuild:./node_modules/.bin/esbuild index.ts --bundle --outfile=out.js

we can find the code in out.js

  // node_modules/lodash-es/debounce.js
  var debounce_exports = {};
  __export(debounce_exports, {
    // notice: there is a function which wraps the debounce_default variable
    default: () => debounce_default // code #1
  });
  function debounce(func, wait, options) {}
  var init_debounce = __esm({
    "node_modules/lodash-es/debounce.js"() {
      init_isObject();
      init_now();
      init_toNumber();
      FUNC_ERROR_TEXT2 = "Expected a function";
      nativeMax = Math.max;
      nativeMin = Math.min;
      debounce_default = debounce;
    }
  });

// node_modules/A.umd.js
var require_sheet_common_umd = __commonJS({
    "node_modules/A.umd.js"(exports2, module2) {  (init_debounce(), debounce_exports)

Object.defineProperty(t2, "__esModule", { value: true }), t2.driveImageTracker = t2.docImageTracker = void 0;
          var r2, o2, i2, a2 = n2(156), c2 = (r2 = a2) && r2.__esModule ? r2 : { default: r2 }, u2 = n2(0);
 // source code had been transformed as
  this.collectResolvedImagesInfoBatchly = (0, c2.default)(this.collectResolvedImagesInfo, 3e3) // code #2

 }

package A is an umd bundle by webpack4。the out.js can be upload together in this issue;

problem:

the value of c2 in runtime is { default: { default: funtion debounce } }code #2 throw an error :(0 , c2.default) is not a function;

question

  1. why code#1 use another function wrap debounce_default?
  2. Could lodash-es/debounce module definition add an __esModule flag in code#1?

expected

the value of c2 in runtime to be { default: funtion debounce() {} }。or __export code#1 width __esModule

Thanks ~

outjs.zip

@Ezrealzbb
Copy link
Author

I use package alias:"lodash-es": "npm:lodash@4.17.21", in package.json,it's works。but why?

@evanw
Copy link
Owner

evanw commented Jul 28, 2021

why code#1 use another function wrap debounce_default?

I'm not sure I understand what you're saying. But __export exists to make sure the export is read-only (as required by the JavaScript specification) and the __esm wrapper exists to allow that module to be lazily-evaluated. You haven't posted enough code to be able to understand why this lazy evaluation is needed but it's likely because that module was imported using require() instead of import, which means the import happens at run-time instead of at compile-time. In that case lazy evaluation is needed.

  1. Could lodash-es/debounce module definition add an __esModule flag in code#1?

What version of esbuild are you using? Any chance this has already been fixed by #1338? The __esModule flag has already been added in version 0.12.7 of esbuild.

@Ezrealzbb
Copy link
Author

Ezrealzbb commented Jul 29, 2021

Thank for your reply.

You haven't posted enough code to be able to understand why this lazy evaluation is needed but it's likely because that module was imported using require() instead of import

source code is very simple. debounce module imported by import syntax;

// tracker.ts  is an es module
import { debounce } from 'lodash-es';
class ImageTracker {
  collectResolvedImagesInfoBatchly: any = debounce(this.collectResolvedImagesInfo, 3000);
  collectResolvedImagesInfo() {}
}
export const docImageTracker = new ImageTracker(ImageType.DOC_IMAGE);

which means the import happens at run-time instead of at compile-time. In that case lazy evaluation is needed.

Your words remind me that peerDeependcy will not package lodash-es into a product bundle directly. May I think like this: The output umd bundle loads lodash-es/debounce by require() syntax and then esbuild recognizes lodash-es/debounce as a cjs require,uses __export to load code?

image

What version of esbuild are you using? Any chance this has already been fixed by #1338? The __esModule flag has already been added in version 0.12.7 of esbuild.

My esbuild version is 0.12.16. The issue of #1338 is same to me, but it has no __esModel flag in output code. cc @lbwa

image

@lbwa
Copy link
Contributor

lbwa commented Jul 29, 2021

As evan said, we need enough code to figure out what's going on. Please provide a complete and minimal reproduce repo, instead of code snippets.

@Ezrealzbb
Copy link
Author

Ezrealzbb commented Jul 29, 2021

As evan said, we need enough code to figure out what's going on. Please provide a complete and minimal reproduce repo, instead of code snippets.

Sorry I cant provide a complete code becouse it used private npm package within the company. But I check the esbuild version again. it's throw problem with 0.11.5. It works when upgrading to 0.12.16.thanks.

there is no question and the issue can be closed.

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

3 participants