Grunt SyntaxError: Unexpected token - grunt-contrib-imagemin

I'm trying to use Grunt but I get a SyntaxError.
I can't find the solution.
MacBook-Pro-van-Maarten:Project maarten$ grunt imagemin
Loading "Gruntfile.js" tasks...ERROR
SyntaxError: Unexpected token ;
Warning: Task "imagemin" not found. Use --force to continue.
Aborted due to warnings.
Gruntfile.js
module.exports = (function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
imagemin: {
png: {
options: {
optimizationLevel: 7
},
files: [
{
expand: true,
cwd: 'images_src/',
src: ['**/*.png'],
dest: 'images_imagemin',
ext: '.png'
}
]
};
jpg: {
options: {
progressive: true
},
files: [
{
expand: true,
cwd: 'images_src/',
src: ['**/*.jpg','**/*.jpeg'],
dest: 'images_imagemin/',
ext: '.jpg',
}
]
};
};
});
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.registerTask('default', ['imagemin']);
});
Thanks in advance.

It looks like your config is not valid json. try usein , instead of ;
module.exports = (function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
imagemin: {
png: {
options: {
optimizationLevel: 7
},
files: [
{
expand: true,
cwd: 'images_src/',
src: ['**/*.png'],
dest: 'images_imagemin',
ext: '.png'
}
]
},
jpg: {
options: {
progressive: true
},
files: [
{
expand: true,
cwd: 'images_src/',
src: ['**/*.jpg', '**/*.jpeg'],
dest: 'images_imagemin/',
ext: '.jpg',
}
]
},
},
});
grunt.loadNpmTasks('grunt-contrib-imagemin');
grunt.registerTask('default', ['imagemin']);
});

Related

How to get grunt serve task working alongside watch?

I've recently installed and got a it up and running but I can't seem to get it running concurrently with my watch task? In my grunt file, if register the serve task before watch, the server spins up and but the watch task doesn't....and vice versa. This is the serve package and Im using and Grunt file attached:
https://www.npmjs.com/package/grunt-serve
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
dist: {
src: [
'js/libs/*.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
uglify: {
options: {
mangle: false
},
my_target: {
files: {
'js/build/production.min.js': ['js/build/production.js']
}
}
},
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images/',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/build/'
}]
}
},
sass: {
//options: {
// style: 'compressed'
//},
dist: {
files: [{
expand: true,
cwd: 'css',
src: ['*.scss'],
dest: 'css/build/',
ext: '.css'
}]
}
},
serve: {
options: {
port: 9000
}
},
watch: {
options: {
livereload: true,
},
css: {
files: ['css/**/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
},
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
},
}
}
});
// Load all Grunt tasks automatically wihtout having to enter manaually
require('load-grunt-tasks')(grunt);
grunt.registerTask(
'default',
[
'concat',
'uglify',
'sass',
'serve',
'watch'
]
);
};
Grunt serve and grunt watch are both blocking tasks. You can use a plugin like grunt-concurrent to run both at the same time in separate threads. https://github.com/sindresorhus/grunt-concurrent
concurrent: {
target1: ['serve', 'watch'],
}
//aslo update your default task
grunt.registerTask(
'default',
[
'concat',
'uglify',
'sass',
'concurrent:target1'
]
);
Additionally you could also use grunt-concurrent to run your uglify and sass tasks in parallel which may improve build time.

How to pass arguments to grunt task?

I want to refactor my grunt copy task to not repeat the same files over and over for multiple sub tasks. It looks like this right now:
"copy":
{
"web-debug":
{
files:
[
{ src: "libs/1st/**/*", dest: config.buildWebDebugOutPath },
{ src: "libs/3rd/**/*", dest: config.buildWebDebugOutPath },
{ src: "assets/**/*", dest: config.buildWebDebugOutPath },
{ src: "shared/**/*", dest: config.buildWebDebugOutPath },
{ src: "client/**/*", dest: config.buildWebDebugOutPath },
]
},
"web-release":
{
files:
[
{ src: "libs/1st/**/*", dest: config.buildWebReleaseOutPath },
{ src: "libs/3rd/**/*", dest: config.buildWebReleaseOutPath },
{ src: "assets/**/*", dest: config.buildWebReleaseOutPath },
{ src: "shared/**/*", dest: config.buildWebReleaseOutPath },
{ src: "client/**/*", dest: config.buildWebReleaseOutPath },
]
},
Ideally, I just have one copy task that takes a path argument that I can pass to it from an alias task like this:
//
// Let's assume I renamed "web-debug" to "web-files"
//
grunt.registerTask("web-debug", ["web-files:<some debug path>"]);
grunt.registerTask("web-release", ["web-files:<some release path>"]);
What's the simplest way of doing this?
How would I access this passed in argument within the task itself?
You can use templates, as described in this Dynamic Grunt Targets Using Templates blog post. In the context of your code, it might look like this:
"copy":
{
"web-files":
{
files:
[
{ src: "libs/1st/**/*", dest: "<%= grunt.task.current.args[0] %>" },
{ src: "libs/3rd/**/*", dest: "<%= grunt.task.current.args[0] %>" },
{ src: "assets/**/*", dest: "<%= grunt.task.current.args[0] %>" },
{ src: "shared/**/*", dest: "<%= grunt.task.current.args[0] %>" },
{ src: "client/**/*", dest: "<%= grunt.task.current.args[0] %>" },
]
}
You could pass in either the full path or just a partial "debug" or "release" path segment.

Coffeescript Glob To Multiple with multipe cwd and dest

I have such CoffeeScript Config inside my gruntfile.js:
coffee: {
glob_to_multiple: {
expand: true,
flatten: false,
cwd: 'server/api',
src: ['**/*.coffee'],
dest: 'server/api',
ext: '.js',
extDot: 'last'
}
}
I want to add another directory, e.g. cwd: 'server/config' and destination should be dest: 'server/config' for that respectively. How to achieve?
Define another coffee subtask:
coffee: {
glob_to_multiple: {
expand: true,
flatten: false,
cwd: 'server/api',
src: ['**/*.coffee'],
dest: 'server/api',
ext: '.js',
extDot: 'last'
},
other_stuff: {
expand: true,
flatten: false,
cwd: 'server/config',
src: ['**/*.coffee'],
dest: 'server/api',
ext: '.js',
extDot: 'last'
}
}
grunt coffee would run both tasks, grunt coffee:glob_to_multiple would just run the first.

Adding Coffee into Gruntfile.js

I used yo webapp with sass setup this project. I also add compass into grunt and working well.
Once I try to configure coffee in Gruntfile.js. I receive an error message.
Warning: Required config property "coffee.server" missing. Use --force to continue.
This is my Gruntfile.js
Gist
// Generated on 2014-11-24 using
// generator-webapp 0.5.1
'use strict';
// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// If you want to recursively match all subfolders, use:
// 'test/spec/**/*.js'
module.exports = function (grunt) {
// Time how long tasks take. Can help when optimizing build times
require('time-grunt')(grunt);
// Load grunt tasks automatically
require('load-grunt-tasks')(grunt);
// Configurable paths
var config = {
app: 'app',
dist: 'dist'
};
// Define the configuration for all the tasks
grunt.initConfig({
// Project settings
config: config,
// Watches files for changes and runs tasks based on the changed files
watch: {
bower: {
files: ['bower.json'],
tasks: ['wiredep']
},
js: {
files: ['<%= config.app %>/scripts/{,*/}*.js'],
tasks: ['jshint'],
options: {
livereload: true
}
},
jstest: {
files: ['test/spec/{,*/}*.js'],
tasks: ['test:watch']
},
gruntfile: {
files: ['Gruntfile.js']
},
compass: {
files: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'],
tasks: ['compass:server', 'autoprefixer']
},
coffee: {
files: ['<%= config.app %>/scripts/{,*/}*.{coffee}'],
tasks: ['coffee:server', 'autoprefixer']
},
styles: {
files: ['<%= config.app %>/styles/{,*/}*.css'],
tasks: ['newer:copy:styles', 'autoprefixer']
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= config.app %>/{,*/}*.html',
'.tmp/styles/{,*/}*.css',
'<%= config.app %>/images/{,*/}*'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
open: true,
livereload: 35729,
// Change this to '0.0.0.0' to access the server from outside
hostname: 'localhost'
},
livereload: {
options: {
middleware: function(connect) {
return [
connect.static('.tmp'),
connect().use('/bower_components', connect.static('./bower_components')),
connect.static(config.app)
];
}
}
},
test: {
options: {
open: false,
port: 9001,
middleware: function(connect) {
return [
connect.static('.tmp'),
connect.static('test'),
connect().use('/bower_components', connect.static('./bower_components')),
connect.static(config.app)
];
}
}
},
dist: {
options: {
base: '<%= config.dist %>',
livereload: false
}
}
},
// Empties folders to start fresh
clean: {
dist: {
files: [{
dot: true,
src: [
'.tmp',
'<%= config.dist %>/*',
'!<%= config.dist %>/.git*'
]
}]
},
server: '.tmp'
},
// Make sure code styles are up to par and there are no obvious mistakes
jshint: {
options: {
jshintrc: '.jshintrc',
reporter: require('jshint-stylish')
},
all: [
'Gruntfile.js',
'<%= config.app %>/scripts/{,*/}*.js',
'!<%= config.app %>/scripts/vendor/*',
'test/spec/{,*/}*.js'
]
},
// Mocha testing framework configuration options
mocha: {
all: {
options: {
run: true,
urls: ['http://<%= connect.test.options.hostname %>:<%= connect.test.options.port %>/index.html']
}
}
},
// Compiles Sass to CSS and generates necessary files if requested
compass: {
options: {
sassDir: '<%= config.app %>/styles',
cssDir: '.tmp/styles',
imagesDir: '<%= config.app %>/images',
javascriptsDir: '<%= config.app %>/scripts',
fontsDir: '<%= config.app %>/styles/fonts',
generatedImagesDir: '.tmp/images/generated',
importPath: 'bower_components',
httpImagesPath: '../images',
httpGeneratedImagesPath: '../images/generated',
httpFontsPath: 'fonts',
relativeAssets: false,
assetCacheBuster: false
},
dist: {
options: {
generatedImagesDir: '<%= config.dist %>/images/generated'
}
},
server: {
options: {
debugInfo: true
}
}
},
coffee: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/scripts',
src: ['**/*.coffee'],
dest: '.tmp/scripts',
ext: '.js'
}]
},
test: {
files: [{
expand: true,
cwd: '.tmp/spec',
src: '*.coffee',
dest: 'test/spec'
}]
}
},
// Add vendor prefixed styles
autoprefixer: {
options: {
browsers: ['> 1%', 'last 2 versions', 'Firefox ESR', 'Opera 12.1']
},
dist: {
files: [{
expand: true,
cwd: '.tmp/styles/',
src: '{,*/}*.css',
dest: '.tmp/styles/'
}]
}
},
// Automatically inject Bower components into the HTML file
wiredep: {
app: {
ignorePath: /^\/|\.\.\//,
src: ['<%= config.app %>/index.html']
},
sass: {
src: ['<%= config.app %>/styles/{,*/}*.{scss,sass}'],
ignorePath: /(\.\.\/){1,2}bower_components\//
}
},
// Renames files for browser caching purposes
rev: {
dist: {
files: {
src: [
'<%= config.dist %>/scripts/{,*/}*.js',
'<%= config.dist %>/styles/{,*/}*.css',
'<%= config.dist %>/images/{,*/}*.*',
'<%= config.dist %>/styles/fonts/{,*/}*.*',
'<%= config.dist %>/*.{ico,png}'
]
}
}
},
// Reads HTML for usemin blocks to enable smart builds that automatically
// concat, minify and revision files. Creates configurations in memory so
// additional tasks can operate on them
useminPrepare: {
options: {
dest: '<%= config.dist %>'
},
html: '<%= config.app %>/index.html'
},
// Performs rewrites based on rev and the useminPrepare configuration
usemin: {
options: {
assetsDirs: [
'<%= config.dist %>',
'<%= config.dist %>/images',
'<%= config.dist %>/styles'
]
},
html: ['<%= config.dist %>/{,*/}*.html'],
css: ['<%= config.dist %>/styles/{,*/}*.css']
},
// The following *-min tasks produce minified files in the dist folder
imagemin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.{gif,jpeg,jpg,png}',
dest: '<%= config.dist %>/images'
}]
}
},
svgmin: {
dist: {
files: [{
expand: true,
cwd: '<%= config.app %>/images',
src: '{,*/}*.svg',
dest: '<%= config.dist %>/images'
}]
}
},
htmlmin: {
dist: {
options: {
collapseBooleanAttributes: true,
collapseWhitespace: true,
conservativeCollapse: true,
removeAttributeQuotes: true,
removeCommentsFromCDATA: true,
removeEmptyAttributes: true,
removeOptionalTags: true,
removeRedundantAttributes: true,
useShortDoctype: true
},
files: [{
expand: true,
cwd: '<%= config.dist %>',
src: '{,*/}*.html',
dest: '<%= config.dist %>'
}]
}
},
// By default, your `index.html`'s <!-- Usemin block --> will take care
// of minification. These next options are pre-configured if you do not
// wish to use the Usemin blocks.
// cssmin: {
// dist: {
// files: {
// '<%= config.dist %>/styles/main.css': [
// '.tmp/styles/{,*/}*.css',
// '<%= config.app %>/styles/{,*/}*.css'
// ]
// }
// }
// },
// uglify: {
// dist: {
// files: {
// '<%= config.dist %>/scripts/scripts.js': [
// '<%= config.dist %>/scripts/scripts.js'
// ]
// }
// }
// },
// concat: {
// dist: {}
// },
// Copies remaining files to places other tasks can use
copy: {
dist: {
files: [{
expand: true,
dot: true,
cwd: '<%= config.app %>',
dest: '<%= config.dist %>',
src: [
'*.{ico,png,txt}',
'images/{,*/}*.webp',
'{,*/}*.html',
'styles/fonts/{,*/}*.*'
]
}, {
src: 'node_modules/apache-server-configs/dist/.htaccess',
dest: '<%= config.dist %>/.htaccess'
}]
},
styles: {
expand: true,
dot: true,
cwd: '<%= config.app %>/styles',
dest: '.tmp/styles/',
src: '{,*/}*.css'
}
},
// Run some tasks in parallel to speed up build process
concurrent: {
server: [
'compass:server',
'copy:styles',
'coffee:server'
],
test: [
'copy:styles'
],
dist: [
'coffee',
'compass',
'copy:styles',
'imagemin',
'svgmin'
]
}
});
grunt.registerTask('serve', 'start the server and preview your app, --allow-remote for remote access', function (target) {
if (grunt.option('allow-remote')) {
grunt.config.set('connect.options.hostname', '0.0.0.0');
}
if (target === 'dist') {
return grunt.task.run(['build', 'connect:dist:keepalive']);
}
grunt.task.run([
'clean:server',
'wiredep',
'concurrent:server',
'autoprefixer',
'connect:livereload',
'watch'
]);
});
grunt.registerTask('server', function (target) {
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
grunt.task.run([target ? ('serve:' + target) : 'serve']);
});
grunt.registerTask('test', function (target) {
if (target !== 'watch') {
grunt.task.run([
'clean:server',
'concurrent:test',
'autoprefixer'
]);
}
grunt.task.run([
'connect:test',
'mocha'
]);
});
grunt.registerTask('build', [
'clean:dist',
'wiredep',
'useminPrepare',
'concurrent:dist',
'autoprefixer',
'concat',
'cssmin',
'uglify',
'copy:dist',
'rev',
'usemin',
'htmlmin'
]);
grunt.registerTask('default', [
'newer:jshint',
'test',
'build'
]);
};
in your config you register a task saying there is a "server" entry in the coffee configuration:
coffee: {
files: ['<%= config.app %>/scripts/{,*/}*.{coffee}'],
tasks: ['coffee:server', 'autoprefixer']
},
You only have the coffee task suitable for that so try
coffee: {
files: ['<%= config.app %>/scripts/{,*/}*.{coffee}'],
tasks: ['coffee']
},

Copy files recursively with grunt-ssh

I try to use grunt-ssh for deployment. But I get only the files of the folder copied:
sftp: {
deploy: {
files: {
"./": "doc/*"
},
options: {
path: '<%= pkg.server.path %>',
host: '<%= pkg.server.host %>',
username: '<%= pkg.server.user %>',
password: '<%= pkg.server.password %>',
showProgress: true,
srcBasePath: 'doc/'
}
}
}
How can I get the whole local folder including its subfolders (recursively) doc copied to the remote?
Taking a quick look into the sources solved my problem:
sftp: {
deploy: {
files: {
"./": "doc/**"
},
options: {
path: '<%= pkg.server.path %>',
host: '<%= pkg.server.host %>',
username: '<%= pkg.server.user %>',
password: '<%= pkg.server.password %>',
showProgress: true,
srcBasePath: 'doc/',
createDirectories: true
}
}
}