Grunt - Watch new folders - javascript

I'm trying to get grunt-contrib-watch to watch my images folder, and run grunt-imageoptim on any added/changed jpgs, gifs, or pngs.
My code below runs fine for running imageoptim on new images, as long as I don't make any new folders. Apparently this has been fixed in recent versions but I'm pretty new to Grunt so it might be something basic I'm missing. I've gotten it to see changes / new folders in watch through a less specific wildcard, but then i can't stop imageoptim from running on all images in all the folders.
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
imageoptim: {
options: {
jpegMini: false,
imageAlpha: true,
quitAfter: true
},
},
watch: {
files: ['images/**/*.jpg', 'images/**/*.png', 'images/**/*.gif'],
tasks: ['imageoptim'],
options: {
spawn: false,
},
},
});
// imageoptim
grunt.loadNpmTasks('grunt-imageoptim');
// grunt watch
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['imageoptim']);
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('imageoptim.all.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
};
(the bottom function is to run imageoptim on a watch change, and then prevent it from seeing it's own changes as changes to act on again)

Whoops, answered my own question :P I was previously (before posting the question) setting src in imageoptim instead of changing files in watch. This works:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
imageoptim: {
options: {
jpegMini: false,
imageAlpha: true,
quitAfter: true
},
},
watch: {
files: ['images/**'],
tasks: ['imageoptim'],
options: {
spawn: false,
},
},
});
// imageoptim
grunt.loadNpmTasks('grunt-imageoptim');
// grunt watch
grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s).
grunt.registerTask('default', ['imageoptim']);
var changedFiles = Object.create(null);
var onChange = grunt.util._.debounce(function() {
grunt.config('imageoptim.all.src', Object.keys(changedFiles));
changedFiles = Object.create(null);
}, 200);
grunt.event.on('watch', function(action, filepath) {
changedFiles[filepath] = action;
onChange();
});
};

Related

Terser does not give minified file

I am trying to minify an angularjs application using grunt and terser. I first used uglifiy-es but then read that it has some issues. So I tried terser. But the output does not give me minified files.
The gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
//grunt task configuration will go here
ngAnnotate: {
options: {
singleQuotes: true
},
app: {
files: {
'./public/min-safe/js/_config_min.js': ['./controllers/_config.js'],
'./public/min-safe/js/ctrl_accountingdashboard.js': ['./controllers/ctrl_accountingdashboard.js'],
}
}
},
concat: {
js: { //target
src: ['./public/min/app.js', './public/min-safe/js/*.js'],
dest: './public/min/app.js'
}
},
terser: {
options: {},
files: {
'./public/min/app.js': ['./public/min/app.js'],
},
}
});
//load grunt tasks
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-terser');
grunt.loadNpmTasks('grunt-ng-annotate');
//register grunt default task
grunt.registerTask('default', ['ngAnnotate', 'concat', 'terser']);
}
I had the same problem. According to the documentation, this should work but it didn't for me. Wrapping the "files" setting in a custom target works for me:
terser: {
options: {},
main: {
files: {
'./public/min/app.js': ['./public/min/app.js'],
}
}
}
To add to #Tim's great answer:
Here is an example that allows to run grunt-terser with path / file wildcard patterns (globbing) – which it does not support out of the box.
Please note the helper properties _src and _dest in the terser config which are not read by grunt-terser itself but by the task terser_all. This task expands the globbing pattern(s) in _src and builds the real config in the files property. When done it runs terser with that updated config.
module.exports = function (grunt) {
grunt.initConfig({
terser: {
dist: {
options: {
compress: {
drop_console: true // remove console.log, console.info, ...
}
},
files: {
// FILLED through terser_all task below!
// Examples config:
// "dist/example.js": [ "path/to/files/example.js" ]
// "dist/example_joined.js": [ "path/to/files/*.js" ]
},
// -----
// HELPER PROPERTIES to build the files prop (see above) in the terser_all task below.
_src: [
"path/to/files/*.js"
],
_dest: "dist/"
}
}
});
grunt.registerTask('terser_all', function () {
// work on this target in terser config
var terser_target_name = "dist";
// read the terser config
var terser_config = grunt.config.get('terser') || {};
var terser_target_config = terser_config[terser_target_name] || {};
// get the destination dir
var destDir = terser_target_config._dest;
// loop through all source files and create an entry in the terser config for each of it
var files = grunt.file.expand(terser_target_config._src);
for (const [i, file] of files.entries()) {
grunt.log.writeln(file);
// add this file to the terser config as: dest_file: src_file
terser_target_config.files[destDir + file] = file;
}
// show new config on CLI
grunt.log.writeflags(terser_target_config);
// write back config and run task
grunt.config.set('terser', terser_config);
grunt.task.run('terser');
});
grunt.loadNpmTasks('grunt-terser');
grunt.registerTask('build', ['terser_all']);
grunt.registerTask('default', ['build']);
};
Just a note:
If you try to "disable" some options by renaming this disables the whole process. At least this was my result with grunt-terser. I was left with the original js file.
{
mangleX: {
reserved: [/* ... */]
}
}

Grunt no "qunit" targets found

Configuring grunt to make automated JS tests with jenkins and qunit, I am actually blocking on this issue.
When I run grunt:
Running "qunit_junit" task
XML reports will be written to _build/test-reports
No "qunit" targets found.
Warning: Task "qunit" failed. Use --force to continue.
Aborted due to warnings.
My Gruntfile:
'use strict';
module.exports = function(grunt) {
var gruntConfig = {};
grunt.initConfig({
sync: {
target: {}
}
});
grunt.registerTask('default', ['qunit_junit', 'qunit']);
grunt.loadNpmTasks('grunt-contrib-qunit');
grunt.loadNpmTasks('grunt-qunit-istanbul');
gruntConfig.qunit = {
src: ['static/test/index.html'],
options: {
coverage: {
src: ['static/js/**/*.js'],
instrumentedFiles: 'temp/',
htmlReport: 'report/coverage',
coberturaReport: 'report/',
linesThresholdPct: 20
}
}
};
grunt.loadNpmTasks('grunt-qunit-junit');
gruntConfig.qunit_junit = {
options: {
dest: 'report/'
}
};
};
I checked and console.log() in the node_modules, the grunt-contrib-qunit is installed and the task is in it so grunt finds the module and the task but seems not to load it.
Just at a glance - you are creating your config, but not doing anything with it.
Change this line
grunt.initConfig({
sync: {
target: {}
}
});
to this:
grunt.initConfig(gruntConfig);
You might also want to move that down below all the other stuff you add to gruntConfig.

Grunt changing multiple times

I have a grunt file that watches for changes on app.css. The watch appears to be processing the file multiple times upon change of app.css. Checked the file and the output is correct.
Grunt File
module.exports = function(grunt) {
"use strict";
grunt.initConfig({
//concat: {
// css: {
// src: ['app/css/*.css'],
// dest: 'app/css/app.min.css'
// }
//},
cssmin: {
minify: {
expand: true,
cwd: 'app/css/',
src: ['*.css', '!*.min.css'],
dest: 'app/css/',
ext: '.min.css'
}
},
watch: {
//js: {
// files: ['app/js/**/*.js'],
// tasks: ['concat']
//},
css: {
files: ['app/css/*.css'],
tasks: ['cssmin']
}
}
});
//grunt.loadNpmTasks('grunt-contrib-concat'); // Load concat
grunt.loadNpmTasks('grunt-contrib-watch'); // Load watch
grunt.loadNpmTasks('grunt-contrib-cssmin'); // Load CSS min
grunt.registerTask('default', ['watch']); // Load default task
};
It is because the first pass modifies the app.css file which creates app.min.css -- but your watcher is looking for modifications to ANY CSS files (including the newly-created app.min.css).
You can either ignore *.min.css in your watcher config, or just output the minified CSS to a folder you're not watching.

grunt-closure-tools config issue with multiple targets

I want to work with closure compiler, so I added grunt-closure-tools to my Grunt config, but my config is erroring with:
Verifying property closureCompiler.loader exists in config...ERROR
Here is the reference material for grunt-closure-tools:
https://www.npmjs.com/package/grunt-closure-tools
or
https://github.com/thanpolas/grunt-closure-tools
Here is my GruntFile.js:
module.exports = function(grunt) {
var path = require('path');
require('load-grunt-config')(grunt, {
//pkg: grunt.file.readJSON('package.json'),
configPath: path.join(process.cwd(), 'grunt'), //path to task.js files, defaults to grunt dir
init: true, //auto grunt.initConfig
data: { //data passed into config. Can use with <%= test %>
pkg: require('./package.json')
},
loadGruntTasks: { //can optionally pass options to load-grunt-tasks. If you set to false, it will disable auto loading tasks.
pattern: ['grunt-contrib-*', 'grunt-jslint', 'grunt-newer', 'imagemin-*','grunt-closure-tools'],
scope: 'devDependencies'
},
postProcess: function(config) {} //can post process config object before it gets passed to grunt
});
//require('load-grunt-tasks')(grunt);
grunt.registerTask("default", ["newer:jslint", "newer:concat", "closureCompiler:loader", "newer:sass"]);
};
I am using load-grunt-config to break up my config into multiple parts. Here is my closure.js file, mostly modeled on grunt-closure-tools github page example:
module.exports = {
options: {
compilerFile: '/usr/local/Cellar/closure-compiler/20141023/libexec/build/compiler.jar',
checkModified: true,
compilerOpts: {
create_source_map: null,
compilation_level: 'ADVANCED_OPTIMIZATIONS',
},
d32: true, // will use 'java -client -d32 -jar compiler.jar'
},
util: {
src: 'includes/javascript/util/util.js',
dest: 'includes/javascript/build/util.min.js'
},
loader: {
src : 'includes/javascript/loaders/loader.js',
dest: 'includes/javascript/build/loader.min.js'
}
};
Any help with this error is appreciated.
After some digging and no small amount of thrashing of teeth, I have managed to getting my config working. My Gruntfile.js:
module.exports = function(grunt) {
var path = require('path');
require('load-grunt-config')(grunt, {
//pkg: grunt.file.readJSON('package.json'),
configPath: path.join(process.cwd(), 'grunt'), //path to task.js files, defaults to grunt dir
init: true, //auto grunt.initConfig
data: { //data passed into config. Can use with <%= test %>
pkg: require('./package.json')
},
loadGruntTasks: { //can optionally pass options to load-grunt-tasks. If you set to false, it will disable auto loading tasks.
pattern: ['grunt-contrib-*', 'grunt-jslint', 'grunt-newer', 'imagemin-*','grunt-closure-tools'],
scope: 'devDependencies'
},
postProcess: function(config) {} //can post process config object before it gets passed to grunt
});
//require('load-grunt-tasks')(grunt);
grunt.registerTask("default", ["newer:jslint", "newer:concat", "closureCompiler:loader", "newer:sass"]);
};
and my closureCompiler.js file (shortened for clarity):
module.exports = {
options: {
compilerFile: '/usr/local/Cellar/closure-compiler/20141023/libexec/build/compiler.jar',
checkModified: true,
compilerOpts: {
// create_source_map: null
},
execOpts: {
maxBuffer: 999999 * 1024
},
TieredCompilation: true // will use 'java -server -XX:+TieredCompilation -jar compiler.jar'
},
loader: {
TEMPcompilerOpts: {
create_source_map: 'includes/javascript/build/loader.min.js.map'
},
src : 'includes/javascript/loaders/loader.js',
dest: 'includes/javascript/build/loader.min.js'
}
};
I had quite a few errors in my config:
I had to rename closure.js to closureCompiler.js so load-grunt-config could find the file. Oops, my bad.
The d32: true switch on the Closure Compiler means use 32-bit JVM, which I do not have on my system. I switched to TieredCompilation: true instead.
create_source_map: null in the options did not work for me. I found the reference in the source code of grunt-closure-tools but didn't spend the time to sort out what was wrong. Instead, I added TEMPcompilerOpts to the target config with the map file I wanted Closure to make.
I hope other benefit from my experience with this solution. From this point, I am going to use the ability of Closure Compiler to create source maps to merge my dev and prod build targets into a single target.

Grunt watch not running tasks

I'm trying to run a grunt server with livereload and less.
on grunt less it does compile my less file but when changing a less file all i get is
>> File "app\style\componenets\components.less" changed.
I also tried less:development but still no luck.
Btw I get livereload on EVERY file I change, though in the watch task I've only configured less locations..
Thanks in advance!
'use strict';
// Gruntfile with the configuration of grunt-express and grunt-open. No livereload yet!
module.exports = function(grunt) {
// Load Grunt tasks declared in the package.json file
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
console.log(__dirname + '\\app\\');
// Configure Grunt
grunt.initConfig({
// grunt-express will serve the files from the folders listed in `bases`
// on specified `port` and `hostname`
express: {
all: {
options: {
bases: ['app'],
port: 8080,
hostname: "0.0.0.0",
livereload: true
}
}
},
less: {
development: {
options: {
compress: true,
yuicompress: true
},
files: {
// target.css file: source.less file
"app/main.css": "app/style/main.less"
}
}
},
// grunt-watch will monitor the projects files
watch: {
less: {
files: ['<%= express.all.options.base%>/style/*.less', '<%= express.all.options.base%>/style/componenets/*.less'],
tasks: ['less']
}
},
// grunt-open will open your browser at the project's URL
open: {
all: {
// Gets the port from the connect configuration
path: 'http://localhost:<%= express.all.options.port%>/#/'
}
}
});
// Creates the `server` task
grunt.registerTask('server', [
'express',
'open',
'watch'
])
// Creates the `less` task
grunt.registerTask('less', ['less']);
};
why the alias task at the end of your gruntfile?
// Creates the `less` task
grunt.registerTask('less', ['less']);
your less task is already defined through your config! remove that line, and you're probably good...
edit: there is at least 1 typo in your less config:
wrong:
<%= express.all.options.base %>/style/*.less'
correct:
<%= express.all.options.bases %>/style/*.less'

Categories