Watch multiple files with Grunt Bake without compiling all at once - javascript

I want to use Grunt Bake for my grunt workflow. This is my grunt.js setup:
grunt.initConfig({
bake: {
build: {
files: {
'dev/foo.html': 'public/foo.html',
'dev/bar.html': 'public/bar.html',
'dev/foo2.html': 'public/foo2.html'
// ...
}
}
},
watch: {
bake: {
files: ['dev/*.html'],
tasks: ['bake:build']
}
}
});
My problem: If I change one file all files will be compiled. I could solve this with creating a watch listener for each file but this seems not to be a clever solution:
grunt.initConfig({
bake: {
foo: {
files: {
'dev/foo.html': 'public/foo.html'
}
},
bar: {
files: {
'dev/bar.html': 'public/bar.html'
}
},
foo2: {
files: {
'dev/foo2.html': 'public/foo2.html'
}
}
// ...
},
watch: {
foo1: {
files: ['dev/foo.html'],
tasks: ['bake:foo']
},
bar: {
files: ['dev/bar.html'],
tasks: ['bake:bar']
},
foo2: {
files: ['dev/foo2.html'],
tasks: ['bake:foo2']
}
}
});
Imagine there are 20+ different html files... So this is not an option for me. Any other solutions for doing that?

Ok, got it!
There is a newer task exactly for doing this:
grunt.initConfig({
bake: {
build: {
files: {
'dev/foo.html': 'public/foo.html',
'dev/bar.html': 'public/bar.html',
'dev/foo2.html': 'public/foo2.html'
// ...
}
}
},
watch: {
bake: {
files: ['dev/*.html'],
tasks: ['newer:bake:build']
}
}
});

Related

Uglify not working with Grunt Watch

I have a pretty basic setup with sass, watch and uglify but for some reason I can't get watch to detect when a js file is saved. It works fine for SCSS/CSS (compiles and reloads.) If I run 'grunt uglify' it bundles my JS files, and if watch is running (in another console instance) it will detect it and trigger the reload.
I've tried lots of combinations and I have a feeling it's something really dumb I'm doing/not doing but I'm just not seeing it.
my gruntfile.js:
module.exports = function(grunt) {
grunt.registerTask('default', ['sass', 'uglify']);
grunt.initConfig({
sass: {
dist: {
options: {
style: 'expanded'
},
files: { 'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.css': 'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.scss' }
}
},
uglify: {
my_target: {
files: {
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js': [
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/jquery/dist/jquery.js',
'fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/*.js'
]
}
}
},
watch: {
options: {
livereload: 35729,
},
html: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/Views/*.cshtml'],
},
sass: {
options: {
livereload: false
},
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/*.scss'],
tasks: ['sass']
},
css: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/css/main.css'],
tasks: []
},
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js'],
tasks: ['uglify']
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
};
Look at your watch config:
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/js/site.js'],
tasks: ['uglify']
}
You are only watching for a single js files changes called site.js. To watch all your sources use this config:
scripts: {
files: ['fivesixtwo.com/src/FiveSixTwo.com/wwwroot/lib/*.js'],
tasks: ['uglify']
}
Use the same pattern as in the uglify config. I assumed you are not going to modify jquery itself.

grunt-include-source multiple configurations

my problem is as following; I'm using grunt-include-source (https://www.npmjs.com/package/grunt-include-source) to include my scripts and css to my index.html, this is working fine but I can only specify one basepath, and i would like to setup this plugin for both dev and production. (im using the same folder structure so nothing will change in my index.html, the only difference is that in concatenate in my production)
includeSource: {
options: {
basePath: 'dev'
},
myTarget: {
files: {
'dev/index.html': 'app/index.html'
}
}
},
Code above is working fine, now i want to have 2 different configuration, but something like this doesn't work when running the task includeSource:dev:
includeSource: {
dev: {
options: {
basePath: 'dev'
},
myTarget: {
files: {
'dev/index.html': 'app/index.html'
}
}
},
prod: {
options: {
basePath: 'prod'
},
myTarget: {
files: {
'prod/index.html': 'app/index.html'
}
}
}
},
index.html:
<!-- include: "type": "js", "files": "scripts/*.js" -->
Anyone could help me out how I would able to achieve this?
edit: Just to be a bit more clear, im running this script after my builds for either production or development is done, for both my prod/dev all scripts are stored in scripts/
Kind regards,
G
Just configure your task like this instead:
includeSource: {
options: {
basePath: 'dev/'
},
dev: {
files: {
'dev/index.html': 'app/index.html'
}
},
prod: {
options: {
basePath: 'dist/'
},
files: {
'dist/index.html': 'app/index.html'
}
}
},

Grunt-Browserify Ignore Option

I have a React app that I am transforming, uglifying and browserfying via Grunt. My grunt file looks like this...
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
dist: {
files: {
'./Scripts/build/App.js': ['./Scripts/src/**/*.js']
},
options: {
browserifyOptions: {
debug: true
},
transform: [ require('grunt-react').browserify ],
ignore: './Scripts/src/**/*-test.js'
}
}
},
uglify: {
my_target: {
files: {
'./Scripts/build/App-min.js': ['./Scripts/build/App.js']
}
}
},
watch: {
scripts: {
files: ['./Scripts/src/**/*.js'],
tasks: ['browserify', 'uglify'],
options: {
spawn: false
},
},
},
})
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
}
You will notice the ignore property of the browserify task is telling it to ignore any file with -test.js in the filename, the reason being that my tests are stored in folders directly next to the file I am testing (as seems to be the convention when looking at the React Flux examples) and I don't want the test files being bundled in to my app.js file. Can anyone tell me if I am doing this wrong because so far it doesnt seem to be working at all? The test files get bundled into app.js and then I get console errors about jest not being defined.
Did a bit of lateral Googling and found a post on stack Here
It seems that you can add files to the src array and if you prefix them with a '!' it marks them as ignored files.
My now working grunt file....
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
browserify: {
dist: {
files: {
'./Scripts/build/App.js': ['./Scripts/src/**/*.js', '!./Scripts/src/**/*-test.js']
},
options: {
browserifyOptions: {
debug: true
},
transform: [ require('grunt-react').browserify ]
}
}
},
uglify: {
my_target: {
files: {
'./Scripts/build/App-min.js': ['./Scripts/build/App.js']
}
}
},
jest: {
options: {
coverage: true,
testPathPattern: /.*-test.js/
}
},
watch: {
scripts: {
files: ['./Scripts/src/**/*.js'],
tasks: ['browserify', 'uglify'],
options: {
spawn: false
},
},
},
})
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-jest');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
}

getting grunt-istanbul error: No coverage information was collected

I've built a grunt setup for testing using qunit and generating coverage reports with istanbul but I can't get the storeCoverage task to complete without the error: No coverage information was collected.
Gruntfile.js
module.exports = function (grunt)
{
"use strict";
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
connect: {
root_server: {
options: {
port: 2424,
base: 'qunit'
},
}
},
qunit: {
all: ['qunit/test1.html']
},
instrument: {
files: "testable.js",
options: {
lazy: true,
basePath: "qunit/"
}
},
storeCoverage: {
options: {
dir: "report/"
}
},
makeReport: {
src: "report/*.json",
options: {
type: "lcov",
dir: "test",
print: "detail"
}
}
});
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks("grunt-contrib-qunit");
grunt.loadNpmTasks("grunt-istanbul");
grunt.registerTask("default", ["instrument", "connect", "qunit", "storeCoverage"/*, "makeReport"*/]);
};
testable.js
function runable ()
{
return true;
};
test1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>QUnit Example</title>
<link rel="stylesheet" href="qunit.css">
</head>
<body>
<script src="qunit.js"></script>
<script src="testable.js"></script>
<script>
QUnit.test("hello test", function (assert)
{
assert.ok(runable());
});
</script>
</body>
</html>
Everything works, qunit runs and the one assert does run on the instrumented file and succeeds. But when it hits the storeCoverage task it fails. Am I doing something wrong? Any help is appreciated of course.
I was able to get this working using the Gruntfile.js from the grunt-istanbul project.
Their documentation indicates that the reloadTasks is not required, but for me it actually was. The clean task they do also assists to tidy up. Also noted in their docs, you can set an ENV variable, rather than using the env task.
Try adding these to your Gruntfile.js:
env: {
coverage: {
APP_DIR_FOR_CODE_COVERAGE: rootPath + 'path/to/instrument'
}
},
clean: ['path/to/coverage'],
reloadTasks: {
rootPath: 'path/to/instrument'
},
My task looks like this:
grunt.registerTask('cover',[
'env:coverage',
'clean',
'instrument',
'reloadTasks',
'connect',
'qunit',
'storeCoverage',
'makeReport'
]);
The question is a little old, but it might help someone else.
To solve this issue, I needed to point my test code to the instrumented code otherwise the original one.
See the example:
Gruntfile.js:
module.exports = function (grunt) {
grunt.initConfig({
env: {
coverage: {
APP_DIR_FOR_CODE_COVERAGE: '../test/coverage/instrument/lib/'
}
},
clean: {
coverage: {
src: ['test/coverage/']
}
},
instrument: {
files: 'lib/*.js',
options: {
lazy: true,
basePath: 'test/coverage/instrument/'
}
},
mochaTest: {
test: {
options: {
reporter: 'spec'
},
src: ['test/**/*test.js']
}
},
storeCoverage: {
options: {
dir: 'test/coverage/reports'
}
},
makeReport: {
src: 'test/coverage/reports/**/*.json',
options: {
type: 'lcov',
dir: 'test/coverage/reports',
print: 'detail'
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-istanbul');
grunt.loadNpmTasks('grunt-env');
grunt.registerTask('test', 'mochaTest');
grunt.registerTask('coverage', ['env:coverage', 'clean', 'instrument', 'mochaTest', 'storeCoverage', 'makeReport']);};
In you test code, point to the instrumented ones.
As described in the grunt-istanbul site, you can create a requireHelper file.
module.exports = function (path) {
return require((process.env.APP_DIR_FOR_CODE_COVERAGE || '../lib/') + path);
};
And use it in your test file.
var requireHelper = require('./require_helper');
var fileToBeTested = requireHelper('file-to-be-tested');
describe('Test', function () {
it('should do some test', function () {
expect(1).to.equal(1);
});
});

How to output two files using grunt durandal

I am having a go at grunt for optimizing my Durandal SPA. It seems to work great but now I would like to output a second file called libs.js which is the merged uglified version of all my required libraries but my first dist is getting ignored and still the only file I get is main-built.js
I only get one file so app/libs.js never gets created. I also have no grunt errors.
Here is my Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
durandal: {
libs: {
src: [
"../scripts/jquery-1.9.1.js",
"../scripts/typeahead.js",
"../scripts/jquery-ui-1.10.3.js",
"../scripts/knockout-3.0.0rc.js",
"../scripts/toastr.js",
"../scripts/q.js",
"../scripts/breeze.min.js",
"../scripts/bootstrap.js",
"../scripts/moment.js",
"../scripts/lodash.js",
"../scripts/respond.js",
"../scripts/knockout-sortable.js",
"../scripts/knockout-bootstrap.js",
"../scripts/knockout.validation.js",
],
dest: 'scripts/libs.js',
options: {
uglify2: {
compress: {
global_defs: {
DEBUG: false
}
}
}
}
},
dist: {
src: [
"app/**/*.*",
"scripts/durandal/**/*.*"
],
options: {
baseUrl: "app/",
mainPath: "app/main.js",
out: "app/main-built.js",
uglify2: {
compress: {
global_defs: {
DEBUG: false
}
}
}
}
}
}
});
grunt.loadTasks('tasks');
grunt.registerTask('default', ['durandal']);
};
This is JavaScript. If you create an object like { a: 'a', a: 'b' }, the first key will be overwritten by the second by the VM.
Instead of configuring it like this:
dist: {
// config goes here
},
dist: {
// config goes here
}
Try
libs: {
// config goes here
},
main: {
// config goes here
}

Categories