WebPack is not the only way
FuseBox is a new generation bundler and module loader, it is the result of our years of experience dealing with complex projects requirements and many of the development tools out there.
First of all, let us establish a very clear fact, this post is not about undermining any of the bundlers out there and most certainly not the hard work of those who shared them with us, on the contrary, we highly appreciate the efforts that have been done, we used them in our work, truly got inspired by them and our goal is to compete to be part of what makes the JavaScript world and developer’s life better.
Why?
Well, we know that with modern day applications requirements, adding script links to a page does not cut it anymore, there must be a better way to manage the complexity, rapid changes and chain of dependencies of resources, therefore we need to use a bundler/module loader. There are many known and unknown tools in that domain, and like everyone else, hunting season started!
We tried everything RequireJS, Browserify, WebPack and many many others… but there was always some requirement that we needed in our projects that none of those bundlers offered, so we decided to enter the kitchen and cook our own beast!
We won’t go through the full details of our research and tests as it would take pages and pages, but we will try to highlight the main parts that led us to create FuseBox and how we feel it is one of the best tools out there.
The tools that made it to our final round before creating FuseBox were WebPack, JSPM, StealJS. Again, all these tools are a great piece of engineering, can get you the job done and most importantly there are communities behind them, but here is what we really faced as issues:
WebPack: No doubt a strong and deep tool, but the lack of documentation (to be fair, the team have released a new documentation website which is looking a lot better) and boilerplate code required to build your project is too much for us. You can do anything with WebPack but it is not easy!
JSPM: this is our favorite one after FuseBox, it is really an underrated project, also Guy Bedford is one of the kindest and smartest people in the industry. JSPM configuration is more straight forward, it accepts virtually any module format but it is slow in the browser if you don’t create a build that targets UMD or CommonJS.
StealJS: is an interesting project in that it shares parts of WebPack and JSPM. like JSPM it uses SystemJS under the hood as module loader, but like WebPack it uses npm as modules resource. Our problem was that some npm modules are not designed to run in the browser. As such, they log errors when loaded, though this doesn’t always affect their functionality.
So what did we do to make FuseBox really different and in our opinion better? We studied all the above-mentioned tools carefully and took the best parts of each of them, enhanced them and added extra awesome features that made our life easier and we are sure it will make your life as a developer much better too.
Philosophy
What we have now is just the tip of the iceberg, we want to go beyond just an open source project, we want to provide professional services and set of tools to cater to the full requirements of the development life-cycle. Stick around with us and soon you will see awesome fruits that will shake some grounds in this field. With that being said we will always have three main goals on our mind
- Speed
- Extensibility
- Simplicity
Turbo start (zero configuration)
To start bundling all that you have to do is
FuseBox.init({
homeDir : “./src”,
outFile : “./build/bundle.js”
})
That is it, now you can start coding and FuseBox will do the magic. The code above will allow you bundle the most complex projects on Github, like babel-core
Shimming npm modules
Some npm libraries are made to work in both client and server environments but some don’t, for example, some libraries have a dependency on Node’s `process` module, this will not work in the browser. therefore we made sure to shim all the major ones so they will work perfectly on the client, or at least will cause no errors if they are designed to work only in server environments. And if there is a library that does need shimming and we did not add it yet, you can always submit a PR or you can do it easily yourself in your project with one great feature custom modules folder
. it is really simple, check the shim for URL module https://github.com/fuse-box/fuse-box/blob/master/modules/url/index.js
TypeScript and Babel
We love TypeScript, we use it on daily basis but it really gets slow when you have a large project, therefore we really worked hard to make sure that it works super fast and out of the box. For example, we have a project with over 200 files and with FuseBox TypeScript integration we were able to take down transpiling time from 5 seconds to 720 ms!
Same goes for Babel we support it as a built-in plugin, just install it and use any of its plugins and it will work like charm.
Bundle anything
We have built-in plugins for most of the required files formats a developer needs, let it be HTML, CSS, SCSS, JSON, etc. here is a list of all built-in plugins we have so far http://fuse-box.org/#built-in-plugins.
FuseBox plugin API is simple and intuitive. One great example of this is when we had a user who required the ability to pass some variables at build time for both client and server bundles, so we created the `EnvPlugin` which allows you to do the following:
plugins : [
fsbx.EnvPlugin({ foo: “bar” })
]
Now you can access your `foo` variable in your code like this `console.log( process.env.foo )` and it does not matter if you are on client or on server, you can even use the plugin with libraries such as https://www.npmjs.com/package/safe-env. This is a great example that shows how combining FuseBox shimming of npm modules with the Plugin API can give awesome possibilities.
Caching
FuseBox has a powerful caching system. The way caching works is that on the first run, FuseBox will build a manifest of all npm modules you use in your code and on subsequent bundling Fuse will fetch those modules from the cache and only process your local code, this will cut down bundling process time tremendously!
Fuse does not only cache top Modules you use, it also caches each Module dependencies, so imagine you have a total of 100 npm modules required in your code, without caching, every time you change one line in your code you will have to re-bundle all those modules.
Dynamic Modules
This is one of FuseBox’s best features, A feature that we can’t live without in our projects. The concept behind dynamic modules is simple yet very powerful, The idea here is that you can create modules at run-time that behave just like the modules you’d normally write at development time. what does that mean? It means you can easily write your code as a string, you can feed this string to Babel-standalone or even Typescript compiler or just directly write commonjs compatible code. Once the module is ready you can register it with FuseBox by calling FuseBox.dynamic with a module path and the CommonJS source string. Now you can import it like any other module.
FuseBox.dynamic(“foo/bar.js”, “module.exports = {foo : ‘bar’}”)
What is crazier is that FuseBox will treat it as a native module, so if you have import statements of real npm modules or your local code inside this dynamic module, FuseBox will resolve it correctly and everything will work as usual. Think about the wild possibilities! To get more nice cover on dynamic modules check out this article
Wildcard imports
Have you ever wanted to load multiple files with a single require statement? We did too, so we built glob support into FuseBox’s import function. For example, imagine you have page-a
in your SPA project and you group all of its components in a folder called page-a/components
, you can simply do the following:
FuseBox.import(“./page-a/components/*-component”)
FuseBox import command will now return an object containing those components:
{
“page-a/components/carousle-component.js” : {code},
“page-a/components/articles-component.js“ : {code}
}
What is even better is that you can load any file format supported by FuseBox or any of its plugins, say you want to load all JSON files in config
folder, then all what you need to do is this:
FuseBox.import(“./config/*.json”)
import relative to root
When we have a complex large application, everything is modular and folder structure gets deep and complicated. Imagine you have the following file src/modules/module-a/validate/email.js
and you have utility function called toCamelCase
at src/utils/toCamelCase
, to reference this utility function inside email.js
typically you would need to do this
import {toCamelCase} from `../../../../utils/toCamelCase
This is ugly, but with FuseBox you can simply do
import {toCamelCase} from `~/utils/toCamelCase`
Much better right?
Extended metadata properties
If you are coming from JAVA or .NET background, this is called reflection. An amazing feature that grants you access to the full details of the loaded module like file name, directory name, exports, etc. which allows you to do wild things! A cool example of that is say that you have a convention of creating a folder for each component and store the JavaScript, HTML and CSS files next to each other and you want to automatically load the HTML and CSS files when you load your component’s JavaScript file, well you are in for a treat :) We can easily create a decorator that will do all of this for you automatically as follows:
Now you can add this decorator to any component like this
@componentDecorator()
class MyComponent {
}
Boom! Fuse will load the component CSS file and add it to the DOM, load the HTML Template and now you can access it as a property on your class.
Conclusions
Working with FuseBox is really a pleasure, thanks to it now we have more time for playing Video Games at the office :) jokes aside, FuseBox is really a fresh new perspective on the whole module loading and bundling business, it really saved us Time and brain works, what makes it even better is that there is no objection on adding new features or going beyond what is considered a limit line for others.
Hop on
This 4 minute video demonstrates the absolute simplicity and power of FuseBox used with Typescript.
This article only scraped the surface of what FuseBox is. FuseBox is still young, but we are working on it on a daily basis so Expect more to come, but meanwhile If you like the project don’t forget to star it on Github! And of course, spread the word by clicking ♥ we need your support and feedback :)
Join our gitter channel, we are active and very friendly!