I am working on the same solution, and have found pretty good luck with the following tools:
grunt-contrib-concat This can concatenate files from one location into a single file in another. You can either specify specific files like this:
files: {
'dist/app.concat.js': ['app/modules/nav.js', 'app/modules/user.js']
}
or you can use the globbing syntax to select multiple (and even exclude as well) like this:
files: {
'dist/app.concat.js': [
'app/**/*.js',
'!app/vendor/**/*.js'
] // this excludes anything from the vendor folder being added
}
Here is a full example
concat: {
dist: { // task name, so you call this with 'grunt concat:dist'. You can have different sections under concat for different builds
files: {
'dist/app.concat.js': ['app/**/*.js',
'!app/vendor/**/*.js',
'!app/test/**/*.js'
], // adds all .js files, but excludes anything in vendor and test
'dist/vendor.concat.js': ['app/vendor/**/*.js'],
'dist/app.concat.css': ['app/styles/**/*.css']
}
}
grunt-contrib-copy
This is a simple one that lets you copy from 1 place to another. You can also use globbing if you want to pull an entire directory structure over (src: [app/**/*.*]
)
copy: {
dist: {
files: [
{
src: ['app/index.html'],
dest: 'dist/'
}
}
This is the one that will help you with dynamically filling out your index.html (or whatever) with references to the correct files. It's useage is pretty straight forward: you add some HTML comments to your index.html (or whatever) and tell scriptlinker to look for them. It will then search through whatever set of files you point it to and dynamically add a reference to those files, within the script tags you give it. I'm using it to load CSS files at the top, then .js files at the bottom:
scriptlinker: {
distCSS: {
options: {
startTag: '<!--CSS SCRIPTS-->',
endTag: '<!--CSS SCRIPTS END-->',
fileTmpl: '\n<link rel="stylesheet" type="text/css" href="%s" />',
appRoot: 'app/'
},
files: {
'dev/app/index.html': ['dist/**/*.css']
}
},
distJS: {
options: {
startTag: '<!--JS SCRIPTS-->',
endTag: '<!--JS SCRIPTS END-->',
fileTmpl: '\n<script src="%s"></script>',
appRoot: 'app/'
},
files: {
'dev/app/index.html': ['dist/vendor/*.js']
},
}
}
So you can see, you tel it what tags to look for, what template to use, and what files or directories to look at. It will turn this:
<html ng-app="ngAD">
<head>
<!--CSS SCRIPTS--><!--CSS SCRIPTS END-->
</head>
<body>
<div class="container">... my app stuff...</div>
<!--JS SCRIPTS--><!--JS SCRIPTS END-->
</body>
</html>
into this:
<html ng-app="ngAD">
<head>
<!--CSS SCRIPTS-->
<link rel="stylesheet" type="text/css" href="styles/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="modules/navbar/navbar.css" />
<link rel="stylesheet" type="text/css" href="styles/jscrollpane.css" />
<link rel="stylesheet" type="text/css" href="styles/styles.app.css" /><!--CSS SCRIPTS END-->
</head>
<body>
<div class="container">... my app stuff...</div>
<!--JS SCRIPTS-->
<script src="vendor/jquery.min.js"></script>
<script src="vendor/angular.min.js"></script>
<script src="vendor/vendor.concat.js"></script>
<script src="common/common.dist.js"></script>
<script src="modules/modules.dist.js"><!--JS SCRIPTS END-->
</body>
</html>
For completeness sake, I'll also point you towards grunt-usemin... it is popular and has similar functionality to scriptLinker... you may like that better. I'm still getting cachebusting setup but I'm working with cacheBust (grunt-cache-bust) and so far it seems to be doing what I want. Let me know if you have any specific issues, I may be able to give more specific feedback.