Open tracker1 opened 4 years ago
@pft Dynamic imports:
var { "x-y": x_y } = await import("./b.mjs")
console.log(x_y)
@hyrious Wow. And, just for completeness sake, this works too:
import("./a.js").then(({"x-y": x_y}) => console.log(x_y));
@pablo-mayrgundter You need to use a newer target which supports dynamic import (import()
), simply edit that field to esnext
or something else.
@evanw i have a different use-case from above, i have this dynamic import
const getIcon = (name) => {
return lazy(() => import(`./icons/${name}`));
};
problem is that esbuild is bundling all the icons into the index.js file rather than keeping them in a separate file. is it possible to say this should stay as it is.
Trying to track down a recent update on "Code splitting is still a work in progress. It currently only works with the esm output format. There is also a known ordering issue with import statements across code splitting chunks."
Is a fix for these issues planned?
I switched to code splitting on dynamic imports but now I've come across a strange bug, has anyone seen this before?
const { parse } = await import('css-what')
parse(selector)
css-what
has both ESM and CJS code internally as well as both main
and module
package.json entries pointing to the relevant file, but for some reason esbuild is using the CJS code instead of ESM. When I edit the package.json and point main
to the same place as module
, the code starts working again.
I don't think this is a bug with css-what
, but I could be wrong
@mattfysh If you're using node.js to run this code, then this is because node.js ignores the module
field. More details at doc: main-fields. You can import the ESM file directly with:
import {parse} from "css-what/lib/es/index.js"
If you're using esbuild to bundle the code with --platform=node
, the reason is the same because esbuild is trying to behave the same as node.js. You can try to add --main-fields=module,main
to your build script.
For package authors: If you really want users to use the native ESM way to use your package, at least do this:
"exports": {
"node": {
"import": "./dist/index.mjs",
"require": "./dist/index.js"
},
"default": "./dist/index.mjs"
}
More details at doc: how-conditions-work.
thanks @hyrious - the fix for my case was to use the --main-fields
flag, thanks! One other thing I've noticed is the size of my output directory is much larger, I'm guessing that no tree shaking occurs when using code splitting and dynamic imports?
Is there any way to control the code-splitting to only look at async/dynamic imports?
If you bundle each entry point separately, then entry points won’t share any code.
If you bundle each entry point separately, then entry points won’t share any code.
Not sure I fully understand that, but I tried setting up separate entry points for a couple of my dynamic import()
calls and the main entry point still fully bundled everything, and then it created separate bundles for those imports (but they weren't used).
And if I try to use splitting
then I still get WAY too many spit files
cjs can also use import(path)
inside, so I'm wondering why splitting can only been enabled with esm format, I'm saying that even with cjs format output option, the dynamic chunks can still be esm. Of course, correct extensions (.cjs
vs .mjs
) should be applied in this case.
@evanw
If you bundle each entry point separately, then entry points won’t share any code.
And if I try to use
splitting
then I still get WAY too many spit files
One important caveat is that if you're importing entry points dynamically, you need to make sure that they are marked as external.
For example, if →
indicate dynamic imports, and your entry points are A, D & C:
A → B → C
D → C
C
You would need to make sure that your onResolve
callbacks marks dynamic imports of A, D & C as external.
Is this still WIP?
Initially meant to be posted here https://github.com/evanw/esbuild/issues/1341
In my case, I needed to bundle dependencies and chunk them, while keeping the output files separate (not one big bundle). All that works except that only format: 'esm'
is currently supported, so I wrote a plugin to transpile to CJS again :upside_down_face:.
Definitely not ideal, I can live with it.
export const esmSplitCodeToCjs: esbuild.Plugin = {
name: 'esmSplitCodeToCjs',
setup(build) {
build.onEnd(async (result) => {
const outFiles = Object.keys(result.metafile?.outputs ?? {})
const jsFiles = outFiles.filter((f) => f.endsWith('js'))
await esbuild.build({
outdir: build.initialOptions.outdir,
entryPoints: jsFiles,
allowOverwrite: true,
format: 'cjs',
logLevel: 'error',
})
})
},
}
If you bundle each entry point separately, then entry points won’t share any code.
Not sure I fully understand that, but I tried setting up separate entry points for a couple of my dynamic
import()
calls and the main entry point still fully bundled everything, and then it created separate bundles for those imports (but they weren't used).And if I try to use
splitting
then I still get WAY too many spit files
I have the same issue. It splits import
s but would only like to split dynamic import()
. Any luck?
@evanw whats the current status on enabling code splitting with cjs
format?
@evanw whats the current status on enabling code splitting with cjs format?
Use tsup
IMO this issue can be closes as not planned
IMO this issue can be closes as not planned
Safari added full ES module support with Safari 11, released sep 2017. When the issue was opened in 2020, safari 10.x probably was inside the support matrix for quite a few users (it still was for us. way too many iMac users back then stuck on that version reporting issues)
But shouldn't almost everyone be able to switch to ES Modules in their pipelines by now? I'd think there are much more interesting issues in esbuild to solve than 'backporting' split support to CJS
Support code splitting on dynamic import() statements, and additionally split/join on shared bundles for shared dependency models.