grunt usemin - concat + uglify sourcemap - angularjs

I'm trying to minify my js and css files but i have a problem with source map files.
My app is an angularjs app and before the usemin i need to generate the angular templates.js files and concatenate all js files.
my index.html is
<!-- build:js js/vendor.min.js -->
<script src="../vendor/jquery/dist/jquery.min.js"></script>
<script src="../vendor/underscore/underscore-min.js"></script>
<script src="../vendor/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../vendor/es5-shim/es5-shim.min.js"></script>
<script src="../vendor/json3/lib/json3.min.js"></script>
<script src="../vendor/http/http.min.js"></script>
<script src="../vendor/fs/dist/fs.min.js"></script>
<script src="../vendor/parse/parse.min.js"></script>
<script src="../vendor/event/dist/js/event.min.js"></script>
<script src="../vendor/angular/angular.min.js"></script>
<!-- endbuild -->
<!-- build:js js/app.min.js -->
<script src="../.tmp/concat/app.concat.js"></script>
<!-- endbuild -->
Now the concat task is concatenating my source files
concat: {
options:{
sourceMap:true
},
js: {
src: [
'<%= config.src %>/**/module/**/*.js',
'<%= config.src %>/**/svcs/**/*.js',
'<%= config.src %>/**/ctrls/**/*.js',
'<%= config.src %>/**/dirs/**/*.js',
'<%= config.src %>/**/filters/**/*.js',
'<%= config.src %>/**/model/**/*.js',
'<%= config.src %>/**/prvdrs/**/*.js',
'<%= config.tmp %>/concat/app.templates.js'
],
dest: '<%= config.tmp %>/concat/app.concat.js'
}
},
and the sourcemap (app.concat.js.map) file is correctly generated.
The generated sourcemap is input of the uglify:generated task
uglify:{
generated:{
options:{
sourceMap:{
includeSources: true
},
sourceMapIn:'.tmp/concat/app.concat.js.map'
}
}
},
finally this is the registeredTask for grunt
grunt.registerTask('build',[
'ngtemplates:app',
'concat:js',
'copy_assets',
'less:dev',
'useminPrepare',
'concat:generated',
'uglify:generated',
'cssmin',
'usemin'
]);
The task is runned correctly, anyway the Chrome developer tool doesn't allow me to set brekpoints where I want
as requested here the ngtemplates task
ngtemplates: {
app: {
cwd: '<%= config.src %>',
src: ['**/*.html','!<%= config.src %>/templates/*.html'],
dest: '<%= config.tmp %>/js/app.templates.js'
}
},

uglify:{
generated:{
options:{
sourceMap:{
includeSources: true
},
sourceMapIn:'.tmp/concat/app.concat.js.map'
}
}
},
this won't work because it will ignore anything within "generated" options.
try to rename it to "gruntisdead" or something else. however the "generated" task may run anycase and rewrite your output. so to avoid it just stop use grunt and go to gulp, webpack or something more modern

Related

Grunt serve delete bower_components/angular-i18n from index.html

When I run grunt serve it delete this row from index.html
<script src="bower_components/angular-i18n/angular-locale_it-it.js"></script>
My bower.json is:
{
"name": "operatore-smart",
"version": "0.0.0",
"dependencies": {
"angular": "^1.4.0",
"bootstrap": "^3.3.6",
"angular-animate": "^1.4.0",
"angular-cookies": "^1.4.0",
"angular-resource": "^1.4.0",
"angular-route": "^1.4.0",
"angular-sanitize": "^1.4.0",
"angular-touch": "^1.4.0",
"angular-ui-router": "^0.3.1",
"lodash": "^4.13.1",
"ngToast": "ngtoast#^2.0.0",
"angularjs-dropdown-multiselect": "^1.5.2",
"angular-bootstrap": "^2.0.0",
"angular-ui-date": "^1.0.1",
"angular-momentjs": "^0.2.2",
"angular-i18n": "^1.5.8"
},
"devDependencies": {
"angular-mocks": "^1.4.0"
},
"appPath": "app",
"moduleName": "operatoreSmartApp",
"overrides": {
"bootstrap": {
"main": [
"less/bootstrap.less",
"dist/css/bootstrap.css",
"dist/js/bootstrap.js"
]
}
}
}
I also make bower install and the directory bower_components\angular-i18n is correctly installed.
Can you help me?
index.html
<!doctype html>
<html>
<head>
<base href="/">
<!--<base href="/~opw2er34mart/">-->
<meta charset="utf-8">
<title>Titolo</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<!-- build:css(.) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"/>
<link rel="stylesheet" href="bower_components/ngToast/dist/ngToast.css"/>
<!-- endbower -->
<!-- endbuild -->
<!-- build:css({.tmp,app}) styles/main.css -->
<link rel="stylesheet" href="styles/main.css">
<link rel="stylesheet" href="styles/myCss.css">
<link rel="stylesheet" href="island/css/island.css">
<link rel="stylesheet" href="user/css/user.css">
<link rel="stylesheet" href="dashboard/css/authentication.css">
<link rel="stylesheet" href="calendar/css/calendar.css">
<!-- endbuild -->
</head>
<body ng-app="SmartApp">
<toast></toast>
<!--[if lte IE 8]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade
your browser</a> to improve your experience.</p>
<![endif]-->
<div data-ng-include="'UI/navigation.template.html'"></div>
<!-- Add your site or application content here -->
<div class="container-fluid">
<div class="row">
<div class="col-xs-12" ui-view></div>
</div>
</div>
<div class="footer-style" data-ng-include="'UI/footer.template.html'"></div>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
<!--<script>-->
<!--!function (A, n, g, u, l, a, r) {-->
<!--A.GoogleAnalyticsObject = l, A[l] = A[l] || function () {-->
<!--(A[l].q = A[l].q || []).push(arguments)-->
<!--}, A[l].l = +new Date, a = n.createElement(g),-->
<!--r = n.getElementsByTagName(g)[0], a.src = u, r.parentNode.insertBefore(a, r)-->
<!--}(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');-->
<!--ga('create', 'UA-XXXXX-X');-->
<!--ga('send', 'pageview');-->
<!--</script>-->
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-touch/angular-touch.js"></script>
<script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
<script src="bower_components/lodash/lodash.js"></script>
<script src="bower_components/ngToast/dist/ngToast.js"></script>
<script src="bower_components/angularjs-dropdown-multiselect/src/angularjs-dropdown-multiselect.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<script src="bower_components/jquery-ui/jquery-ui.js"></script>
<script src="bower_components/angular-ui-date/dist/date.js"></script>
<script src="bower_components/moment/moment.js"></script>
<script src="bower_components/angular-momentjs/angular-momentjs.js"></script>
<script src="bower_components/angular-i18n/angular-locale_it-it.js"></script>
<!-- endbower -->
<!-- endbuild -->
<!-- build:js({.tmp,app}) scripts/scripts.js -->
<script>
_.contains = _.includes;
</script>
<script src="app.js"></script>
<script src="app.routes.js"></script>
<script src="dashboard/controllers/dashboard.controller.js"></script>
<script src="authentication/services/authentication.service.js"></script>
<script src="authentication/controllers/login.controllers.js"></script>
<script src="profile/controllers/profile.controller.js"></script>
<script src="profile/services/user-profile.service.js"></script>
<script src="profile/controllers/notifica.controller.js"></script>
<script src="profile/services/notifica.service.js"></script>
<script src="changepsw/controllers/changepsw.controller.js"></script>
<script src="changepsw/services/change-psw.service.js"></script>
<script src="alarm/controllers/alarm.controller.js"></script>
<script src="alarm/services/alarm.service.js"></script>
<script src="alarm/controllers/alarm.avvisi.controller.js"></script>
<script src="alarm/services/alarm.avvisi.service.js"></script>
<script src="island/controllers/island.controller.js"></script>
<script src="island/controllers/island.groups.controller.js"></script>
<script src="island/services/island.groups.service.js"></script>
<script src="island/services/island.service.js"></script>
<script src="island/controllers/island.accessories.controller.js"></script>
<script src="island/services/island.accessories.service.js"></script>
<script src="island/controllers/island.availabilities.controller.js"></script>
<script src="island/services/island.availabilities.service.js"></script>
<!-- USER COMPONENTS-->
<script src="user/services/user.service.js"></script>
<script src="user/controllers/user.controller.js"></script>
<script src="user/controllers/user-modal.controller.js"></script>
<script src="user/controllers/general-info.controller.js"></script>
<script src="user/controllers/job.controller.js"></script>
<script src="user/controllers/documents.controller.js"></script>
<script src="user/controllers/other-info.controller.js"></script>
<script src="user/controllers/courses.controller.js"></script>
<script src="user/controllers/vaccinations.controller.js"></script>
<script src="user/controllers/holidays.controller.js"></script>
<script src="calendar/controllers/calendar.controllers.js"></script>
<script src="calendar/services/calendar.service.js"></script>
<script src="utils/directives/my-checkbox.directive.js"></script>
<script src="calendar/controllers/island-calendar.controller.js"></script>
<script src="calendar/controllers/giustificativi.controller.js"></script>
<script src="utils/directives/select-option.directive.js"></script>
<script src="calendar/services/giustificativi.service.js"></script>
<!-- endbuild -->
</body>
</html>
Gruntfile.js
// Generated on 2016-06-24 using generator-angular 0.15.1
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Automatically load required Grunt tasks
require('jit-grunt')(grunt, {
useminPrepare: 'grunt-usemin',
ngtemplates: 'grunt-angular-templates',
cdnify: 'grunt-google-cdn'
});
// Configurable paths for the application
var appConfig = {
app: require('./bower.json').appPath || 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
yeoman: appConfig,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= yeoman.app %>/**/*.js'],
tasks: ['newer:jshint:all', 'newer:jscs:all'],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
jsTest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
},
styles: {
files: ['<%= yeoman.app %>/**/*.css'],
tasks: ['newer:copy:styles', 'postcss']
},
gruntfile: {
files: ['Gruntfile.js']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= yeoman.app %>/**/*.html',
'.tmp/**/*.css',
'<%= yeoman.app %>/**/*.css',
'<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
livereload: {
options: {
open: true,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect().use(
'/app/styles',
connect.static('./app/styles')
),
connect.static(appConfig.app)
];
}
}
},
test: {
options: {
port: 9001,
middleware: function (connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use(
'/bower_components',
connect.static('./bower_components')
),
connect.static(appConfig.app)
];
}
}
},
dist: {
options: {
open: true,
base: '<%= yeoman.dist %>'
}
}
},
// Make sure there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/**/*.js'
]
},
test: {
options: {
jshintrc: 'test/.jshintrc'
},
src: ['test/spec/{,*/}*.js']
}
},
// Make sure code styles are up to par
jscs: {
options: {
config: '.jscsrc',
verbose: true
},
all: {
src: [
'Gruntfile.js',
'<%= yeoman.app %>/**/*.js'
]
},
test: {
src: ['test/spec/{,*/}*.js']
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= yeoman.dist %>/{,*/}*',
'!<%= yeoman.dist %>/.git{,*/}*'
]
}]
},
server: '.tmp'
},
// Add vendor prefixed styles
postcss: {
options: {
processors: [
require('autoprefixer-core')({browsers: ['last 1 version']})
]
},
server: {
options: {
map: true
},
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the app
wiredep: {
app: {
src: ['<%= yeoman.app %>/index.html'],
ignorePath: /\.\.\//
},
test: {
devDependencies: true,
src: '<%= karma.unit.configFile %>',
ignorePath: /\.\.\//,
fileTypes:{
js: {
block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
detect: {
js: /'(.*\.js)'/gi
},
replace: {
js: '\'{{filePath}}\','
}
}
}
}
},
// Renames files for browser caching purposes
filerev: {
dist: {
src: [
'<%= yeoman.dist %>/**/*.js',
'<%= yeoman.dist %>/**/*.css',
'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
'<%= yeoman.dist %>/styles/fonts/*'
]
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
html: '<%= yeoman.app %>/index.html',
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
// Performs rewrites based on filerev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.dist %>/**/*.html'],
css: ['<%= yeoman.dist %>/**/*.css'],
js: ['<%= yeoman.dist %>/**/*.js'],
options: {
assetsDirs: [
'<%= yeoman.dist %>',
'<%= yeoman.dist %>/images',
'<%= yeoman.dist %>/styles'
],
patterns: {
js: [[/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']]
}
}
},
// The following *-min tasks will produce minified files in the dist folder
// By default, your `index.html`'s <!-- Usemin block --> will take care of
// minification. These next options are pre-configured if you do not wish
// to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= yeoman.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= yeoman.dist %>/scripts/scripts.js': [
// '<%= yeoman.dist %>/scripts/scripts.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.{png,jpg,jpeg,gif}',
dest: '<%= yeoman.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.app %>/images',
src: '{,*/}*.svg',
dest: '<%= yeoman.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseWhitespace: true,
conservativeCollapse: true,
collapseBooleanAttributes: true,
removeCommentsFromCDATA: true,
removeComments: true
},
files: [{
expand: true,
cwd: '<%= yeoman.dist %>',
src: '**/*.html',
dest: '<%= yeoman.dist %>'
}]
}
},
ngtemplates: {
dist: {
options: {
module: 'operatoreSmartApp',
htmlmin: '<%= htmlmin.dist.options %>',
usemin: 'application/application.js'
},
cwd: '<%= yeoman.app %>',
src: '**/*.html',
dest: '.tmp/templateCache.js'
}
},
// ng-annotate tries to make the code safe for minification automatically
// by using the Angular long form for dependency injection.
ngAnnotate: {
dist: {
files: [{
expand: true,
cwd: '.tmp/concat/scripts',
src: '*.js',
dest: '.tmp/concat/scripts'
}]
}
},
// Replace Google CDN references
cdnify: {
dist: {
html: ['<%= yeoman.dist %>/*.html']
}
},
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'**/*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*'
]
}, {
expand: true,
cwd: '.tmp/images',
dest: '<%= yeoman.dist %>/images',
src: ['generated/*']
}, {
expand: true,
cwd: 'bower_components/bootstrap/dist',
src: 'fonts/*',
dest: '<%= yeoman.dist %>'
}]
},
styles: {
expand: true,
cwd: '<%= yeoman.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Run some tasks in parallel to speed up the build process
concurrent: {
server: [
'copy:styles'
],
test: [
'copy:styles'
],
dist: [
'copy:styles',
'imagemin',
'svgmin'
]
},
// Test settings
karma: {
unit: {
configFile: 'test/karma.conf.js',
singleRun: true
}
}
});
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'postcss:server',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run(['serve:' + target]);
});
grunt.registerTask('test', [
'clean:server',
'wiredep',
'concurrent:test',
'postcss',
'connect:test',
'karma'
]);
grunt.registerTask('build', [
'clean:dist',
'wiredep',
'useminPrepare',
'concurrent:dist',
'postcss',
'ngtemplates',
'concat',
'ngAnnotate',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'newer:jscs',
'test',
'build'
]);
};
Your build uses wiredep to replace everything between
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
and
<!-- endbower -->
<!-- endbuild -->
by a single script loading scripts/vendor.js generated by the build and containing all the main js files found in the bower components. So you need to add your additional file outside of these comments, or to add your angular-locale_it-it.js to the main files of the angular-i18n dependency, ad explained in the wiredep documentation.

How can I add angular-chart to yeoman generated angular app?

I think it can be more generic question. How can I add custom (vendor) scripts to yeoman yo generated app. I installed angular charts with npm (npm install angular-chart --save). I add scripts to index.html.
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="bower_components/angular-animate/angular-animate.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.js"></script>
<script src="bower_components/angular-resource/angular-resource.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="bower_components/angular-touch/angular-touch.js"></script>
<!-- endbower -->
<script src="node_modules/chart.js/Chart.min.js"></script>
<script src="node_modules/angular-chart.js/dist/angular-chart.min.js"></script>
<!-- endbuild -->
But making distribution with grunt does not create proper minified script.
scripts.226f19b7.js:1 Uncaught Error: Chart.js library needs to be included, see http://jtblin.github.io/angular-chart.js/
Include the library in your grunt task build (Gruntfile.js)
You will find this task or something like it:
grunt.registerTask('build', [
'clean:dist',
'wiredep',
'useminPrepare',
'concurrent:dist',
'postcss',
'concat',
'copy:dist',
'cdnify',
'cssmin',
'uglify',
'filerev',
'usemin',
'htmlmin'
]);
I think you would find your solution in copy:dist task
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= yeoman.app %>',
dest: '<%= yeoman.dist %>',
src: [
'*.{ico,png,txt}',
'*.html',
'images/{,*/}*.{webp}',
'styles/fonts/{,*/}*.*'
]
}, {
expand: true,
cwd: 'bower_components/bootstrap/dist',
src: 'fonts/*',
dest: '<%= yeoman.dist %>'
},
{
expand:true,
cwd:'node_modules/yourlib/,
src:'*',
dest:'<%=yeoman.dist %>'
}
Thanks to webenegized I finally found the problem and the solution.
At first, it should work out of the box!! No gruntfile.js modification are needed or any other action. Just npm install dependecies, put the required script tag(s) in the index.html and voila. The magic of yeoman generator.
The error I encouter was caused by the copy/paste of incorrect script tags values from the example on the angular-chart.js website (see: installation section). The site example states:
<script src="node_modules/chart.js/Chart.min.js"></script>
but the real path should be
<script src="node_modules/chart.js/dist/Chart.min.js"></script> (dist folder is missing).
I should have spotted this because the error I've got clearly show that angular-chart.js was included and the complaint was about its dependency (chart.js). It turns out I'm less perceptive that I think.

Grunt usemin and absolute (nonexistent) file paths

My directory structure looks like this, I have an absolute path /static mapped to my public dir
+public/
+--app/
+--dist/
|--Gruntfile.js
|..
|..
Currently, everything builds fine and I wind up with my minified/rev'd files in dist but the index.html file contains relative paths like:
<script src="some-file.56a75bad.js"></script>
When I need them to be:
<script src="/static/dist/some-file.56a75bad.js"></script>
Can't seem to figure out how to achieve this, everything I've tried winds up giving my the right file paths but not the rev'd file, i.e:
<script src="/static/dist/some-file.js"></script>
My solution: copy task moves all scripts to a .tmp folder. uglify task then runs and outputs to a folder hierarchy in .tmp that the absolute paths to resolve to. After those 2 tasks are run I have a folder structure that looks like this (mid build):
public/
+--.tmp/
+--static/
+--dist/
|--application.min.js
|--dependencies.min.js
+--app/
+--bower_components/
+--dist/
|--Gruntfile.js
|--index.html
A little piece of my index.html
<!-- build:js /static/dist/dependencies.min.js -->
<script src="/static/dist/dependencies.min.js"></script>
<!-- endbuild -->
<!-- build:js /static/dist/application.min.js -->
<script src="/static/dist/application.min.js"></script>
<!-- endbuild -->
Now it's business as usual, the useminPrepare filerev and usemin tasks are run.
And my GruntFile:
module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
grunt.config.init({
useminPrepare: {
html: 'dist/index.html',
options: {
dest: './dist'
}
},
usemin:{
html:['dist/index.html'],
options: {
assetsDirs: ['.tmp']
}
},
copy:{
html: {
src: './index.html',
dest: 'dist/index.html'
},
javascripts: {
cwd: '',
src: 'app/scripts/**',
dest: '.tmp',
expand: true
}
},
uglify: {
build: {
options: {
mangle: true
},
files: {
'.tmp/static/dist/application.min.js': ['.tmp/app/**/*.js'],
'.tmp/static/dist/dependencies.min.js': [
'bower_components/jquery/dist/jquery.js',
'bower_components/angular/angular.js'
// All my other 3rd party libs, I realized this can be done in index.html but there's environmental constraints making that not possible
]
}
}
},
filerev: {
dist: {
src: ['.tmp/static/dist/application.min.js', '.tmp/static/dist/dependencies.min.js'],
dest: 'dist'
}
}
});
grunt.registerTask('build',[
'copy:javascripts',
'copy:html',
'uglify',
'useminPrepare',
'filerev',
'usemin'
]);
};

ng-boilerplate grunt scripts compilation

I would like to be able to duplicate ng-boilerplate's script compilation process in my own app, but I am unable to get it working.
I am referring to having this line in index.html be compiled into a list of all the scripts in my app:
<!-- compiled JavaScript --><% scripts.forEach( function ( file ) { %>
<script type="text/javascript" src="<%= file %>"></script><% }); %>
I added the filterForJS function and registered the multi task in my gruntfile.js, but it is not working :(
Have you added the options for the index task?
```
/**
* The `index` task compiles the `index.html` file as a Grunt template. CSS
* and JS files co-exist here but they get split apart later.
*/
index: {
/**
* During development, we don't want to have wait for compilation,
* concatenation, minification, etc. So to avoid these steps, we simply
* add all script files directly to the `<head>` of `index.html`. The
* `src` property contains the list of included files.
*/
build: {
dir: '<%= build_dir %>',
src: [
'<%= vendor_files.js %>',
'<%= build_dir %>/src/**/*.js',
'<%= html2js.common.dest %>',
'<%= html2js.app.dest %>',
'<%= vendor_files.css %>',
'<%= recess.build.dest %>'
]
},
/**
* When it is time to have a completely compiled application, we can
* alter the above to include only a single JavaScript and a single CSS
* file. Now we're back!
*/
compile: {
dir: '<%= compile_dir %>',
src: [
'<%= concat.compile_js.dest %>',
'<%= vendor_files.css %>',
'<%= recess.compile.dest %>'
]
}
},
```

How to use well ngmin for annotate angularjs files and usemin to produce a dist file

I'm using a yeoman web app template that runs an AngularJS app.
usemin is great, but AngularJS files must be pre-processed with ngmin to be annotated before being uglified and minified by usemin.
I can produce a single, concatenated file of annotated AngularJS controllers, directives, services, etc. using ngmin.
ngmin: {
build: {
src: ['<%= yeoman.app %>/js/one.js','<%= yeoman.app %>/js/two.js'],
dest: '<%= yeoman.dist %>/ng/annotated.js'
}
}
Basically I run a build that successfully created annotated.js.
What I want is declare annotated.js file in index.html to inform usemin to use that file only for distribution, not the ones I mention for development.
<!-- build:js js/app.min.js --> //annotated.js only must be processed instead of those 2 files.
<script src="js/one.js" type="text/javascript"></script>
<script src="js/two.js" type="text/javascript"></script>
<!-- endbuild -->
For reference, my usemin config:
useminPrepare: {
options: {
dest: '<%= yeoman.dist %>'
},
html: '<%= yeoman.app %>/index.html'
},
usemin: {
options: {
dirs: ['<%= yeoman.dist %>']
},
html: ['<%= yeoman.dist %>/{,*/}*.html'],
css: ['<%= yeoman.dist %>/css/{,*/}*.css']
}
For reference, my build task:
grunt.registerTask('build', [
'clean:dist',
'useminPrepare',
'concat',
'cssmin',
'ngmin',
'uglify',
'copy:dist',
'rev',
'usemin'
]);
How can I achieve it?
So, you used yo webapp to generator an application that you then plugged Angular in to? For future Angular apps you create (or if it's not too late for this one), there's a generator for that! https://github.com/yeoman/generator-angular
Here is a link and some code that shows how the ngmin task is pre-configured with the Angular generator:
https://github.com/yeoman/generator-angular/blob/v0.4.0/templates/common/Gruntfile.js#L326-335
ngmin: {
dist: {
files: [{
expand: true,
cwd: '<%= yeoman.dist %>/scripts',
src: '*.js',
dest: '<%= yeoman.dist %>/scripts'
}]
}
}
Plug that in, tweak as necessary, and let me know if it works!

Resources