Personally, the only bundler I use is Parcel. Parcel is a zero configuration, blazing fast, plugin aware bundler that - in my opinion - is just better than the competition. It is easier to configure (hint: no need for configuration), more robust (hint: no plugin / ecosystem that usually breaks), and faster (hint: caching) than others. I've tried Webpack (no matter what version), Rollup (was that ever released fully?), FuseBox (they got the TypeScript part right, but everything else is just not there yet), Browserify (oh good old times! - I think this one started it all...), and even Pax. Still, one of the things I needed (and had in, e.g., Webpack) was virtual modules.
What's so special about virtual modules? A virtual module can be generated during bundling and allows using information from, e.g., some API or the file system, to generate a valid JavaScript module that just lives in our application. This is an easy way to make the application just simpler to grow.
Example: On our company page we have a directory called pages
. In order to get the pages into our application we had to do a little trick. Using Parcel's "import all" feature we included them using import './pages/*.tsx';
. Now the pages had to register themselves using a registerPage
function from an ambient module. Still, using import { registerPage } from '../pageRegistry';
on every page feels weird. Likewise, since we already importing the modules we cannot lazy load them. Thus, the actual content had to be on a different module ... Long story short. Every page addition took adding either one weird embedded module or two modules with lazy loading. Quite ugly.
Using the parcel-plugin-codegen
we can now revert this. We can generate all the imports on the fly. So once we add a page we'll do the re-build and generate a new module called pages.codegen
, which just exports a list of the pages; their metadata (e.g., the route of the page) and the React Lazy component triggering the bundle splitting and lazy loading.
We also included parcel-plugin-codegen
for other tasks, e.g., a blog overview page (showing a preview of all existing blog posts), or a media module containing all the image references. Instead of writing require('../hope-you-got-the-path/foo.png')
we can now write images.category.foo
. And that works reliable.