Closed ry closed 3 years ago
If we were to do that, then deno compile
couldn't work (or would require significant changes to keep the functionality working).
I can see why it is done because there are alot of bundler's that already provide the same or more than deno bundle
Other than that, I'm fine with deprecating it and eventually removing it eventho it feels a bit weird to remove a handy utility like this with the only reason being "it can be done effectively in user space"
I personally will always vote for making deno
more of a pit of success for things that will predictably be needed by a huge percentage of apps. Keeping out parts of a toolchain that is needed for a lot of projects makes people spend time on choices that will likely not generate a lot of value, making project setup more complex and the whole space more fragmented.
At least how I see it, deno
tries to solve exactly that go
style by having one toolchain to do things and let people write applications instead of tooling setup.
If we were to do that, then deno compile couldn't work (or would require significant changes to keep the functionality working).
@bartlomieju To clarify (for other people) "deno bundle" can be deprecated and removed without effecting "deno compile", but in order to remove the swc_bundler dependency, we'd need to do some work to "deno compile" maybe to use something like the eszip json file format instead.
JS bundlers have a lot of complexity and we do not want to take on all that complexity in Deno. We believe this can be done effectively in "user space" - that is, it doesn't need to be built into the Deno executable.
While true, that can be said for nearly all of our subcommands.
I'm against just because we're taking away a useful (albeit, needs some tic) feature from our promise of being a one stop toolchain.
My first reaction was “no”. Then I thought about it a little bit and still “no”. From where I stand, one of the big promise of Deno was the out-of-box toolchain. If we start removing every tools because there might be another option in user land, what’s the argument to not remove everything? I think that we’re better off with a “not as great” bundler than no bundler; at least a “not so great” bundler can be fixed or improved. 🤔
JS bundlers have a lot of complexity and we do not want to take on all that complexity in Deno. We believe this can be done effectively in "user space" - that is, it doesn't need to be built into the Deno executable.
While true, that can be said for nearly all of our subcommands.
I'm against just because we're taking away a useful (albeit, needs some tic) feature from our promise of being a one stop toolchain.
If we start removing every tools because there might be another option in user land, what’s the argument to not remove everything?
I think the main difference here is that deno fmt
& deno lint
are used to help with the development of JS/TS that gets executed by deno. deno bundle
however is mostly used for packaging up a single script for using it in the browser, to help target other runtimes, and perhaps as a way to distribute a library for Deno as well (less files, so less requests, though that's more of a nice to have).
On the note about complexity, I believe userland already has and will be able to provide better versioned APIs that aren't tied to the deno executable in order to solve this problem. They'll be able to provide features like code splitting, transforms, and such that would be unreasonable to add to deno bundle
.
I think the main difference here is that
deno fmt
&deno lint
are used to help with the development of JS/TS that gets executed by deno.deno bundle
however is mostly used for packaging up a single script for using it in the browser
But Deno explicitly invests work to be as browser compatible as possible, so I do not see how it does not fit - I see more potential to standardize an almost required part of the toolchain that people spend a ridiculous amount of time on right now (choosing one of 6 tools and 6273 meta frameworks that configure them) without writing actual code to solve their actual problem.
On the note about complexity, I believe userland already has and will be able to provide better versioned APIs that aren't tied to the deno executable in order to solve this problem.
Deno's philosophy is to have a one stop toolchain - that does not prevent people from writing userland alternatives but I still do not see how the option of alternatives defeats the purpose of a central standardized toolchain that will see a lot of use because it is convenient.
They'll be able to provide features like code splitting, transforms, and such that would be unreasonable to add to
deno bundle
.
Why are they unreasonable?
I'm just saying there's a difference between deno bundle
and the other sub commands.
They'll be able to provide features like code splitting, transforms, and such that would be unreasonable to add to
deno bundle
.Why are they unreasonable?
For example, implementing transforms would expose a huge amount of API that rapidly changes under the hood. People would be relying on what's available in the deno executable rather than a semantically versioned API. Using a versioned imported module would provide more stability and likely work no matter what version of the deno executable is used (since they're not tied together). For code splitting and more advanced bundler features it would require config or to expand the complexity of Deno.emit
(in which case, once the complexity becomes too great I believe it's more appropriate to rely on a versioned imported module so that breaking changes can easily be made by the maintainers).
I'm mixed on this. On the one hand, bundlers are a rabbit hole that doesn't seem to ever end. deno bundle
sort of opens the door to endless user requests to support this and that feature. On the other hand, I also agree that one of the selling points of Deno is that it is a one-stop-shop toolchain for the whole developer workflow, and it would be a shame to lose that feature.
We're in an interesting place right now since we're bundling swc in the runtime itself, so while esbuild and swc compiled to wasm are probably fast enough, a truly native solution is most likely faster. I think a sensible course of action would be to remove the deno bundle
subcommand but keep Deno.emit
in the runtime and keep working on its capabilities. The idea here would be to leave the implementation of the bundling, chunking, code splitting, whatever to userland, but provider the low-level API to access swc directly under the hood so that these tools can be written in JavaScript yet benefit from the native speed.
This is really a fascinating discussion! There are a lot of things that come to mind:
deps.js
will suffice mostly, etc.)<opinion>I'm actively trying to drop all this over-engineered stuff like babel, etc. and get back to a sane, minimal prod build pipeline</opinion>
If Deno is able to articulate a bundling vision much the way it has for other aspects of itself, It may make sense to leave it in core.
To me that would look like taking a minimal stance and saying "sorry, we don't think you should be running 4 different html/css/js transpilers in your build system, etc." We have an ecosystem that has gorged itself on tools. Enough is enough. :)
I remember standing on a stage with you Ry at TSConf and stating that "Deno CLI will be the only tool you need" and now you are suggesting backing away from that.
I am not supportive, as it fundamently goes against what I thought we were trying to accomplish. Changing the infrastructure so that there are less issues with deno bundle
is one thing, deprecating it is just cruel. Next thing you know, we will be requiring people to load tsc or some other type stripper themselves to use TypeScript with Deno because it makes maintaining Deno easier.
I remember standing on a stage with you Ry at TSConf and stating that "Deno CLI will be the only tool you need" and now you are suggesting backing away from that.
@kitsonk Deno CLI is still the only tool you need to do bundling, even if you remove deno bundle
. Packup is a good proof of concept:
deno run -A --unstable https://deno.land/x/packup@v0.0.13/cli.ts build index.html
The alternative is that deno bundle
starts competing with systems like webpack, esbuild. This is likely a deep rabbit hole of options.
@kitsonk Deno CLI is still the only tool you need to do bundling, even if you remove
deno bundle
. Packup is a good proof of concept:deno run -A --unstable https://deno.land/x/packup@v0.0.13/cli.ts build index.html
So are we deprecating deno lint
, deno doc
, deno info
, deno test
as well since all those can be done in user land. What about TypeScript transpiling all together? Again can be done in userland.
The alternative is that
deno bundle
starts competing with systems like webpack, esbuild. This is likely a deep rabbit hole of options.
As we talked earlier, we should be talking in use cases of problems we are trying to solve. deno bundle
was always solving one problem in my mind, how do I take an arbitrary set of modules that run under Deno and create a single file that can be redistributed to run under Deno. It never has nor in my opinion never should be a competition for other arbitrary bundlers.
Drawing a line around what you do is one thing, deprecating core functionality because it is hard is another.
I completely agree with @kitsonk here. deno bundle
is a tool for bundling program code for use in Deno. I don't think it should be deprecated or removed. It is incredibly useful and explicitly not meant as a general purpose web bundler.
In relation to Deno.emit
, I could understand the argument that that could be done in userland, and that we should prevent scope creep. But I don't think we should discuss the future of Deno.emit
in the same issue as discussing deno bundle
. They must not be confused. They are distinctly different, even if they build on the same infrastructure.
The alternative is that deno bundle starts competing with systems like webpack, esbuild. This is likely a deep rabbit hole of options.
That's definitely true, but I'm thinking about it an inverted way; If my project can't be bundled with deno, it's on me to drop all the stupid crap that today's bundlers do and pare down to a reasonable bundle capability that deno already provides.
I'm trying to align my project to work with Deno's vision of a minimalistic modern js runtime. I don't know if I want deno to adopt these other unhealthy practices, even though it's very practical to do so today. If I want a bunch of bloated bundling logic including bits for commonjs plugins etc., why don't I just use node?
It is incredibly useful and explicitly not meant as a general purpose web bundler.
@lucacasonato is it incredibly useful? How are people using it?
It seem odd to me that Deno claims to be web compatible, but "deno bundle" explicitly does not produce bundles for browser.
But I don't think we should discuss the future of Deno.emit in the same issue as discussing deno bundle. They must not be confused. They are distinctly different, even if they build on the same infrastructure.
I agree - I'm conflating the problems here...
It seem odd to me that Deno claims to be web compatible, but "deno bundle" explicitly does not produce bundles for browser.
that's a really interesting point. Maybe it makes sense to specifically (re-?)define the purpose of deno bundle
to explicitly produce bundles that run in the browser. I'm assuming that is the main use case 99% of the time (avoiding loading dozens or hundreds of modules is still not great, even when assuming http2 or even http3 capabilities.)
If we were to define that as the specific purpose, could we declare the bundle command as done, and just shrug off the infinite bundling feature requests?
How are people using it?
Bundling Deno programs for deployment to a server. The bundle is then just a single file you can plop onto a VPS or into a Docker image. Startup is greatly improved because no downloads or emits have to happen at startup.
It seem odd to me that Deno claims to be web compatible, but "deno bundle" explicitly does not produce bundles for browser.
It does not explicitly not create bundles for the browser (quite the opposite, they work fine there), it just is not it's primary focus as far as I can tell. The intension is to use deno bundle
to produce bundles that will be loaded in Deno.
is it incredibly useful? How are people using it?
Yes. Creating dependency-less bundles of Deno code qt a specific version, sometimes to have a single distributable with Node.js or a browser as a "library". Effectively a build step. There are other comments in this thread where people have uses which you seem to be ignoring.
It seem odd to me that Deno claims to be web compatible, but "deno bundle" explicitly does not produce bundles for browser.
Now you are changing your previous statements again. We always said that Deno would adopt web platform APIs where suitable, so that it is easier to move code between Deno and the Web, not to be headless Chrome.
Bundling Deno programs for deployment to a server. The bundle is then just a single file you can plop onto a VPS or into a Docker image. Startup is greatly improved because no downloads or emits have to happen at startup.
I think this is the most compelling use case though I think deno compile
also covers this need.
is it incredibly useful? How are people using it?
Yes. Creating dependency-less bundles of Deno code at a specific version, sometimes to have a single distributable with Node.js or a browser as a "library". Effectively a build step. There are other comments in this thread where people have uses which you seem to be ignoring.
This is where I think there are userland tools that are better or have the potential to better meet this need. For example, something that even transpiles the Deno
object to something Node compatible.
I think this is the most compelling use case though I think deno compile also covers this need.
It is alot slower to use compiling in a JavaScript tool chain. Plus you would have to install a 75 MB binary each time your project has an update. While a bundle would likely be less than 15 mb's in filesize. So for deploying code I feel like the bundle subcommand is a really handy feature that the compile subcommand is not usable for.
@lucacasonato is it incredibly useful? How are people using it?
From the stated goals as listed in the Deno manual...
- Ship as just a single executable (deno).
- Be browser-compatible.
- The subset of Deno programs which are written completely in JavaScript and do not use the global Deno namespace (or feature test for it), ought to also be able to be run in a modern web browser without change.
- Provide built-in tooling to improve developer experience.
I'm primarily a front end web developer. I can say from personal experience I hate the high levels of complexity, configuration, language-manipulation magic involved with the node bundling ecosystem. One of the core things that attracted me to Deno was that it was going to be straightforward and follow the language implementations of the browser.
The goal stated above, (which deno bundle
's current implementation totally lines up with) unlocks more or less my ideal workstream:
deno bundle
to produce a single file (or a few files) to improve JS loading performance, while still being able to enjoy all the goodness of code organized into ES modules.And that's it. No complex tool chains or plugins or configuration needed. Not to say there aren't use cases that are more demanding, but I don't see why they couldn't build on top of or just be separate from the basic functionality Deno provides. I don't need to import my CSS into my JS. I can use other tools purpose built to be a dev server (the snowpack mentality, non-bundled es modules are great in dev environments). I don't mind (at all) writing file extensions in my import
statements. I just want to be able to take a whole bunch of TS/JS files and smash them into one. deno bundle
lets me do that so easily: one command with one executable that I'll already be using for other things like formatting, linting, and running non-browsers scripts. It'd be a shame if that dream died.
P.S. Thank you to all the maintainers that work on Deno. I realize you've put in a ton of time and effort and that managing an open source project can be a thankless task where people have baseless expectations that their every demand will be met. I hope this didn't come across that way, just sharing my use case.
I think this is the most compelling use case though I think
deno compile
also covers this need.
Partially. It doesn't make it easy to combine "lib a" and "lib b" and have something that is deployable. As other stated, just copying the binary as well is painful/useless in some instances. One can also do a deno bundle
as a build step and then host that some place and then everyone with the CLI can just import myLib from "https://example.com/myLib.js"
. If we get type emitting working with deno bundle
then people can even use the bundles strongly typed.
It isn't just about my deployments, it is about making code available to others simply, without having to worry about resolving dependencies.
As other stated, just copying the binary as well is painful/useless in some instances. One can also do a deno bundle as a build step and then host that some place and then everyone with the CLI can just import myLib from "https://example.com/myLib.js". If we get type emitting working with deno bundle then people can even use the bundles strongly typed.
I'm not sure we should encourage users to ship libraries with their dependencies bundled (libraries distributing minified bundles would be terrible for debugging #6900). I think that should be up to the user making the final distribution of an application (not a library) to make those decisions rather than midway through the dependency graph. Additionally, it makes it more difficult to understand what depedencies a library is pulling in... which makes it harder to catch the same dependency used multiple times (so it might be included multiple times in the final output), or duplicate dependencies with different versions, or to analyze code for auditing purposes.
It is alot slower to use compiling in a JavaScript tool chain. Plus you would have to install a 75 MB binary each time your project has an update.
Running deno compile <file-path>
seems almost just as fast to me. The 78MB file is 30 MB zipped, though I can see how that's not as convenient and obviously that grows with application size... dependening on what services are used I don't think this is a deal breaker and probably in the worst case nowadays is only a few seconds slower (I'm not so familiar with how fast different services transfer data though)... many deployments would need to download deno anyway.
Additionally, a huge advantage of deno compile
is the same version of deno that was used on the CI to test the code is also what's used in the deployment. You don't need to configure your server environment to use it either... so overall I think that's a lot simpler and wonder if perhaps it should be encouraged over deno bundle
for that purpose once it's stable.
(libraries distributing minified bundles would be terrible for debugging #6900)
Not if we fully solve #8577 (WIP PR at #10698). The same thing could be argued for deno compile
as it stands now.
I think that should be up to the user making the final distribution of an application (not a library) to make those decisions rather than midway through the dependency graph. Additionally, it makes it more difficult to understand what depedencies a library is pulling in... which makes it harder to catch the same dependency used multiple times (so it might be included multiple times in the final output), or duplicate dependencies with different versions, or to analyze code for auditing purposes.
These are good potentially good practices, given specific contexts. I don't see them as being material do the deno bundle
s utility.
so overall I think that's a lot simpler and should probably be encouraged over
deno bundle
once it's stable
They solve different problems differently. deno compile
is suitable for some situations, deno bundle
is suitable for others. They both have their place. Especially in environments where every binary has to be "authorised" to be installed, having a single file distributable allows people to install deno
but be able to have multiple workloads they can run without installing n binaries for example.
I feel that too complicated bundle is a big problem not only for Deno but also for Javascript itself. It is still stage 1, but if this proposal is adopted and the requirements for bundler change, will the implementation of deno bundle be simplified? https://github.com/littledan/proposal-module-fragments
We need deno compile
, and have dynamic import support (https://github.com/denoland/deno/issues/8655).
If deno bundle
is deprecated to help improve deno compile
, I think it is appropriate.
Speaking as an end user, I assumed that deno bundle
was bundling Deno compatible code for Deno compatible runtimes (as @kitsonk described it). Otherwise, as a general bundler for web, it is indeed a huge undertaking as @ry says. For it to be useful on the front end and replace other bundlers, I'd expect it to support tree shaking, chunking, and minification, not to mention legacy module standards. Those are not simple tasks, and as much as I appreciate Deno's single toolchain (so much so that I'm porting my isomorphic libraries to it) I would not expect Deno to come with an all-purpose bundler; IMHO the time and effort of the team would be better spent elsewhere.
I'd expect it to support tree shaking, chunking, and minification
Tree shaking is actually already a feature of deno bundle
-- as for the other features being large undertaking, yeah that's true, but I think it's something we should strive for. We're not gonna be in a position to compete with existing bundlers any time soon, but I think that's an ideal we should slowly work towards. We have the infrastructure in place to do it, it'd be a shame to waste it.
If fully removing and refractoring the code for the command, and dropping the dependency will cut down on a sizable portion of the Deno binary, then I, as a user, will definitely appreciate the leaner application.
On the other hand, Ry claims that JS bundling is complex. Running JavaScript is already a complex task, but no one has made an issue saying that we should deprecate Deno. Some things are complex, and we appreciate the amount of work put into it, I'm sure the same applies to deno bundle
.
the amount of time wasted and the number of tools required to package javascript not only for deno but for other platforms is an incredible pain. For example tools like webpack create a huge number of issues (and dependencies). For example, javascript language features like optional chaining and bullish coalescing will make them insane depending on the version of the stack (let's not even get started with the number of security updates generated by the tooling dependencies)
When I started working on deno port for nats, I realized I could eliminate a lot of the tooling and have deno do the heavy lifting. I for one love it. I think you should keep the functionality. With that said the bundling feature seems more fragile than it could be (experiencing an issue with the current 1.11.2), the earlier version was resilient and seemed to deal with cycles, etc correctly.
Perhaps a good compromise is to restore the original bundler which did the ESM bundles just right and seems to work regardless of the code you throw at it - this would reduce the effort on your side, but maintain the feature.
The fact that deno comes with a bundler is awesome. I only used it while it was still working for my project. I don't expect the bundler to do more than packing all deps into a single js file. I can the use babel to minify that, etc. But since last year the bundler is not working for me https://github.com/denoland/deno/issues/8224 , if this would get fixed than what the bundler does now is perfectly fine.
I'm not sure where the idea that people expect deno bundle
to bundle deno code for the browser comes from? As a user I expect it to bundle deno code and its dependencies into one file runnable by deno, if the code is already runnable in both the browser and Deno, then yes, I'll expect it to bundle code that works for both, but I don't believe thats requires any extra work on the bundler.
I'm retracting this idea after reading through the discussion above.
I wouldn't totally be against the idea - as kt3k is the author, i have a strong confidence in packup, i mean if it does the same thing, i can't imagine why people wouldn't want to adopt it as opposed to using deno bundle
i mean if it does the same thing, i can't imagine why people wouldn't want to adopt it as opposed to using
deno bundle
It doesn't do the same thing. It is for bundling front-end code.
It should be a cost-benefit analysis. SWC is getting lots of attention right now, so the benefit is increasing. The cost should remain approximately the same.
This is now being deprecated again? https://deno.land/manual@v1.31.1/tools/bundler It suggests using esbuild. Any info on this decision, given above discussion? The current deno
binary is around 100MB, and the esbuild binary is about 8MB - too big to include?
that is too bad - the bundler is one of the features that make deno great - the setup for all this other infra is not required...
the only proper way to recommend esbuild is to deprecate the bundler, so I support it
One interesting exercise, is that deno bundle does the right thing with just pointing it to the src of the module. No doubt esbuild will do the right thing once the magic incantation is found (btw, still trying to get it to work)
personally, I wish bundlers would stop enabling really awful practices, and all the complexity that entails. I just want a simple bundler: Something that takes pure es modules and puts them together. Maybe with a couple bells n' whistles like importing json or css as modules. But to support an entire plugin ecosystem, and then typescript, and then code splitting, and then multiple package managers, and then 19 other things is where it goes off the rails.
Just give me a simple freakin' bundler that doesn't try to fix all the worlds problems and just knows how to concatenate es modules and call it done.
Not trying to just rant here, the point being if deno provided a sane/limited bundling option rather than trying to emulate all the stupid crap that webpack does, that would be sufficient for me.
@mreinstein esbuild is pretty close to it. I guess Deno could wrap esbuild, simplify it, add JSX by default, and make it follow the permissions. that would be pretty sweet actually...it could even go so far as to run the wasm version that would be forced to follow the security permissions no matter what upstream did, and if anyone's wondering why it's 10x slower (NOT an issue much of the time), document how you can switch to esbuild and that you give up Deno permissions...
the only proper way to recommend esbuild is to deprecate the bundler, so I support it or wrap it, cue complaints about increasing the binary size by ~10MB I think (unless it were optional 🤔)...
esbuild is pretty close to it
It is great, I use it in many projects, but it too is beginning to suffer from feature explosion. I would love for deno to just not fall into this trap.
add JSX by default,
This is exactly what I'm talking about. I don't want this stuff clogging up my bundler. I just want to take esm, combine it together into a bundle, and be done with it. I want the bundler to be done, and not some mega project that just grows constantly every time someone wants some special snowflake feature that some other bundler has and requires an entire team just to keep running.
@mreinstein I'm no big fan of JSX, but it's already included in Deno's umbrella of Zero Configuration, and I am quite alright with it. There is very little cost to me as a user and it is great for many.
I'm no big fan of JSX, but it's already included in Deno's umbrella of Zero Configuration
I'm not trying to pick on Jsx or typescript or any of those things. I agree in isolation they aren't that controversial, and I get the value they provide in some scenarios. The problem is in aggregate; it's death by 10,000 cuts. You either buy into the "bundlers will solve all the problems" or you take a hardline and keep it minimal but maintainable.
To me deno has represented an alternative path outside the maximalist node ecosystem. My hope is deno could keep a very minimal bundler that just doesn't go down that path as we already have these options elsewhere (webpack, esbuild, rollup, etc.)
So again, not trying to rant. Streamlining the points, we have 2 obvious options:
Ryan's original comment in this issue kind of assumed (2) as a foregone conclusion, but maybe it doesn't have to be? I agree (2) is untenable and not worthwhile. I would love to see (1) happen.
esbuild
I appreciate your opinion, but I think in order for that to be the case esbuild would have to be buggy*, and if it is, almost all code is. Deno having selected it as a recommendation is evidence that it is not a buggy project in general (and I don't just mean relative to bundler ecosystems).
I think this thread will be locked soon because I'm sure Deno has discussions on what's too complex to maintain.
Thanks for your thoughtful reply.
JS bundlers have a lot of complexity and we do not want to take on all that complexity in Deno. We believe this can be done effectively in "user space" - that is, it doesn't need to be built into the Deno executable. Packup is an example of a Deno program which utilizes esbuild-wasm to provide complex bundling abilities.
Ultimately we'd like to remove swc_bundler dependency completely completely from Deno.