Uglify with SourceMaps while using grunt usemin and rev - javascript

I want to log javascript errors to server but the stacktrace is not useful with minified JS code. So I was thinking of using either Getsentry or Rollbar which shows proper stack trace with the help of sourcemaps. But I'm struggling to create sourcemap in first place.
I'm getting this error
"Destination (_build/js/app.js) not written because src files were empty."
Once it creates source map properly, there will be another problem i.e. rev will rename the file. I also need to leave the unminified concatenated file.
Below is my gruntfile.js (I've removed few bits out of it.)
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
clean: {
jsFolders: {
src: [
'_build/js/ui',
'_build/js/vendor',
'_build/js/app',
'_build/js/*templates.js'
]
},
build: {
src: ['_build/**/*']
}
},
copy: {
build: {
files: [{
expand: true,
src: [
'index.html',
'img/**/*', //includes web.cofig also.
'img/**/*.svg',
'!img/**/*.psd',
'js/**/*', //includes web.cofig also.
'css/**/*', //includes web.cofig also.
'*.png',
'favicon.ico'
],
dest: '_build/'
}]
},
},
rev: {
option: {
algorithm: 'sha1',
length: 4
},
all: {
files: {
src: [
'_build/**/*.{js,css,eot,ttf,woff}'
]
}
}
},
useminPrepare: {
html: ['_build/index.html']
},
usemin: {
html: [
'_build/index.html'
],
css: [
'_build/css/**/*.css'
]
},
uglify: {
options: {
sourceMap: '_build/js/app.js.map',
},
js: {
files: {
'_build/js/app.js': ['_build/js/app.js']
}
}
},
cssmin: {
minify: {
expand: true,
cwd: '_build/css/',
src: '*.css',
dest: '_build/css/'
}
},
});
grunt.registerTask('build', [
'clean:build',
'handlebars',
'compass',
'autoprefixer',
'copy:build',
'useminPrepare',
'concat',
'uglify',
'cssmin',
'clean:jsFolders',
'rev',
'usemin',
]);
};
UPDATE
Tried #Andy's solution, it still shows the same error "Destination (_build/js/app.js) not written because src files were empty." and it also says below while building
uglify:
{ options:
{ sourceMap: true,
sourceMapName: '_build/js/app.js.map' },
js: { files: { '_build/js/app.js': [ '_build/js/app.js' ] } },
generated:
{ files:
[ { dest: 'dist\\js\\app.js',
src: [ '.tmp\\concat\\js\\app.js' ] } ] } }
Don't know where it got dest name from. My output folder is _build.
UPDATE2:
Refer to below links for better solution
https://stackoverflow.com/a/20574196/148271
https://github.com/gruntjs/grunt-contrib-uglify/issues/39#issuecomment-14856100

useminPrepare is merging the existing uglify config with its own, but nested under generated. Therefore this configuration for uglify works for me
grunt.initConfig({
uglify: {
generated: {
options: {
sourceMap: true
}
}
}
});

There is no simple solution to getting sourcemaps to work with the usemin flow.
Its a known problem that hasnt been addressed in a year it seems:
https://github.com/yeoman/grunt-usemin/issues/30
https://github.com/yeoman/grunt-usemin/issues/220

The options for uglify are:
sourceMap: true,
sourceMapName: 'path/to/name.map'
For example, in my GruntFile.js I use the name found in package.json:
sourceMap: true,
sourceMapName: 'dist/<%= pkg.name %>-<%= pkg.version %>.map'

Related

Grunt, how to minify different folders (to include node_modules folder)

I am using NPM in a WP project.
I already have a grunt task that compiles my separate SCSS files into CSS files and then minifies them into one default.min.css file when running grunt (that's good.)
My main issue is that I would like to include different npm packages such as fontawesome, bootstrap etc. where they also would be minified into that one minified min.css file, together with my own files.
I would also like to know how to do this for my own *.js files uglify'd with different packages i'm using (jquery-ui, owl-carousel, etc.)
Please find below my Gruntfile.js, this is my first Gruntfile.js so feel free to include any constructive remarks.
Thanks,
Bud
Gruntfile.js
module.exports = function (grunt) {
grunt.initConfig({
sass: {
dist: {
files: [{
expand: true,
cwd: 'resource/scss/',
src: ['*.scss'],
dest: 'resource/builds/css/',
ext: '.css'
}]
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['sass', 'cssmin']
},
scripts: {
files: 'resource/js/*.js',
tasks: ['uglify']
}
},
cssmin: {
target: {
files: [{
expand: true,
cwd: 'resource/builds/css/',
src: ['*.css', '!*.min.css'],
dest: 'public/css',
ext: '.min.css'
}]
}
},
concat: {
js: {
options: {
separator: ';'
},
src: 'resource/**/*.js',
dest: '<%= paths.dest.js %>'
}
},
uglify: {
build: {
files: [{
expand: true,
cwd: 'resource/js/',
src: '**/*.js',
dest: 'public/js',
ext: '.min.js'
}]
}
}
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-concat');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default',['cssmin', 'uglify', 'watch']);
};

No 'Sass' Targets Found - Error whilst using Grunt

I've started trying to get to grips with the very basics of Grunt but when I try to run 'Grunt Sass' I get a "No 'sass' targets found" error. I can't see where I'm going wrong, anyone able to give me nudge in the right direction?
module.exports = function(grunt) {
//configuration
grunt.initConfig({
// pass in options to plugins, references to files
concat: {
js: {
src: ['js/*.js'],
dest: 'build/script.js'
},
css: {
src: ['css/*.css'],
dest: 'build/styles.css'
},
sass: {
dist: {
files: [{
src: 'css/sass/styles.scss',
dest: 'css/styles.css'
}]
}
},
}
});
//Load Plugins
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-sass');
// register tasks
grunt.registerTask('concat-js', ['concat:js']);
grunt.registerTask('concat-css', ['concat:css']);
};
Your sass task is nested in concat which is why it can’t identify the sass task and is returning a No "sass" targets found. error.
Un-nest your sass task like such:
grunt.initConfig({
concat: {
...
},
sass: {
dist: {
files: [{
src: 'css/sass/styles.scss',
dest: 'css/styles.css'
}]
}
},
});
Sidenote: Looks like your css task is misplaced as well, but that shouldn’t affect grunt sass or grunt sass:dist from running; however, it will not find grunt sass:css. If you want both grunt sass:css and grunt sass:dist to be available, remove the css task from js and here’s how you should struct your sass task:
grunt.initConfig({
concat: {
js: {
src: ['js/*.js'],
dest: 'build/script.js'
},
},
sass: {
css: {
src: ['css/*.css'],
dest: 'build/styles.css'
},
dist: {
files: [{
src: 'css/sass/styles.scss',
dest: 'css/styles.css'
}]
}
},
});

Grunt don't concatenate css and jquery files

Grunt should concatenate both my css and jQuery so I used this code:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
jquery: {
files: ['jquerytest/**/*.js'],
tasks: ['concat:js']
},
css: {
files: ['css/*.css'],
tasks: ['concat:css3']
},
scss:{
files: ['csstest/*.scss'],
tasks: ['compass:dist']
}
},
concat: {
js : {
options: {
separator: ',\n',
banner: 'jQuery.fn.extend({',
footer: '});'
},
files: {
src: ['jquerytest/general/MyFunJqueryLibrary.js', 'jquerytest/general/MySetJqueryLibrary.js'],
dest: 'jquery/MyJqueryLibrary.js'
},
},
css3 : {
options: {
separator: '\n'
},
files: {
src: ['css/MyLibraryCss.css', 'css/MyLibraryScss.css'],
dest: 'css/css.css'
},
},
},
compass: {
dist: {
options: {
sassDir: 'csstest',
cssDir: 'css'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('concatjs', ['concat:dist1', 'concat:dist2']);
grunt.registerTask('default', ['watch']);
};
When running the watch task I get this message:
File "css\MyLibraryCss.css" changed.
Running "concat:css3" (concat) task
but nothing happens. However, when using the jQuery concat task it works, the problem happens only when I use two tasks inside concat.
You have problem with registering task. The task 'concat:dist1' and 'concat:dist2' does not exists. Instead you have to write 'concat:js' and 'concat:css3'.

Build whole angular project using grunt

I'm using grunt for the first time in order to annotate/minify/uglify my whole angular project. Here is what i have for the moment :
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
ngAnnotate: {
options: {
singleQuotes: true
},
all: { //"app" target
files: [
{
expand: true,
src: ['./app/**/*.js'],
dest: './build',
},
],
}
},
concat: {
js: { //target
files: [
{
expand: true,
src: ['./build/**/*.js'],
dest: '.',
},
],
}
},
uglify: {
js: { //target
files: [
{
expand: true,
src: ['./build/**/*.js'],
dest: '.',
},
],
}
}
//grunt task configuration will go here
});
//load grunt task
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-ng-annotate');
//register grunt default task
grunt.registerTask('default', ['ngAnnotate', 'concat', 'uglify']);
}
This works great, i get all my .js files in a "build" folder, with the correct folder architecture. The problem is : i only have the javascript files.
What am i supposed to add in the gruntfile to have my whole project architecture in the "build" folder ? ( HTML,CSS and media files in the right places, not only the annotated/minified/uglified javascript ?
You'll want to look at the copy task. It lets you copy files from one directory to another (like your html, css, fonts, images, etc):
copy: {
html: {
files: [
{expand: true, cwd: '.app/', src: ['some-dir/index.html'], dest: '.build/'}
]
},
css: {
files: [
{expand: true, cwd: '.app/', src: ['some-dir/styles/**/*.css'], dest: '.build/'}
]
},
// ... more targets for `copy`
}
Let's assume we want the following post-build file structure:
.
├── build
│ ├── css
│ ├── img
│ └── js
└── index.html
grunt-contrib-concat
You can just add a parameter for your CSS to be concatenated in a single file, just like you did with JS files.
concat: {
js: {
src: [
'scripts/config.js',
'app.js',
'controllers/*.js'
],
dest: 'build/js/main.js'
},
css: {
src: [
'css/*.css'
],
dest: 'build/css/main.css'
}
}
grunt-contrib-cssmin
This will minify your CSS (the single file the concat task created.)
cssmin: {
target: {
files: [{
expand: true,
cwd: 'build/css',
src: ['*.css', '!*.min.css'],
dest: 'build/css',
ext: '.min.css'
}]
}
}
grunt-contrib-imagemin
Minifies your images and puts them in build/img.
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images/',
src: ['**/*.{png,jpg,jpeg}'],
dest: 'build/img/'
}]
}
}
And finally:
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.registerTask('default', ['concat', 'uglify', 'cssmin', 'imagemin']);

how to config grunt.js to minify files separately

there are some js files in static/js/
1. a.js
2. b.js
3. c.js
how to config grunt.js to get below files:
1. a.min.js
2. b.min.js
3. c.min.js
as far, I have to type specific file name:
min: {
dist: {
src: 'js/**/*.js',
dest: 'js/min/xxx.min.js'
}
}
Had the same problem and found a solution that would automatically minify all my scripts separately:
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'app/scripts'
}]
}
}
In grunt 0.4 you can specify multiple dest/src pairs like this:
uglify: {
dist: {
files: {
'dist/main.js': 'src/main.js',
'dist/widget.js': 'src/widget.js'
}
}
}
Or you can use expandMapping, like this:
min: {
files: grunt.file.expandMapping(['path/*.js', 'path2/*.js'], 'destination/', {
rename: function(destBase, destPath) {
return destBase+destPath.replace('.js', '.min.js');
}
})
}
And the output:
path/test.js => destination/path/test.min.js
path2/foo.js => destination/path2/foo.min.js
This below gruntjs works for me for creating minified files for all the js files under a dir
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'public_html/app',
ext: '.min.js'
}]
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Default task(s).
grunt.registerTask('default', ['uglify']);
};
From the grunt docs for min:
This task is a multi task, meaning that grunt will automatically
iterate over all min targets if a target is not specified.
So you can do this:
min: {
min_a: {
src: 'a.js',
dest: 'a.min.js'
},
min_b: {
src: 'b.js',
dest: 'b.min.js'
},
min_c: {
src: 'c.js',
dest: 'c.min.js'
}
There's nothing special about the name 'dist' for these tasks.
Use the ext option to name the files .min.js instead of .js
uglify: {
build: {
files: [{
expand: true,
src: '**/*.js',
dest: 'build/scripts',
cwd: 'app/scripts',
ext: '.min.js'
}]
}
}
For explicitly export some files into separate output files (in this case all.min.js and all.jquery.js) use:
uglify: {
js: {
files : {
'js/all.min.js' : [
'js/modernizr.js',
'js/vendor/modernizr-2.6.2-respond-1.1.0.min.js',
'js/bootstrap.min.js',
'js/main.js',
'js/ZeroClipboard.min.js',
'js/bootstrap-datepicker/bootstrap-datepicker.js'
],
'js/all.jquery.js' : [
'js/vendor/jquery-1.9.1.js',
'js/vendor/jquery-migrate-1.2.1.js',
'js/vendor/jquery-ui.js'
]
}
},
options: {
banner: '\n/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n',
preserveComments: 'some',
report: 'min'
}
},
I like to keep the original files and also create uglified ones:
uglify: {
dist: {
files: [{
expand: true,
src: '**/*.js',
dest: 'destdir',
cwd: 'srcdir',
rename: function(dest, src) { return dest + '/' + src.replace('.js', '.min.js'); }
}]
}
},
You also can use copy and grunt-mindirect.
copy: {
dist: {
src: 'a.js',
dest: 'a.min.js'
}
},
minidirect: {
all: 'js/min/*.min.js'
}
This should work.
I guess it only matters for watch tasks.
In grunt 0.4 you can do this
var filesA = 'a.js', filesB = 'b.js', filesC = 'c.js';
...
min: {
min_a: {
src: filesA,
dest: 'a.min.js'
},
min_b: {
src: filesB,
dest: 'b.min.js'
},
min_c: {
src: filesC,
dest: 'c.min.js'
}
watch: {
min_a: {
files: filesA,
tasks: ['min:min_a']
},
min_b: {
files: filesB,
tasks: ['min:min_b']
},
min_c: {
files: filesC,
tasks: ['min:min_c']
}
}
After that just start grunt watch and all will be fine automagically.
In an intention to help others who come to this page in future -
I came across a video which explains on how to minify JS files using Grunt JS here: https://www.youtube.com/watch?v=Gkv7pA0PMJQ
The source code is made available here: http://www.techcbt.com/Post/359/Grunt-JS/how-to-minify-uglify-javascript-files-using-grunt-js
Just in case, if the above links are not working:
You can minify all javascript files and combine/concat into one file using the following script:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
files:{
'dest/all.min.js': ['src/app.js', 'src/one.js', 'src/t/two.js']
}
}
}
});
};
If you would like to have source maps also generated, you can enable "sourceMap" option as follows:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
options : {
sourceMap : true,
},
files:{
'dest/all.min.js': ['src/app.js', 'src/one.js', 'src/t/two.js']
}
}
}
});
};
In order to retain entire folder structure while minifying JS files, you can use the following script:
module.exports = function(grunt){
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify:{
t1:{
files: [{
cwd: 'src/',
src: '**/*.js',
dest: 'dest/',
expand: true,
flatten: false,
ext: '.min.js'
}]
}
}
});
};

Categories

Resources