Grunt usemin and absolute (nonexistent) file paths - angularjs

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'
]);
};

Related

grunt usemin - concat + uglify sourcemap

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

Coursera - AngularJS week 2 Issue js & css file isn't created after i type grunt command

I'm new in using Grunt tool, I was doing the steps like the video said, but i faced some errors and started from the whole beginning again, but now i'm facing this issue, when i type the command "grunt" in the CMD in the directory of the project folder i get everything good, but there is no JavaScript file created in the distribution folder directory "dist/scripts", and even the Uglify is not generated.
In the video after the instructor typed the command grunt a JS file created in dist/scripts directory with name "main.6c5adb2140e008f7bb85.js", and css file created in dist/styles directory with name "main.d1901e133950f2e3aeae.css", and also in his terminal it was written replaced 1 reference to assets and Uglify generated like in the picture:
Instead i get replaced 0 references to assets and the uglify is not generated:
I did all the installation command that in the video by order, and i created all the files (package.json, Gruntfile.js, app.js, .jshintrc)
after that i added the usemin to the require jit-grunt
and added it to the registerTask. Here's the Gruntfile.js source code:
'use strict';
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'
});
// Define the configuration for all the tasks
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: {
src: [
'Gruntfile.js',
'app/scripts/{,*/}*.js'
]
}
},
useminPrepare: {
html: 'app/menu.html',
options: {
dest: 'dist'
}
},
// Concat
concat: {
options: {
separator: ';'
},
// dist configuration is provided by useminPrepare
dist: {}
},
// Uglify
uglify: {
// dist configuration is provided by useminPrepare
dist: {}
},
cssmin: {
dist: {}
},
// Filerev
filerev:{
options: {
encoding: 'utf8',
algorithm: 'md5',
length: 20
},
release: {
// filerev: release hashes(md5) all assets (images, js and css)
// in dist directory
files: [{
src: [
'dist/scripts/*.js',
'dist/styles/*.css',
]
}]
}
},
// Usemin
// Replace all assets with their revved version in html and css files.
// options.assetDirs contains the directories for finding the assets
// according to their relative paths
usemin: {
html: ['dist/*.html'],
css: ['dist/styles/*.css'],
options: {
assetsDirs: ['dist', 'dist/styles']
}
},
copy: {
dist: {
cwd: 'app',
src: [ '**','!styles/**/*.css','!scripts/**/*.js' ],
dest: 'dist',
expand: true
},
fonts: {
files: [
{
//for bootstrap fonts
expand: true,
dot: true,
cwd: 'bower_components/bootstrap/dist',
src: ['fonts/*.*'],
dest: 'dist'
}, {
//for font-awesome
expand: true,
dot: true,
cwd: 'bower_components/font-awesome',
src: ['fonts/*.*'],
dest: 'dist'
}
]
}
},
clean: {
build: {
src: [ 'dist/']
}
}
});
grunt.registerTask('build', [
'clean',
'jshint',
'useminPrepare',
'concat',
'cssmin',
'uglify',
'copy',
'filerev',
'usemin'
]);
grunt.registerTask('default',['build']);
};
Need help please !!
it's look like there is no mistake in the commands that 've wrote but the mistake here is the name of the html in my project folder is not the same name which is "menu.html" and i wrote it in Gruntfile "meun.html" that's why it doesn't create the js & css file !!

AngularJS Grunt load JS file with dynamic query string parameter

I am developing application with yeoman + grunt + angularJs.
To load the JS file only when require I have added JS file path inside calendar.html.
To achieve this I have modified grunt.js and html file.
Grunt.JS file
useminPrepare: {
html: ['<%= yeoman.app %>/index.html', '<%= yeoman.app %>/views/*.html'],
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
}
Modified calendar.html file
<!-- build:js({.tmp,app}) scripts/fullcalendar.js -->
<script src="scripts/plugins/fullcalendar/fullcalendar.js"></script>
<!-- endbuild -->
This solution is working properly. But now whenever I load my Calendar page a fresh request goes to fullcalenar.js with dynamic query string parameter like this
http://localhost/scripts/fullcalendar.a13f9b72f8.js?_=1422010995753
This number (1422010995753) increments every time I make a request which stop browsers from caching the file.
I believe it is because of assetCacheBuster but here is my configuration of Grunt. And I have set that to false along with debugInfo.
compass: {
options: {
javascriptsDir: '<%= yeoman.app %>/scripts',
fontsDir: '<%= yeoman.app %>/styles/fonts',
importPath: './bower_components',
relativeAssets: false,
assetCacheBuster: false,
raw: 'Sass::Script::Number.precision = 10\n'
},
server: {
options: {
debugInfo: false
}
}
}
My problem is, I want to cache the fullcalendar.js file and don't want to fetch the fresh JS file every time.
If I move above calendar.html code inside index.html file application works properly and cache the file without combining with rest of the js. But if I add that code inside index.html, the fullcalendar.js file will get loaded with first page itself.
A late answer: grunt-cachebuster-querystring

grunt task to modify yeoman angular index.html

yo angular sets up a basic scaffold for writing angular apps. So in index.html we have code as follows:
<!-- build:css(.) styles/vendor.css -->
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.css" />
<!-- endbower -->
<!-- endbuild -->
I am looking for a task that would remove those lines and inject the correct location of the files. For e.g.:
<link rel="stylesheet" href="css/bootstrap.css" />
<link rel="stylesheet" href="css/bootstrap-theme.css" />
Or is there some alternate way to deal with this...like for e.g. have the watch task create different versions of index.html, say index.html.fooTarget; it gets updated with the correct paths for that target; and then when it comes to the grunt task have the latter file copied appropriately.
What can be done to deal with this?
Maybe you should let the paths be as they are since CSS files are bower dependencies, too. Copy the dependencies to a directory with the same relative path?
But if you will, I think this will help you modify your grunt tasks.
I assume you have (at least) the following in your package.json.
{
"name": "app",
"version": "0.0.1",
"dependencies": {},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-contrib-copy": "~0.4.1",
"grunt-text-replace": "0.3.11"
}
}
Then the minimal copy & replace tasks could look like the following in your Gruntfile.js (you can combine copy and replace by using grunt-contrib-copy alone, if you will).
'use strict';
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-text-replace');
grunt.initConfig({
src: 'src',
dest: 'dest',
copy: {
dev: {
expand: true,
cwd: '<%= src %>',
src: '{,*/}*.html',
dest: '<%= dest %>/'
}
},
replace: {
dev: {
src: ['<%= dest %>/{,*/}*.html'],
overwrite: true,
replacements: [{
from: 'bower_components/bootstrap/dist/css',
to: 'css'
}]
}
}
});
grunt.registerTask('prepare', function(val) {
var target = val || 'dev';
grunt.task.run([
'copy:' + target,
'replace:' + target
]);
});
};
Now when you run prepare task with desired target it will copy all HTML files from src to dest directory and have desired CSS paths replaced, leaving original files intact.
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
--> will be replaced as -->
<link rel="stylesheet" href="css/bootstrap.css" />

Grunt-usemin: Not generating my new index.html but it is concatenating and minifying my scripts

I need your help :)
I am trying to use usemin to build my angular app.
Basically I want to generate a new index.html that will have a reference to just one .js file that is properly minified.
The app.js file is being generated correctly, but my new index.html is not.
I am pretty new to grunt and usemin, but here is my gruntfile:
grunt.initConfig({
pkg: grunt.file.readJSON('bower.json'),
useminPrepare: {
html: 'public/index.html',
options: {
dest: 'dist'
}
},
concat: {
generated: {
files: [
{
dest: '.tmp/concat/js/app.js',
src: ['public/**/*.js', '!public/bower_components/**']
}
]
}
},
uglify: {
generated: {
files: [
{
dest: 'dist/js/app.js',
src: [ '.tmp/concat/js/app.js' ]
}
]
}
}
});
grunt.registerTask('build', [
'useminPrepare',
'concat:generated',
'uglify:generated',
'usemin'
]);
Here is the relevant section of my index.html:
<!-- build:js js/app.js -->
<script src="app.js"></script>
<script src="domain/domain.js"></script>
<script src="domain/landingPage/landingPageController.js"></script>
...
<!-- endbuild -->
My folder structure is:
+- public
| +- index.html
| +- domain
| +- js files
+- gruntfile
Thanks for the help in advance!!
I took this file from #KevinB and created a simpler one that did what I wanted.
There are still some rough edges, but it does answer the question.
grunt.initConfig({
pkg: grunt.file.readJSON('bower.json'),
clean: [ 'dist' ],
copy: {
build: {
files: [
{
expand: true,
cwd: 'public/',
src: [ '**', '!**/**/*.js' ],
dest: 'dist'
}
]
}
},
processhtml: {
dist: {
files: {
'dist/index.html': ['dist/index.html']
}
}
},
concat: {
generated: {
files: [
{
dest: 'dist/js/app.js',
src: ['public/**/*.js', '!public/bower_components/**']
}
]
}
},
uglify: {
generated: {
files: [
{
dest: 'dist/js/app.js',
src: [ 'dist/js/app.js' ]
}
]
}
}
});
grunt.registerTask('build', [
'clean',
'copy',
'processhtml',
'concat:generated',
'uglify:generated'
]);

Resources