evanw/esbuild

Entry file's export isn't exported

ravener opened this issue ยท 3 comments

Using ES6 Modules with main.js

import lib from "./lib.js"

console.log(lib());

export default () => "main";

lib.js

export default () => "Hello, World!";

Using command esbuild --bundle --outfile=bundle.js main.js

Then loading the bundle.js file in Node.js i see the Hello World being printed so lib.js got imported successfully however the main.js also exported a function that i cannot use from Node.js it should've been exported. Cannot reproduce this with rollup.

(Another comment: the bundle is pretty big compared to what rollup produces for the code i mentioned do we really need all that stuff?)

@evanw any ideas about this? I also can't use react with multiple files it generates broken code for the importing logic.

evanw commented

the main.js also exported a function that i cannot use from Node.js it should've been exported.

The reason why this wasn't working before was because esbuild actually generated output in the IIFE (immediately-invoked function expression) format, not the CommonJS format that node uses, since I've been focusing on running code in the browser.

I added a new --format flag to control the output format and added support for the CommonJS output format. You can enable that with --format=cjs. However, if you want this to run in node you'll probably want to use --platform=node which automatically implies --format=cjs. Bundling with --platform=node enables referencing builtin node libraries and if you use any node modules that have both browser and node variants, switches esbuild over to bundling the node variants.

(Another comment: the bundle is pretty big compared to what rollup produces for the code i mentioned do we really need all that stuff?)

I assume you're talking about the extra module loading code esbuild sticks at the top. No, that stuff isn't necessarily needed. I'm trying to have esbuild support bundling both ES6 and CommonJS modules instead of something like Rollup, which only natively supports ES6 modules. That extra stuff is for CommonJS support.

I'm working towards a state where that extra stuff is stripped out when it's not needed. Believe me, it bugs me too. But I haven't yet done the additional work to detect when it's not needed and strip it away. I'll definitely get to this at some point.

(Mostly as a reminder for me later) I recently made some progress towards this state by rearranging how the bundle is structured so that helper code is now in multiple top-level functions instead of in a single multi-purpose function nested inside a closure. The next step is to detect which of those helper functions are unused and strip the unused ones away, which will only leave the ones that are actually needed, if any. I also need to detect if all code reachable from the entry point is valid ES6 and, if so, skip embedding the code inside a CommonJS module map.

I tried --platform=node and didn't work but explicit --format=cjs did the job, thanks!