AngularJS Grunt load JS file with dynamic query string parameter - angularjs

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

Related

grunt build failed to load template

I created a yeoman angular project that is not building properly. After I run run the production build (dist folder), I get this error:
Failed to load template: /bundles/craigslist/main.html
It seems to be copying the files, but since the html files get turned into a string that lives in dist/scripts.js, it throws an error when trying to find /bundles/craigslist/main.html
In my "/dist/scripts.js":
.config(["$routeProvider", function(a) {
a.when("/", {
templateUrl:"/bundles/craigslist/main.html",
controller:"CraigslistMainCtrl",
controllerAs:"craigslist_main_root"
})
Info if necessary:
instead of the pattern /scripts and /views, I use bundles that organize similar files together, regardless of extension. For example, I have a /bundles/craigslist folder, which has the craigslist templates, service and routes. I'm trying to adjust my Gruntfile.js to account for this.
This is my grunt file: https://gist.github.com/ivansifrim/f632832a4ba8f44bf828b5d88066a0ce
This is my folder structure:
I tried to apply what was discussed here Angular / grunt failed to load template without any luck.
Try :
usemin: {
html: ['<%= yeoman.dist %>/**/*.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
js: ['<%= yeoman.dist %>/scripts/{,*/}*.js', '<%= yeoman.dist %>/bundles/{,*/}*.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']]
}
}
}

Angular JS ui-tinymce

I use ui-tinymce module in angular project. In one controller are called tinymce.execCommand('mceRemoveControl', true, 'ntContent'); and this works fine. But after grunt build command I get the following error: ReferenceError: tinymce is not defined. Can anyone help with this ?
I had the same problem with angular-ui-tinymce module, I fixed this by making sure that the file is included.
<script src="bower_components/tinymce-dist/tinymce.min.js"></script>
<script src="bower_components/angular-ui-tinymce/src/tinymce.js"></script>
This scripts are inserted in the index.html file bower install angular-ui-tinymce and also the source code is downloaded and placed at the appropriate location.
Also when you run grunt build on the copy task it will not copy the files needed from the /tinymce-distfolder and a solution is to manually add to the copy task to copy the folders you need. I had to copy the /skins /themes /plugins folders directly into the dist/scripts folder by inserting the following code into the grunt.js file at the copy task:
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
...
}, {
...
}, {
expand: true,
cwd: 'bower_components/tinymce-dist/themes/modern/',
src: ['**'],
dest: '<%= yeoman.dist %>/scripts/themes/modern/'
}, {
expand: true,
cwd: 'bower_components/tinymce-dist/skins/',
src: ['**'],
dest: '<%= yeoman.dist %>/scripts/skins/'
}, {
expand: true,
cwd: 'bower_components/tinymce-dist/plugins/link/',
src: ['**'],
dest: '<%= yeoman.dist %>/scripts/plugins/link/'
}]
},
styles: {
...
}
}
This is not the best solution ever but it worked for me, hope it helps somebody.

Grunt usemin and cache manifest

I'm building an angular app with grunt which uses cache manifest.
My problem is that after concatenation and minification of all my js files in one, the manifest.cfm doesn't get rewritten and that makes the paths in it incorrect.
Here is some of my Gruntfile.js :
// 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',
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
options: {
dest: '<%= yeoman.dist %>',
flow: {
html: {
steps: {
js: ['concat', 'uglifyjs'],
css: ['cssmin']
},
post: {}
}
}
}
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
html: ['<%= yeoman.dist %>/{,*/}*.html','<%= yeoman.dist %>/{,*/}*.tpl.html', '<%= yeoman.dist %>/views/templates{,*/}*.tpl.html'],
css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
options: {
assetsDirs: ['<%= yeoman.dist %>', '<%= yeoman.dist %>/images', '<%= yeoman.dist %>/images/icons-app']
}
},
I know the question is a bit old, but I just solved something similar, and could not find many answers to help. Your best bet is to continue using filerev and use a grunt manifest creator like grunt-manifest. You want the file names to change when they are updated (with filerev) so the manifest file will change as well. That is the only way the application cache will know it needs to update.
After you install grunt-manifest, a config like this in your grunt file should do what your asking:
manifest: {
generate: {
options: {
basePath: 'app/',
network: ['*'],
preferOnline: true
},
src: [
'scripts/*.js',
'styles/*.css',
'images/*.*',
'views/{,*/}*.html'
],
dest: 'dist/cache.manifest'
}
}
More Info: http://bnlconsulting.com/blog/the-browser-cache-and-angular
I ended up hand-writing the new paths in manifest.cfm before building. I'm not sure there is actually a way to get it automatically rewritten by any grunt task.
you can comment the "filerev" task form your grunt build one. This will spare you the rewriting after a new build.
Maybe necromacing this thread but there is: https://github.com/JoshSchreuder/grunt-manifest-generator
It will scan a given html file and automatically include all javascript/css/html files within.

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