esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

[lexical][prism] The code seems to have been incorrectly elevated while minimizing

Open wszgrcy opened this issue 1 year ago • 2 comments

version: 0.21.5 I built it using Angular CLI Import Lexical package Everything is normal during development But there were problems with the packaging during production Finally, it was found that the position of the prism code introduced by Lexical was different from that during development During development:

image

During production: image image image

wszgrcy avatar Jul 28 '24 08:07 wszgrcy

demo: https://github.com/wszgrcy/angular-lexical-build-error

wszgrcy avatar Jul 28 '24 09:07 wszgrcy

This minimal case to trigger this error is when esbuild bundles @lexical/code and hits its weird dual export entry with --minify (which means defining process.env.NODE_ENV="production"):

// node_modules/@lexical/code/LexicalCode.mjs
import * as modDev from './LexicalCode.dev.mjs';
import * as modProd from './LexicalCode.prod.mjs';
const mod = process.env.NODE_ENV === 'development' ? modDev : modProd;
export const $createCodeHighlightNode = mod.$createCodeHighlightNode;
// ...

So the reprodcution without angular cli could be like this:

// entry.js
import {CodeHighlightNode} '@lexical/code'
console.log(CodeHighlightNode)
$ esbuild entry.js --bundle --outdir=dist --define:process.env.NODE_ENV=\"production\"

Playground Link

I'm not quite sure what happened here, but here are some guesses:

  • import * as ns in esbuild will make the depended module be wrapped with a namespace object, generating something like __export(prod_exports, { foo: () => foo }) and var import_prism = __toESM(require_prism()).
  • The prism module is identified as a CJS module because it has module.exports = statement. The prism/plugin module is identified as an ESM module.
  • The var import_prism = __toESM(require_prism()) statement is delayed to where it was actually depended because CJS modules need preserving execution order, which is at the prod entry.
  • import 'prismjs/components/prism-javascript.js';, does not say it is depending on the 'prism' module, and is occured both in the dev and prod entry. So it is lift up as a shared dependency. Although internally it is actually depending on the execution order of 'prism' to run first. So here 'prismjs/components/prism-javascript.js' is lift up before 'prism', causing the error.

To solve this error, at least as a workaround, is to set --conditions in esbuild options to select the prod entry file directly without touching the weird dual entry. I don't know if angular has the place to put this option but, here it is:

esbuild.build({
  conditions: ['production']
})

hyrious avatar Jul 28 '24 11:07 hyrious

Thanks for the excellent investigation above. I'm closing this issue as it sort of sounds like a problem with the package. Specifically it sounds like prism/plugin is missing a dependency on prism. I'm glad it seems like there is a suitable workaround in this case.

evanw avatar Sep 22 '24 01:09 evanw