The major benefit to referencing Bundles in a view using Razor is the automatic creation of URLs to the bundle with a cache buster query string appended to it (so that when content of any of the files in the bundle change, the URL changes, and you don't need to worry about the client still referencing an older cached version of your bundle). A second benefit is that when debug=true (in web.config), it renders URLs directly to the items in the bundle.
You could, of course, just hardcode the path to the bundle in your plain HTML, but then you lose both of these features. I'm also not sure if it'll render the combined bundle if you go to the bundle URL when debug=true (meaning, it might not work when you are in debug mode on your dev machine).
What I'm getting at is that if you aren't using a Razor view for at least the initial page in your SPA (the page that bootstraps your Angular client), you're not going to find Bundles very useful.
If you forego Razor entirely, you may wish to use alternate ways of bundling assets (and updating references to the bundle in HTML). There are a number of ways, but the most popular involve using Grunt or Gulp build tasks, which run on Node.js. For example (using Grunt), see grunt-contrib-concat, grunt-contrib-uglify, grunt-rev, and grunt-usemin.
Here is a link using Grunt and a variety of the aforementioned tasks to accomplish all of the things Bundles do without using Bundles or Razor.
Brief summary of the article follows (your mileage may vary):
- Install Node.js
- Install Grunt CLI
- Create package.json (
npm init can create this for you).
Add requisite Grunt add-ons:
"grunt": "~0.4.1",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-uglify": "~0.2.7",
"grunt-contrib-cssmin": "~0.7.0",
"grunt-usemin": "~2.0.2",
"grunt-contrib-copy": "~0.5.0",
"grunt-rev": "~0.1.0",
"grunt-contrib-clean": "~0.5.0"
Create Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: ["dist", '.tmp'],
copy: {
main: {
expand: true,
cwd: 'app/',
src: ['**', '!js/**', '!lib/**', '!**/*.css'],
dest: 'dist/'
},
shims: {
expand: true,
cwd: 'app/lib/webshim/shims',
src: ['**'],
dest: 'dist/js/shims'
}
},
rev: {
files: {
src: ['dist/**/*.{js,css}', '!dist/js/shims/**']
}
},
useminPrepare: {
html: 'app/index.html'
},
usemin: {
html: ['dist/index.html']
},
uglify: {
options: {
report: 'min',
mangle: false
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-rev');
grunt.loadNpmTasks('grunt-usemin');
// Tell Grunt what to do when we type "grunt" into the terminal
grunt.registerTask('default', [
'copy', 'useminPrepare', 'concat', 'uglify', 'cssmin', 'rev', 'usemin'
]);
};
Edit your index.html (or whatever your main app bootstrap page is) so your CSS and JS assets are properly decorated for usemin and rev:
<!-- build:css css/app-name.min.css -->
<link rel="stylesheet" href="lib/bootstrap/bootstrap.min.css"/>
<link rel="stylesheet" href="lib/font-awesome/font-awesome.min.css"/>
<link rel="stylesheet" href="lib/toaster/toaster.css"/>
<link rel="stylesheet" href="css/app.css"/>
<link rel="stylesheet" href="css/custom.css"/>
<link rel="stylesheet" href="css/responsive.css"/>
<!-- endbuild -->
...
<!-- build:js js/app-name.min.js -->
<script src="lib/jquery/jquery-1.10.2.min.js"></script>
<script src="lib/bootstrap/bootstrap.min.js"></script>
<script src="lib/angular/angular.min.js"></script>
<script src="lib/angular/angular-animate.min.js"></script>
<script src="lib/angular/angular-cookies.min.js"></script>
<script src="lib/angular/angular-resource.min.js"></script>
<script src="lib/angular/angular-route.min.js"></script>
<script src="lib/fastclick.min.js"></script>
<script src="lib/toaster/toaster.js"></script>
<script src="lib/webshim/modernizr.min.js"></script>
<script src="lib/webshim/polyfiller.min.js"></script>
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
<!-- endbuild -->
Now you have a Grunt build task that will look at your page for any asset blocks and concatenate/uglify the individual files referenced therein, and then replace the links in that block with one link to a single cache-busted file. This gets you what you had with Bundles.
During development, you don't need to do anything except add or remove assets from these blocks. For production, you just need to run your grunt build task before you package up or deploy your application.