Grunt Uglify wildcard and versioning
Seems to be there are some additional options being enabled which cause the above error.
I have corrected those and did some changes.
Run the below grunt file and see whether you can execute without any errors.
module.exports = function(grunt) {
grunt.initConfig({
clean : [ 'dest/js' ],
uglify : {
options : {
report : 'min',
mangle : true
},
my_target : {
files : [ {
src : 'src/js/*.js',
dest : 'dest/js/main.min.js'
} ]
}
},
cssmin : {
options : {
report : 'min'
},
minify : {
expand : true,
cwd : 'src/css',
src : '**/*.css',
dest : 'dest/css',
}
},
imagemin : {
dynamic : {
options : {
optimizationLevel : 7
},
files : [ {
expand : true,
cwd : 'src/assets',
src : [ '**/*.{png,jpg,gif}' ],
dest : 'dest/assets'
} ]
}
},
htmlmin : {
mini : {
options : {
removeComments : true,
collapseWhitespace : true,
collapseBooleanAttributes : true,
removeAttributeQuotes : true,
removeRedundantAttributes : true,
removeEmptyAttributes : true,
useShortDoctype : true
},
files : [ {
expand : true,
cwd : 'src',
src : '**/*.html',
dest : 'dest'
} ]
}
},
versioning : { // Task
options : { // Task options
cwd : 'public',
outputConfigDir : 'public/config'
},
dist : { // Target
options : { // Target options
},
files : [ {
assets : '<%= uglify.my_target.files %>',
key : 'global',
dest : 'dest/js',
type : 'js',
ext : '.js'
} ]
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-static-versioning');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.loadNpmTasks('grunt-contrib-htmlmin');
grunt.registerTask('default', [ 'clean', 'uglify', 'cssmin', 'imagemin',
'htmlmin', 'versioning' ]);
}
How can I insert a version number to index.html when building with Grunt?
I ended up keeping it simple and used the grunt-text-replace plugin to replace the placeholder (@@BUST@@) with a timestamp.
replace: {
bust: {
src: ['./target/*.html'],
overwrite: true, // overwrite matched source files
replacements: [
{
from: '@@BUST@@',
to: "<%= new Date().getTime() %>"
}
]
}
}
Grunt usemin, get final path of compressed files to allow preload
The answer is no in grunt-usemin
, but in one of the dependencies: grunt-filerev
. This last module is the one used to create the file revisions of you css
, js
and other files.
After grunt-filerev
is executed (executed as a subtask of grunt-usemin
), it creates a summary (stored in within your grunt task, under grunt.filerev.summary
). The summary contains the following information:
{
“original.js” : “destination.59bcc35a.js”
}
So you could use it later on you string replacement method/module of your choice.
You can find more information about grunt-filerev
here.
Hope it helps.
Grunt module(s) to upload all static assets to S3 / CloudFront, replace paths, and invalidate old assets
Invalidating CDN assets is a Bad Idea ®. In CloudFront, it may take up to 15 minutes to complete - that would be adding 15 minutes to your deploy. Also, some browsers may hold old files because the URL is the same.
Instead, you should probably version you static assets and publish new versions under different version names.
For example:
my-app/1.2.3/main.js
my-app/1.2.4/main.js
So on, and so forth.
This gives you two advantages:
- You can cache forever, confidently. The same URL will always serve the same file.
- You can rollback quickly in case of a disaster deploy. Old files are where they were.
For deploying to S3, there are specific plugins for that.
I, however, prefer to simply use grunt-shell in tandem with the official Amazon AWS CLI
Configuring it would look something like this:
shell: {
cp: {
command: "aws s3 cp --recursive dist/ s3://my-bucket/my-app/"
}
}
You can use grunt to read a version variable from somewhere and automatically put all files inside the dist/{version}/
folder, while replacing any paths in your html to the correct version
path.
Have Grunt generate index.html for different setups
I've come up with my own solution. Not polished yet but I think I'm going to move in that direction.
In essense, I'm using grunt.template.process() to generate my index.html
from a template that analyzes current configuration and produces either a list of my original source files or links to a single file with minified code. The below example is for js files but the same approach can be extended to css and any other possible text files.
grunt.js
:
/*global module:false*/
module.exports = function(grunt) {
var // js files
jsFiles = [
'src/module1.js',
'src/module2.js',
'src/module3.js',
'src/awesome.js'
];
// Import custom tasks (see index task below)
grunt.loadTasks( "build/tasks" );
// Project configuration.
grunt.initConfig({
pkg: '<json:package.json>',
meta: {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */'
},
jsFiles: jsFiles,
// file name for concatenated js
concatJsFile: '<%= pkg.name %>-all.js',
// file name for concatenated & minified js
concatJsMinFile: '<%= pkg.name %>-all.min.js',
concat: {
dist: {
src: ['<banner:meta.banner>'].concat(jsFiles),
dest: 'dist/<%= concatJsFile %>'
}
},
min: {
dist: {
src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
dest: 'dist/<%= concatJsMinFile %>'
}
},
lint: {
files: ['grunt.js'].concat(jsFiles)
},
// options for index.html builder task
index: {
src: 'index.tmpl', // source template file
dest: 'index.html' // destination file (usually index.html)
}
});
// Development setup
grunt.registerTask('dev', 'Development build', function() {
// set some global flags that all tasks can access
grunt.config('isDebug', true);
grunt.config('isConcat', false);
grunt.config('isMin', false);
// run tasks
grunt.task.run('lint index');
});
// Production setup
grunt.registerTask('prod', 'Production build', function() {
// set some global flags that all tasks can access
grunt.config('isDebug', false);
grunt.config('isConcat', true);
grunt.config('isMin', true);
// run tasks
grunt.task.run('lint concat min index');
});
// Default task
grunt.registerTask('default', 'dev');
};
index.js (the index task)
:
module.exports = function( grunt ) {
grunt.registerTask( "index", "Generate index.html depending on configuration", function() {
var conf = grunt.config('index'),
tmpl = grunt.file.read(conf.src);
grunt.file.write(conf.dest, grunt.template.process(tmpl));
grunt.log.writeln('Generated \'' + conf.dest + '\' from \'' + conf.src + '\'');
});
}
Finally, index.tmpl
, with generation logic baked in:
<doctype html>
<head>
<%
var jsFiles = grunt.config('jsFiles'),
isConcat = grunt.config('isConcat');
if(isConcat) {
print('<script type="text/javascript" src="' + grunt.config('concat.dist.dest') + '"></script>\n');
} else {
for(var i = 0, len = jsFiles.length; i < len; i++) {
print('<script type="text/javascript" src="' + jsFiles[i] + '"></script>\n');
}
}
%>
</head>
<html>
</html>
UPD. Found out that Yeoman, which is based on grunt, has a built-in usemin task that integrates with Yeoman's build system. It generates a production version of index.html from information in development version of index.html as well as other environment settings. A bit sophisticated but interesting to look at.
Related Topics
Build JavaScript Object to Use with Jquery .Css() (What About Duplicate Keys)
Jquery/Js:Detect User's Scroll Attempt Without Any Window Overflow to Scroll To
React Animation for Moving an Element from One Parent to Another
Need to Load Image as Modal on Click in Bootstrap CSS
Make Named Anchor Bookmarks Appear Always at Top of the Screen When Clicked
Jquery Example (In Jsfiddle) Working in Firefox But Not in IE8, 7
How to Get Element's Attribute Set in CSS Class
Catch JavaScript Event in iOS Wkwebview with Swift
Rotating Clickable Elements in IE8+
JavaScript .Replace Alternative
Primefaces Dialog with Modal=True Not Working Properly
The Best Way of Checking for -Moz-Border-Radius Support
Vertical-Align Text Within a Textarea
Find Next Cell Contained in Sibling Row with Queryselector
How to Get Jquery or JavaScript to Change CSS Based on the Current Url
Prevent Requestanimationframe from Running All the Time
Workaround for Display Block and CSS Transitions Not Triggering