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
Output multiple files when bundle: false #944
Comments
Have you considered doing this with an esbuild plugin and However, esbuild currently doesn't convert CommonJS The only exception to this that I can think of is if you converted every CommonJS module into an ES module that exports the CommonJS wrapper closure but without executing it, and then also converted every import of a CommonJS module in an ES module into code that automatically calls that CommonJS wrapper. But this is not a transform that any tool currently does as far as I'm aware, so it would be incompatible with other stuff? It also assumes that you never import ESM from CommonJS which some libraries in the wild actually do, so that still doesn't work. I think the full solution would involve converting all ESM code into CommonJS to ensure that module instantiation could be code-directed, then convert all code (which is now CommonJS) back into ESM using lazily-evaluated CommonJS wrappers. This is essentially doing most of what it would take to turn esbuild into a single-file-at-a-time dev server, which is basically what you're asking for. Having esbuild do something like this is currently out of scope for now, and is not a priority. I think it makes the most sense for esbuild to focus on being a good bundler at the moment. However, I think what you're looking for already exists! I believe tools like Vite and Snowpack do this, and from what I hear they do this very well. People seem generally satisfied with them. And they also implement hot-module reloading which you might also be looking for. Since these already exist and have a lot of effort going into them, I expect people looking for features like this to use those tools instead of using esbuild directly. These tools actually both still use esbuild under the hood and are supposed to be quite fast. |
What I think you're saying here is that I would have an That's workable, but a bit more involved. It requires direct access to the build process, which means it'll need to be specifically designed to handle this recursive transforming. The testing plugin is meant to allow the user to configure esbuild (including their own plugins, but there'll always be a root file which imports their entrypoints). I was hoping that we could just detect that the result contains X output files (and they already contain the path!), so we could immediately know that the user intends for a un-bundled output.
Sorry, I'm jumbled a few points. I don't expect esbuild to transform ESM to CJS. We currently patch the files during compilation to convert simple But this was just a smaller detail of the initial feature request, I mainly wanted to focus on the ability to traverse the entire tree and generate some output.
I agree, but both of these require you build for their serving framework, so they're higher level designs and the cost of switching to them is much higher. The bundler is lower level, and mostly interchangeable in our build process (we've already gone browserify to esbuild, and we've sampled rollup/webpack, too). So I was looking to see if esbuild could support something similar to this, without having to fully adopt a different serving framework. |
The current code couples together the esbuild bundler (which really only cares about a file existing on disk) and the test "entry point" we generate to import all the user's test files. This makes reuse of the Bundler difficult. I want to get to the point where we can spin up multiple bundlers. This will eventually allow for something I call "module mode", where esbuild doesn't generate one large super-bundle. Instead, it'll outputs all files as individual ESM modules, and we'll let the browser load each file individually. You can read evanw/esbuild#944 for the full story.
Another thought I've had since opening this: Supporting a 1 for 1 input->output file module in build mode, instead of just transform mode, could allow for tree-shaking. Because we'd be aware of the full module graph, we could apply tree-shaking to each file to strip out unnecessary bits. |
A similar request was made for Webpack (>50 upvotes): webpack/webpack#5866 One of the webpack developers responded later with "Yes, it will be great feature, we will consider it after the stable webpack 5 release", but so far no progress has been made on it in webpack itself. That said, apparently someone made a plugin which approximates the desired behavior (each input file is processed by the webpack plugin chain, but then is written to its own output file rather than placed into a bundle): https://github.com/DrewML/webpack-emit-all-plugin I'm considering attempting to write a similar plugin for esbuild, but I'm not sure if that's even possible, due to less of the build process being accessible from JavaScript plugins. @evanw Do you know if the approach used by the plugin above is possible for esbuild's plugin system as well? The plugin's full source-code is here, for reference (56 lines): https://github.com/DrewML/webpack-emit-all-plugin/blob/master/index.js The key question, I guess, is whether there's something equivalent to the afterCompile hook in Webpack, as that is how the plugin "intercepts" the processed contents of each module prior to bundling. |
I think this is a duplicate of #708 |
TLDR: When using the JS API and setting
bundle: false
andwrite: false
, it'd be nice for the result to include multiple output files for each file in the module tree.This is a bit specific, but one of my biggest goals for my test suite treat each file as an independent module and not bundle them into a large single build file. AMP's current test suite generates a file at about 60mb, and trying to debug that in Chrome is a nuisance (extremely slow to load files in sources pane, and sourcemaps make it even slower). Having each file be independent an module served by the test server would eliminate this pain, and would make incremental building of the test suite extremely fast (just update a relatively small file, instead of concatting the 60mb file together again).
This would be really simple if everything just used ESM. But we still require CJS node modules, and so we still need some sort of transpilation layer to build. Additionally, we use Babel to do a few custom things, so we're definitely stuck with running some transpiler.
Currently, setting
bundle: false
means that each entry point is considered an independent module, which is good. But it doesn't allow us to generate a metadata for the full dependency tree, and it doesn't continue non-bundling any dependencies of the entry point. What I would like to happen is for esbuild to traverse down the tree and generate output files for each dependency (don't bundle them into a single output). This would allow us to transpile the CJS into ESM using esbuild, and hook into the plugin API to feed into babel for our custom transforms.The text was updated successfully, but these errors were encountered: