We’ve seen a little internal debate on the best way to start up and lay out new JavaScript-based apps.
To Bower
There is no real ‘build-and-deliver’ safety net that Java apps have in Maven with the central repo.
CDNs and library locations can go down (the npm central registry has gone down like GitHub has). Bower can download web dependencies and npm can download build dependencies, and as unpleasant as it is, checking them in to source control ensures that everyone on the team has exactly the same code.
This also has the advantage that you don’t need to access a CDN when running builds or unit tests.
You may want to use a concatenation tool like browserify or require.js – this concatenates and minifies your code and the frameworks to a tiny little file, but allows you to develop with the fully expanded source.
So, in short, there are a lot of reasons to keep the code locally, mostly around the fact that JavaScript as a platform needs to uniquely preserve its code into completely reliable places, and we need a maven-like tool with a local cache of the libraries like ~/.m2/repository
if we want to have more reliable and cleaner builds, and then a server like Nexus/Artifactory to cache those libraries in the enterprise.
or Not To Bower
Most of the JavaScript libraries we include in an app already exist on CDNs. Why not take advantage of them? Using CDNs:
- A browser can cache libraries across apps
- JavaScript and CSS libraries that expect images or fonts or other artifacts will automatically find them in the right places
- There’s no third-party clutter in an application’s source code.
If the source map on the CDN doesn’t work, it’s easy enough to flip between minified and expanded CDN URLs when the time comes to debug. And consider how much a project is streamlined — an empty Angular site generated using NPM, Bower, and Angular-Seed or Yeoman puts upwards of 7,000 files into the project directory before a single line of application code is written.
Now there’s some fine print:
- It may be easier to emit a new project with these tools and then go clean up the initial code, replacing local links with CDN links and removing the unneeded source downloads.
- And enterprises may want to run their own “CDN” server with approved versions of various libraries. This can be a simple Web server, but it would be nice if a better tool existed to manage it.
To Bower
CDNs are fine for small projects or libraries hosted by massive providers. But who wants to tie your uptime to somebody else’s infrastructure? Should it be your responsibility to find out whether some random CDN is stable enough?
Bower keeps the code locally even if you don’t check it into version control. For development a bower.json
file is enough. Bower doesn’t support repeatable build like Maven, so you may want to check in your dependencies for releases. (There are similar issues with Ruby gems, and you may want to check in your CDN dependencies so your tests can run offline.)
You can also run your own Bower server for all the same reasons you’d run Nexus.
There are other benefits to Bower too:
- Bower will download dependencies. (For instance, downloading bootstrap will also download jQuery.)
- Bower can use a manifest of the requirements, so other developers can “
bower install
“ - Bower lets you easily search and install libraries even locking to a specific version. Bower makes it easy to list and update dependencies.
Now unlike Maven, Bower is just a package manager — you still need something like Grunt to build. Grunt is useful for automation, minification etc.
You could build Java projects without Maven, but that doesn’t make sense for most projects. Similarly many JavaScript projects with multiple libraries and developers can benefit from better tooling like Bower and Grunt.
or Not To Bower
The issue with CDN uptime is true. If you don’t feel that CDNs are reliable enough, either you run your own or download and bundle all the files you need.
On Bower, though, it has to be one way or the other. If it’s not reliable and repeatable enough to always give you the same code for the same config, then you can’t just check in your bower.json
because each of your developers and CI boxes may get different library code for that same Bower config file. And if GitHub isn’t reliable enough to be a CDN during a test run, why is it reliable enough for Bower to download code from for a test run?
It seems like there are pitfalls in any direction. Bower would certainly be more friendly if it only copied the necessary runtime files from a CDN into the project, instead of copying in the whole source and build and kitchen sink for every JavaScript library and every dependency. Having thousands of files with millions of lines in your project before you even start writing code is just not friendly.