-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[Feature] Dynamic import w/ template literals w/ variables #56
Comments
Bundling with esbuild is intended to traverse your whole dependency tree and include all of your dependencies in the bundle. However, it can only do this if the dependency tree is statically analyzable. This is why esbuild requires string literals. Dynamically-computed import paths are not statically analyzable. Can you say more about your use case? What are you using this to try to do? |
Is it possible to extract all the dynamic parts of a template literal expression and handle them like a |
An example use case would be dynamically loading translation files which is what I use it for at work. e.g. |
@traverse do you have a bundle per language or do you import the language at runtime? |
@kilianc the translations files are simple JSON files per language but since we're using webpack it creates bundles and a bundle map for us so that they can be loaded dynamically at runtime. You can find some more info here https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import. Like it states in the documentation though the path can't be fully dynamic. |
Since it's relevant to this thread: as of version 0.5.3, dynamic imports with template literals with variables are now a warning, not an error. The dynamic import is passed through to the output code unchanged. At the moment I don't have any plans to emulate a virtual file system like Webpack does. That feature in Webpack seems too complicated and special-cased to be built into esbuild itself in my opinion, especially with all of the Webpack-specific comment directives. One option is to wait for esbuild to have plugin support and then write a plugin for this (see #111). Another option is to just rewrite the import expression in your source code if it is intended to be statically-determined and included in the bundle. So instead of this: let translation = await import(`translations/${language}.json`) You could just do something like this instead: let translation = await {
'en-US': () => import(`translations/en-US.json`),
'zh-CN': () => import(`translations/zh-CN.json`),
// ...
}[language]() |
I'm going to close this issue "won't fix" as explained in my post above. |
Unfortunately the suggested work-around doesn't scale for larger (legacy) code bases where a dir substructure must be loaded. Webpack has variable dynamic imports and Parcel has the super useful glob import:
(but Parcel has other shortcomings, namely handling externals). I suppose one could run a glob preprocessor and generate statically linked imports -- but having it in the tool makes it a lot easier. Or as a plugin, when that's available. |
@moos I think the plugin API will fit this beautifully. You'll be able to catch the "*" and return an object with anything you like |
Not sure if anyone else has come up with a better solution, but I was able to create a plugin that will look for dynamic imports that have a template literal and a variable inside. Transform that variable into a glob i.e. I was just able to get it working for my pretty large code base and am working on cleaning up the code. Seems like my plugin accomplishes what is talked about in this issue. I can check back in when I get it published if anyone is interested. |
@kalvenschraut could you share your plugin? |
@AndrewBogdanovTSS See above comment if you have not seen it yet |
its not completely clear to me is:
working at runtime? if i would copy the files in that translations directory myself? because doing it statically is a nogo for us then we never are able to use esbuild for building because in our current product that would mean 1271 lines of code.... currently webpack build does copy all the dynamic files (1271 for our current product) and i can use that dynamic import |
i see you make it static imports what does that exactly mean? |
No they are still imports at being added at the top of the file which was fine for my use case at the time. In theory I think it would work to make them dynamic imports of the specific file but I haven't tested it. Main thing that esbuild support IIRC is the template literal parse so if the plugin were to enumerate all the options as dynamic imports instead of static ones at the top then hopefully would work. Vite does something similar internally, they have option to preload the imports or still keep them lazy. Though this is more so when using globs, which is very similar to how these template literals work anyway on the bundler side. They add a method that you call that they then compile down. |
Dynamic import w/ template literals w/ variables problem. Used
esbuild@0.0.15
.Run:
esbuild --bundle test.js --outfile=build.js
Expected output:
Actual output:
The text was updated successfully, but these errors were encountered: