As build processes became more complex it wasn't a matter of bundling but often taking your code through several build steps.
- translate any styles written in Sass into CSS
- minify the code to optimize bundle size
The original solution were Task Runners like Gulp and Grunt with which you could schedule an order of tasks to run these processes. This was fine but then something else came along...
Webpack was a bundler that can also be used to manage your whole build pipeline (run tasks). So you can specify code to be bundled, through plugins and modules create a whole chain of things to be done (lint, transpile, compile CSS and then bundle for example). Webpack made setting this all up much easier from one place with a rich ecosystem of plugins and is still dominant today.
Although, all problems weren't fixed so the demand for other bundlers still existed.
A new bundler called Rollup hit the scene with a cool new feature called "Tree Shaking". Tree Shaking allowed you to only bundle what you used. So if you only used one Lodash function then only that function would be included in your bundle, not the whole library.
This feature is now standard in bundlers, but Rollup was the innovator in solving this problem.
Setting up all the configurations for Webpack and Rollup only really needs to be done once but can be time-consuming and complicated to get just right.
Parcel billed itself as a "no config" bundler. By building into itself many of the most common defaults it created a tool to very easily create your build environment. Of course, the catch is if the defaults aren't what you need then oftentimes going back to Webpack or Rollup may be the right option.
When running your development environment, bundlers like Rollup, Webpack, and Parcel are rebuilding your entire project after each saves. This is fine in the early stages but as your project gets bigger this re-bundling of your app can start taking a whole lot of time.
So the newest bundlers around, Snowpack and Vite, take advantage of this. Instead of bundling your whole app into one file, it compiles them into individual modules. Now when your code updates instead of having to rebuild the whole bundle it only needs to rebuild the edited module making for a much faster and pleasant development experience.