Using Grunt to set environment based variables - gruntjs

I'm looking at grunt-string-replace to accomplish changing variables in my files to an environment specific variable. However, when I try to run the grunt script below I get this warning: "Task min:dev not found". But in this code I have that defined:
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
min: {
dev: {
"string-replace": {
dist: {
files: {
"/newrelic.js": "/newrelic.js"
},
options: {
replacements: [
{
pattern: /$APPNAME/ig,
replacement: "services"
},
{
pattern: /$ENV/ig,
replacement: "nonprod"
}
]
}
}
}
},
prod: {
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-string-replace');
// Default task(s).
grunt.registerTask('default', ['min:dev']);
grunt.registerTask('prod', ['min:prod']);
};
Am I missing something?

Have you read the manual? The getting started guide states that the tasks expect their configuration to be specified in a property of the same name. You have no 'min' task defined, thus it's erroring.
The top-level keys of the config object need to match the task names, and then you define 'targets' (eg, 'dev' or 'prod') within the task config.
So, here's your Gruntfile re-worked. I have not tested this so I can't promise it will work, but it will certainly lead you in the right direction:
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
"string-replace": {
dev: {
files: {
"/newrelic.js": "/newrelic.js"
},
options: {
replacements: [{
pattern: /$APPNAME/ig,
replacement: "services"
}, {
pattern: /$ENV/ig,
replacement: "nonprod"
}]
}
}
},
uglify: {
prod: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
}
}
}
});
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-string-replace');
// Default task(s).
grunt.registerTask('default', ['string-replace:dev']);
grunt.registerTask('prod', ['uglify:prod']);
};

think your trying to do this, this fragment will put the environment variable SOME_ENV, into the grunt config, the replace is simply giving you a easy way to do ${SOME_ENV} placeholders in files for replacement
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg : grunt.file.readJSON('package.json'),
SOME_ENV: process.env.SOME_ENV,
copy: {
files: [
{expand: true, cwd: "src/", src: ["*.*", "**/*.*"], dest: "./build",}
],
options: {
// Replace ${MEH} in files with grunt.config.get("MEH"),
// eg ${SOME_ENV}
// == grunt.config.get("SOME_ENV")
// == process.env.SOME_ENV == systems SOME_ENV environment var
process: function (content, srcpath) {
return content.replace(
/\$\{([a-zA-Z.]+)\}/g,
function replacer(match, p1, offset, string){
var value = grunt.config.get(p1);
grunt.log.write(" in file '" + srcpath + "'\n replacing '" + match + "'\n with '" + value + "'\n");
return value;
});
}
},
}
});
// Production Build Tools
grunt.loadNpmTasks('grunt-contrib-copy');
// Default Production Build task(s).
grunt.registerTask('default', ['copy']);
};

Related

How to use array variable properly in gruntfile.js

Trying to use a predefined array inside of a grunt file, thought using this.js_paths would work, but doesn't seem to work as I'm getting the error, "Cannot read property IndexOf of undefined" when it comes to trying to uglify the scripts. How can I link the js_paths variable to the files src property properly instead of copying the array into the files. Would like to define it separately at the top. Is this possible?
module.exports = function(grunt) {
// loadNpmTasks from package.json file for all devDependencies that start with grunt-
require("matchdep").filterDev("grunt-*", './package.json').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
js_paths: [
'inc/header1/js/*.js',
'!inc/header1/js/*.min.js',
'inc/header2/js/*.js',
'inc/header2/js/*.js',
'!inc/header2/js/*.min.js',
'js/*.js',
'!js/*.min.js'
],
uglify: {
options: {
mangle: true
},
build: {
files: [{
expand: true,
src: this.js_paths,
rename: function(dst, src) {
return src.replace('.js', '.min.js');
}
}]
}
},
watch: {
scripts: {
files: ['inc/header1/js/*.js', 'inc/header2/js/*.js', 'js/*.js'],
tasks: ['uglify'],
options: {
spawn: false,
}
}
}
});
grunt.registerTask('default', ['uglify', 'watch']);
};
Preferrably would like to use the same array js_paths in the watch files (since it's required there), if that makes sense? Still kinda new to using gruntfile.js
Utilize the Templates syntax. It's described in the docs as following:
Templates
Templates specified using <% %> delimiters will be automatically expanded when tasks read them from the config. Templates are expanded recursively until no more remain.
Essentially, change this.js_paths to '<%= js_paths %>' in your uglify task.
For instance:
// ...
uglify: {
options: {
mangle: true
},
build: {
files: [{
expand: true,
src: '<%= js_paths %>', // <-----
rename: function(dst, src) {
return src.replace('.js', '.min.js');
}
}]
}
},
// ...
Likewise for your watch task too.
For instance:
watch: {
scripts: {
files: '<%= js_paths %>', // <-----
tasks: ['uglify'],
options: {
spawn: false,
}
}
}

Grunt: How do I run seperate processes for CSS and JS

As you can see I have tasks for CSS ['sass:main'] and for JS ['jshint:main', 'concat:main', 'uglify:main'], but I want to do separate tasks for separate files (JS and CSS) and listen for changes (watch). Can someone point me in the correct direction, I'm not really sure what I should be searching for. Is this something that watch can handle, or is there another plugin? I'm a little new to grunt so still trying to figure out how to use it. Thanks
GruntFile.js:
module.exports = function(grunt) {
var config = {
pkg: grunt.file.readJSON('package.json'),
jshint: {
options: {
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
},
main: {
src: [
'assets/templates/main/js/crm/*.js',
]
}
},
concat: {
options: {
separator: '\n\n'
},
main: {
src: [
'assets/templates/main/js/crm/*.js',
],
dest: 'assets/templates/main/js/crm.min.js'
}
},
sass: {
options: {
style: 'compressed'
},
main: {
files: {
'assets/templates/main/css/main.min.css': 'assets/templates/main/sass/main.scss',
}
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
main: {
src: 'assets/templates/main/js/crm.min.js',
dest: 'assets/templates/main/js/crm.min.js'
}
},
watch: {
mainjs: {
files: ['assets/templates/main/js/crm/*.js'],
tasks: ['jshint:main', 'concat:main', 'uglify:main'],
},
mainsass: {
files: ['assets/templates/main/sass/*.scss''],
tasks: ['sass:main'],
}
},
concurrent: {
maincss: ['sass:main'],
mainjs: ['jshint:main', 'concat:main', 'uglify:main']
}
};
grunt.initConfig(config);
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-concurrent');
grunt.registerTask('main', ['jshint:main', 'concat:main', 'uglify:main', 'sass:main']);
grunt.registerTask('main-watch', ['jshint:main', 'concat:main', 'uglify:main', 'sass:main', 'concurrent:mainsass']);
};
When I try run tasks:
$ grunt main-watch
Loading "Gruntfile.js" tasks...ERROR
SyntaxError: Invalid or unexpected token
Warning: Task "main-watch" not found. Use --force to continue.
Aborted due to warnings.
It sounds like you want to perform two concurrent watch tasks. You can do that using a configuration like this:
...
concurrent: {
options: { logConcurrentOutput: true },
watch: ['watch:mainjs', 'watch:mainsass']
}
};
...
grunt.registerTask('main-watch', ['concurrent:watch']);
Note that logConcurrentOutput defaults to false, so if you want to see output logged to the console, you need to set it to true.

Grunt: cssmin not working

I am trying to minify CSS using Grunt cssmin plugin. Below is my code:
// Minify CSS
cssmin: {
build: {
options: {
banner: '/* Minified CSS */'
},
files: {
'htt/css/style.min.css' : ['wp/css/**/*.css']
}
}
},
when i run "grunt cssmin" it gives error of "Unexpected identifier".
You where missing a comma after the js object in the watch task, for future you can edit your answer to provide more information instead of posting it as an answer :)
// Watch Tasks
watch: {
js: {
files: ['wp/js/*.js'],
tasks: ['uglify:dev']
}, <------- Missing comma
css: {
files: ['wp/css/*.css'],
tasks: ['']
}
}
});
#mike
`module.exports = function (grunt) {
// Configure Tasks
grunt.initConfig ({
pkg: grunt.file.readJSON ('package.json'),
// Uglify JS
uglify: {
build: {
src: 'wp/js/*.js',
dest: 'htt/js/script.min.js'
},
dev: {
options: {
beautify: true,
mangel: false,
compress: false,
preserveComments: 'all'
},
src: 'wp/js/*.js',
dest: 'htt/js/script.min.js'
}
},
// Concatenating files
concat: {
build: {
src: ['wp/css/*.css'],
dest: 'htt/css/style.css'
}
},
// Minify CSS
cssmin: {
build: {
//options: {
// banner: '/* Minified CSS */'
//},
files: {
'htt/css/style.min.css' : ['wp/css/**/*.css']
}
}
},
// Watch Tasks
watch: {
js: {
files: ['wp/js/*.js'],
tasks: ['uglify:dev']
}
css: {
files: ['wp/css/*.css'],
tasks: ['']
}
}
});
// Load the Plugins
grunt.loadNpmTasks ('grunt-contrib-uglify');
grunt.loadNpmTasks ('grunt-contrib-watch');
grunt.loadNpmTasks ('grunt-contrib-concat');
grunt.loadNpmTasks ('grunt-contrib-cssmin');
// Register Tasks
grunt.registerTask ('default', ['uglify:dev']);
grunt.registerTask ('build', ['uglify:build', 'cssmin']);
};`
Above is the whole gruntfile.js file

Grunt concat not working during watch task

If I run 'grunt concat' it compiles my JS files as per the Grunt file (line 82). However, it doesn't concatenate when I'm doing 'grunt watch' (line 107).
From what I can see, my file is ok but I'm fairly new to grunt so would love to see if you guys can see an issue.
Here is my full Grunt file...
// All scripts to be included in project go here
var _SCRIPTS = [
'js/prefixfree.js',
'js/jquery-1-10-2.js',
'js/ie-detect.js',
'js/application.js'
];
var _PORT = 7777;
module.exports = function(grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
server: {
options: {
port: _PORT,
base: 'prototype'
}
}
},
htmlvalidation: {
options: {
},
files: {
src: ['prototype/*.php']
},
},
jshint: {
beforeconcat: _SCRIPTS,
afterconcat: ['js/main.js']
},
csslint: {
check: {
src: ['css/*.css']
},
strict: {
options: {
import: 2
},
src: ['css/*.css']
},
lax: {
options: {
import: false
},
src: ['css/*.css']
}
},
compass: {
dev: {
options: {
config: 'config.rb',
force: false
}
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'js/main.js': ['js/main.js']
}
}
},
concat: {
options: {
stripBanners: true,
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */',
},
dist: {
src: _SCRIPTS,
dest: 'js/main.js',
nonull: true
},
},
cssmin: {
add_banner: {
options: {
banner: '/* <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */',
},
files: {
'css/style.css': ['css/style.css']
}
}
},
watch: {
concat: {
files: ['js/**/*.js', '!js/main.js'],
tasks: 'concat',
options: {
spawn: false,
},
},
sass: {
files: ['sass/**/*.scss'],
tasks: ['compass:dev'],
options: {
spawn: false,
},
},
/* watch and see if our javascript files change, or new packages are installed */
/* watch our files for change, reload */
livereload: {
files: ['*.html', 'css/*.css', 'img/*', 'js/*.js'],
options: {
livereload: true
}
},
}
});
// Default task (Watch)
grunt.registerTask('default', ['watch']);
// grunt.registerTask('default', [ 'preprocess:dev', 'watch']);
// Watch with localhost (For Static Templates)
grunt.registerTask('watch_with_server', [ 'connect:server', 'watch']);
// TESTING
// Run all tests
grunt.registerTask('allTests', [ 'jshint:beforeconcat', 'concat', 'jshint:afterconcat', 'cssLint', 'htmlvalidation']);
// JS Testing
grunt.registerTask('jsHint', ['jshint:beforeconcat', 'concat', 'jshint:afterconcat']);
// CSS Testing csslint
grunt.registerTask('cssLint', ['csslint:check']);
grunt.registerTask('cssLintLax', ['csslint:lax']);
grunt.registerTask('cssLintStrict', ['csslint:strict']);
// HTML Vaidation
grunt.registerTask('htmlTest', [ 'htmlvalidation']);
grunt.registerTask('printenv', function () { console.log(process.env); });
// Concat and uglify js and minify css for release
grunt.registerTask('release', [ 'concat:dist', 'uglify', 'cssmin']);
};
Many thanks
I managed to get it working by moving 'livereload' above 'concat' in the watch task. No idea why this would make a difference but it's working!
If anyone has any insight on why this would affect it I'd love to know.
add this and see:
livereload: {
files: ['*.html', 'css/*.css', 'img/*', 'js/*.js'],
options: {
livereload: true
}
},
options: {
livereload: true
},
files: '<%= options.watch.files %>',//might have to change this line
tasks: ['default', 'notify:watch']

Changing grunt uglify config options on watch

I'm trying to alter my default uglify dev options on 'watch', however they're not getting set. I'm planning on adding more subtasks to the uglify task for 'production' as an example, which will use the default options, however for my 'dev' subtask, i'd like to pass new options with the watch task.
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
// ...
uglify: {
// default options
options: {
banner: '<%= banner %>/* Built <%= grunt.template.today("yyyy/mm/dd") %> for <%= powerful.name %> */\n',
preserveComments: 'some',
report: 'min',
mangle: {
except: ['jQuery', 'Backbone']
}
},
dev: {
// options were here...
files: {
// Powerful Theme JS
'<%= powerful.jspath %>touch.min.js':
[
'<%= powerful.jspath %>libs/jquery.hammer.js',
'<%= powerful.jspath %>dev/touch.js'
],
'<%= powerful.jspath %>768down.min.js':
[
'<%= powerful.jspath %>dev/768down.js'
]
}
},
production: {
// production files here, use default options....
}
},
watch: {
js: {
files: ['<%= themesPath %>/**/js/{dev,libs,bootstrap}/*.js'],
tasks: ['uglify:dev'],
options: {
nospawn: true
}
}
}
});
// ...
grunt.event.on('watch', function(action, filepath) {
grunt.config.set('uglify.dev.options', {
banner: '/*! TESTING 123 */',
preserveComments: 'all',
report: false,
compress: false,
beautify: true
});
});
grunt.registerTask('default', ['watch']);
};

Resources