Summary
I am proposing that we remove the PureScript bundler once we support ES modules in the compiler (once #3791 merges and #3613 is closed). With ES modules in place, the bundler is no longer necessary to develop applications in the browser or on Node. Since the bundler is slow, buggy, and difficult to work on -- a high risk, low reward part of the compiler -- removing it reduces the maintenance burden on the already-thin compiler team.
Two weeks ago I opened an RFC on Discourse titled RFC: The Future of the PureScript Bundler in which the community has so far seemed entirely in favor of this proposal.
Motivation
The PureScript compiler includes a bundler that performs dead code elimination and produces a single .js file from PureScript sources, which can then be used in the browser or on Node. The bundler exists for a few reasons:
- To ensure users can run their PureScript code in the browser and on Node without requiring additional tools
- To trim the size of the generated code by performing dead code elimination while bundling
Enter ES modules, which we have already agreed to support in the compiler. We have two paths forward for ES modules support as far as the bundler is concerned:
- We fix the bundler so it works for ES modules -- which is trickier than it may at first appear
- We remove the bundler altogether
Why has (2) even become an option at all, when it hasn't historically been an option? Because things have changed with ES modules:
- ES modules are usable in the browser without bundling. Therefore user interfaces can be developed in PureScript without the need for a bundler.
- ES modules are usable in Node experimentally since v12, and fully in Node since v14 -- which will be the oldest supported version by the time PureScript 0.15 comes out -- so long as you use the file extension
.mjs or set type: "module" in a package.json file. For now, the compiler output contains a package.json file containing type: "module".
- Bundlers like webpack and esbuild are able to provide dead code elimination for ES modules comparable with
purs bundle optimized with zephyr, and may even perform better if we make other compiler changes like changing the representation of data types. These bundlers of course are also able to produce a single .js file for use in the browser or on Node, and so they are able to replace purs bundle.
Points (1) and (2) mean that PureScript users can run their code in the browser and on Node without requiring any additional tools, and point (3) means that users can get effective dead code elimination without using the PureScript bundler.
My understanding is that there is little appetite among the compiler team for sinking engineering resources into the bundler; this is part of why ES modules support has taken so long. @kl0tl, the author of the ES modules PR to the compiler and member of the core team, has indicated their preference for removing the bundler.
Unfortunately: users would no longer get effective dead code elimination without external tooling. Still, I don't think this is much of a problem, because:
- Dead code elimination is not necessary during development (it's typically an optimization needed for production builds)
- It is already a best practice to rely on external tools for dead code elimination (namely, Zephyr).
- Every production project I'm aware of (other than Try PureScript) already uses a JS bundler like Webpack or esbuild, which will perform the dead code elimination on the JS on your behalf.
- If you have any JS dependencies in your PureScript project, then you already must use a JS bundler like Webpack or esbuild (or take your FFI dependencies via a CDN, which is exceedingly uncommon).
Proposal
Therefore, my proposal is that we remove the bundler altogether as part of supporting ES modules. The purs bundle command would be completely removed and the compiler would only produce the output directory. Downstream tools like Spago could implement their own spago bundle commands that rely on an industry-standard JS bundler like esbuild or webpack.
There is an issue on Spago tracking the spago bundle command.
Examples
The ES modules working group is producing more examples of the ES modules compiler being usable with bundlers like esbuild or snowpack or webpack, and the compiler being usable for unbundled development, but preliminary results show that JS bundlers are competitive with purs bundle.
Summary
I am proposing that we remove the PureScript bundler once we support ES modules in the compiler (once #3791 merges and #3613 is closed). With ES modules in place, the bundler is no longer necessary to develop applications in the browser or on Node. Since the bundler is slow, buggy, and difficult to work on -- a high risk, low reward part of the compiler -- removing it reduces the maintenance burden on the already-thin compiler team.
Two weeks ago I opened an RFC on Discourse titled RFC: The Future of the PureScript Bundler in which the community has so far seemed entirely in favor of this proposal.
Motivation
The PureScript compiler includes a bundler that performs dead code elimination and produces a single
.jsfile from PureScript sources, which can then be used in the browser or on Node. The bundler exists for a few reasons:Enter ES modules, which we have already agreed to support in the compiler. We have two paths forward for ES modules support as far as the bundler is concerned:
Why has (2) even become an option at all, when it hasn't historically been an option? Because things have changed with ES modules:
.mjsor settype: "module"in a package.json file. For now, the compiler output contains apackage.jsonfile containingtype: "module".purs bundleoptimized withzephyr, and may even perform better if we make other compiler changes like changing the representation of data types. These bundlers of course are also able to produce a single.jsfile for use in the browser or on Node, and so they are able to replacepurs bundle.Points (1) and (2) mean that PureScript users can run their code in the browser and on Node without requiring any additional tools, and point (3) means that users can get effective dead code elimination without using the PureScript bundler.
My understanding is that there is little appetite among the compiler team for sinking engineering resources into the bundler; this is part of why ES modules support has taken so long. @kl0tl, the author of the ES modules PR to the compiler and member of the core team, has indicated their preference for removing the bundler.
Unfortunately: users would no longer get effective dead code elimination without external tooling. Still, I don't think this is much of a problem, because:
Proposal
Therefore, my proposal is that we remove the bundler altogether as part of supporting ES modules. The
purs bundlecommand would be completely removed and the compiler would only produce theoutputdirectory. Downstream tools like Spago could implement their ownspago bundlecommands that rely on an industry-standard JS bundler likeesbuildorwebpack.There is an issue on Spago tracking the
spago bundlecommand.Examples
The ES modules working group is producing more examples of the ES modules compiler being usable with bundlers like
esbuildorsnowpackorwebpack, and the compiler being usable for unbundled development, but preliminary results show that JS bundlers are competitive withpurs bundle.