Open CSchulz opened 2 years ago
It looks like you're bundling your ESM code into CommonJS (or IIFE), but with "lodash-es" being externalized. (i.e. esbuild index.mjs --bundle --format=cjs --external:lodash-es
) There are a few problems:
import
to require
calls to external modules.require()
is not allowed in any environment.{ default: module }
, you can find more details in issues you've mentioned above.The simplest workaround is do not externalize lodash-es, just remove it from your extenral
settings.
I am not sure if I can match all your arguments with the call I have found in the jest preset:
esbuild.transformSync(fileContent, {
loader: 'js',
format: 'cjs',
target: 'es2016',
sourcemap: compilerOpts.sourceMap,
sourcefile: filePath,
sourcesContent: true,
sourceRoot: compilerOpts.sourceRoot,
});
format: 'cjs',
That's the cause. While as I know jest cannot run in ESM mode, so you may not be able to use lodash-es with jest.
We are using it in conjuction with jest-resolve. I was expecting jest-resolve will detect the correct order of the dependencies and will transform first lodash-es before trying to transform / load our library using lodash-es. Is that not true?
i have a question , why this callExpression second parameter is 1 in esbuild output result ? 🤔️
var import_isPlainObject = __toESM(require("lodash-es/isPlainObject"), 1);
As you can see from the source code, the second parameter of __toESM
is called isNodeMode
. Node compatibility mode (including when and why it happens) is documented here: https://esbuild.github.io/content-types/#default-interop.
As you can see from the source code, the second parameter of
__toESM
is calledisNodeMode
. Node compatibility mode (including when and why it happens) is documented here: https://esbuild.github.io/content-types/#default-interop.
i got a issue maybe related isNodeMode
. here is a third dependence entry file in my project, it seem mark as ESM format already.
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(
exports, "__esModule", { value: true });
const Graphemer_1 = __importDefault(require("./Graphemer"));
exports.default = Graphemer_1.default;
here is the output result, the isNodeMode
has been marked as 1
, this will cause __toESM
unexpected working. check the comment in __toESM
below.
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// 🔧 it will hit this branch to define default props again,
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var import_graphemer = __toESM(require_lib(), 1);
// ❌ runtime error
var gaphemer = new import_graphemer.default();
The same problem occurs when using import()
with Angular 17 after building.
It's strange because I didn't encounter this problem while serving locally.
export const exportExcel = () => import('xlsx-js-style').then(xlsx => {})
Workaround:
const safeESModule = <T>(a: T | { default: T }): T => {
const b = a as any;
return b.__esModule || b[Symbol.toStringTag] === 'Module' ? b.default : b;
};
export const exportExcel = () => import('xlsx-js-style').then(safeESModule).then(xlsx => {})
I have this problem when bundling code for the browser and having type: module
set in package.json
.
xstream
) which is built to CommonJS and uses exports.default
.I do:
import xs from 'xstream';
console.log(xs.never());
This fails when running in the browser with never() doesn't exist on undefined
.
Removing type: module
from package.json
fixes this issue, but prevents us from doing ESM on the server.
type: module
for doing native ESM on the server in Node.__toESM
:var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
which in turn messes up the default import of xstream
.
I've scanned the excellent docs and read the explanations in https://esbuild.github.io/content-types/#default-interop, but it feels like I'm between a rock and a hard place: I want ESM on the server, but don't want this to affect esbuild's bundling of client code.
Using @ApplY3D's workaround above worked:
// safe-xstream.ts
import _xs from "xstream";
const safeESModule = <T,>(a: T | { default: T }): T => {
const b = a as any;
return b.__esModule || b[Symbol.toStringTag] === "Module" ? b.default : b;
};
const xs = safeESModule(_xs);
export default xs;
// index.ts
import xs from './safe-xstream';
console.log(xs.never());
I have issues with ESM imports in ESM modules. I am using esbuild@0.13.23 but also esbuild@0.15.5 fails.
I think it could be related to #2384 and #2026.
lodash-es/isPlainObject is a .js file.
Here are the specific file parts:
Original mjs file
esbuild output