I have a simple Jekyll site, and am using grunt to compile LESS files.
I want to build in the ability to continue compiling .less files, building the jekyll site & serving it locally. I also have a task to watch and copy compiled css files into the jekyll _site folder.
However the Grunftile I have at the moment isn't quite working:
module.exports = function (grunt) {
grunt.initConfig({
// compile set less files
less: {
development: {
options: {
paths: ["assets/less"],
yuicompress: true,
compress: true
},
files: {
"assets/css/site.css": ["assets/less/*.less", "!assets/less/_*.less"]
}
}
},
// watch changes to less files
watch: {
styles: {
files: ["less/**/*"],
tasks: ["less", "copy:css"]
},
options: {
livereload: true,
spawn: false,
},
},
// copy compiled css to _site
copy: {
css : {
files: {
cwd: './assets/css/',
src: 'site.css',
dest: './_site/assets/css',
expand: true
}
}
},
// run jekyll command
shell: {
jekyll: {
options: {
stdout: true
},
command: 'jekyll build'
}
},
// jekyll build
jekyll: {
files: [
'*.html', '*.yml', 'assets/js/**.js',
'_posts/**', '_includes/**'
],
tasks: 'shell:jekyll',
options: {
livereload: true
}
},
exec: {
server: {
command: 'jekyll serve -w'
}
},
concurrent: {
options: { logConcurrentOutput: true },
server: {
tasks: ['watch', 'exec:server']
}
}
});
// Load tasks so we can use them
grunt.loadNpmTasks("grunt-contrib-watch");
grunt.loadNpmTasks("grunt-contrib-less");
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-concurrent');
// the default task will show the usage
grunt.registerTask("default", "Prints usage", function () {
grunt.log.writeln("");
grunt.log.writeln("Using Base");
grunt.log.writeln("------------------------");
grunt.log.writeln("");
grunt.log.writeln("* run 'grunt --help' to get an overview of all commands.");
grunt.log.writeln("* run 'grunt dev' to start watching and compiling LESS changes.");
});
grunt.registerTask("dev", ["less:development", "watch:styles", "copy:css", "shell:jekyll", "concurrent:server"]);
};
It's probably better to have Grunt also building Jekyll, using grunt-jekyll https://github.com/dannygarcia/grunt-jekyll. I suspect you're having issues with Jekyll cleaning the output directory after your copy task has placed your compiled LESS output there, so it's important your tasks are run in the correct sequence.
There's an excellent Yeoman generator with a complete Jekyll / Grunt workflow that's also worth checking out; https://github.com/robwierzbowski/generator-jekyllrb and if you don't want to use Yeoman then you will at least find some helpful pointers in the Gruntfile https://github.com/robwierzbowski/generator-jekyllrb/blob/master/app/templates/Gruntfile.js
Related
Write a grunt file to validate js
files using jshint, minify html files, start the web server and watch the local web server.
Validate js files with jshint.
The source file is located in "src/js".
Minify the html files in "src" folder and place it inside "dest/src" folder with same file
name.
After html minification, setup and run a local web server.
Run the watch task to watch the webserver.
Use the IDE terminal to install
plugins.
Use official grunt plugins only.
Install necessary grunt commands for all the below tasks and make sure the commands are saved in packages.json and try this:
module.exports = function(grunt) {
require('jit-grunt')(grunt);
grunt.initConfig({
jshint: {
files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
options: {
globals: {
jQuery: true
}
}
},
htmlmin: { // Task
dist: { // Target
options: { // Target options
removeComments: true,
collapseWhitespace: true
},
files: { // Dictionary of files
'dest/src/form.html': 'src/form.html', // 'destination': 'source'
'dest/src/management.html': 'src/management.html'
}
}
},
watch: {
styles: {
files: ['less/**/*.less'], // which files to watch
tasks: ['less'],
options: {
nospawn: true
}
}
},
connect: {
server: {
options: {
port: 9000,
base: 'app',
keepalive: false
}
}
}
});
grunt.registerTask('default', ['htmlmin','jshint','connect','watch']);
};
I've started to learn this just now. I installed the grunt.
If I get grunt watch it is automatic but only in case one file.
How could I make it wath all scss file in my theme, and make the css in different folders.
I don't really undestand how could it working in big.
This is my gruntfile.js now:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
connect: {
uses_defaults: {}
},
sass: {
dev: {
options: { sourceMap: true },
files: { 'sites/all/themes/uj/css/uj.styles.css' : 'sites/all/themes/uj/sass/uj.styles.scss' }
}
},
watch: {
css: {
files: 'sites/all/themes/uj/**/*.scss',
tasks: [ 'sass:dev' ],
options: { livereload: true }
}
}
});
// Load Grunt plugins
// grunt.loadNpmTasks('');
// Default task(s).
grunt.registerTask('default', []);
// Load Grunt plugins
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
};
Per the official documentation on file globbing, to watch for changes for files of a certain file type in the directory path and its subdirectories, you'll want:
files: ['js/**/*.js']
or:
files: ['css/**/*.*']
I'm trying to build a Grunt task that minifys my JS files and return a single minified JS file.
This is my gruntfile.js file:
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
minified: {
files: {
src: [
'js/*.js',
],
dest: 'js/min/'
},
options: {
allinone: true
}
},
});
grunt.loadNpmTasks('grunt-minified');
};
When I run the task it does work, but it also returns an error.
> cmd.exe /c grunt -b "C:\Users\alucardu\documents\visual studio 2015\Projects\JS-demo\JS-demo" --gruntfile "C:\Users\alucardu\documents\visual studio 2015\Projects\JS-demo\JS-demo\Gruntfile.js" minified
Running "minified:files" (minified) task
Warning: Cannot read property 'yellow' of undefined Use --force to continue.
Process terminated with code 3.
Aborted due to warnings.
I've done a search action in my entire solution for 'yellow' but it doesn't return any results. Also when I empty both my JS files that are being minified it still returns the error.
Does anyone know why it's returning this error?
By removing the
options: {
allinone: true
}
The warning no longer showed up, but it also doesn't concat the files together. So I've added another task called concat. So now my gruntfile looks like this:
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
watch: {
scripts: {
files: ['js/*.js'],
tasks: ['concat', 'minified', 'uglify'],
},
},
concat: {
dist: {
src: ['js/*.js'],
dest: 'js/min/concat.js'
},
},
minified: {
files: {
src: ['js/min/concat.js'],
dest: 'js/min/minified.js'
},
},
uglify: {
my_target: {
files: {
'js/min/uglify.js': ['js/min/minified.jsconcat.js']
}
}
},
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-minified');
grunt.loadNpmTasks('grunt-contrib-uglify');
};
And it seems to be working fine.
I am currently trying to configure grunt-sync to run inside a watch and am running into issues. I've reported the issue to the module's github page but decided to post here to draw upon the general development population rather than wait for a single contributor to come across my issue report.
So, I'm thinking this may just be a gap in my understanding of how to drive grunt tasks through a watch. I've got watches up and running for several tasks already and I'm adding grunt-sync to my workflow to automate publication of my changes to a network directory that blah blah blah...not important; my watch is working for some stuff but not for this. I'm dropping in the relevant config section along with my "concurrent","karma", and "sass" tasks to give you the gist of my overall grunt config.
module.exports = function(grunt){
grunt.initConfig({
pkg: grunt.file.readJSON("package.json"),
project: {
app: 'app',
},
sync:{
main: {
files:
[
{
cwd: 'app/',
src: [
'**/*.js',
'**/*.html',
'**/*.css',
'!app/node_modules/**'
],
dest: ['publish/']
}
],
verbose: true
}
},
karma: {
unit: {
configFile: 'test/karma.conf.js'
},
continuous:{
configFile: 'test/karma.conf.js',
singleRun: true,
browsers: ['PhantomJS']
}
},
sass:{
dev: {
options:{
style: 'expanded',
compass: false
},
files:{
'app/css/app.css':'app/css/app.scss'
}
},
dist: {
options: {
style: 'compressed',
compass: false
},
files:{
'app/css/app.css':'app/css/app.scss'
}
}
},
watch: {
sass: {
files: 'app/css/**/{,*/}*.{scss,sass}',
tasks: ['sass:dev']
},
styles: {
files: ['app/css/app.css'],
tasks: ['autoprefixer']
},
// karma: {
// files: ['test/*.js',
// 'test/**/*.js'
// ],
// tasks: ['karma:unit:run']
// },
livereload:{
options: {livereload: true},
files: ['app/**/*'],
},
sync:{
files: ['app/**'],
tasks: ['sync:main']
}
},
concurrent:
{
target: {
tasks: [
'karma:unit',
'watch'
],
options: {
logConcurrentOutput: true
}
}
}
});
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.registerTask('default', [
'sass:dev',
'concurrent:target'
]
);
};
Currently receiving the following warning when I grunt
Warning: Task "sync:main" not found. Use --force to continue.
Aborted due to warnings.
Since there is only the main subtask, I thought that maybe changing the watch from executing ['sync:main'] to executing ['sync'] would possibly work. The warning goes away but poof nothing happens...so I'm not sure if the issue is with my config or with the module implementation.
Any ideas?
Edit to Add:
From the module's github site, I see the following in sync.json
{
"main": {
"files": [{
"src": ["**"],
"dest": "bin/to",
"cwd": "bin/from"
}]
}
}
so that would lead me to believe that "main" is the name I should be using for the sync subtask. I'm really confused as to why grunt isn't recognizing it in my config, but I am not too terribly familiar with dissecting the code for grunt modules.
Well...turns out I referenced a module in my gruntfile before I ran npm install on it and then decided to come on the internet to tell everybody about it.
Edit:
To partially exonerate myself, I found the console that I used to run npm install grunt-sync --save-dev. I had run it, but I was in the
wrong directory; it added it to the wrong gruntfile.
To answer my own question, the gruntfile packaged with the [grunt-sync] module contains a watch section, so you just have to have grunt-contrib-watch installed; you don't have to do anything special. And that makes sense. A folder synchronization task would be pretty darned worthless without a file system watch, so it is perfectly reasonable to run the task in a very broad watch but with an inherent blacklist (it watches all files in all folders but only operates on files matching a src pattern.
So to get it to syn-down all files on all file changes,
sync: {
main:{
files:[{
src:[
'**'
]
, dest: 'publish'
}
]
,verbose: true
}
},
will copy all files to the publish subdirectory. I run mine inside a concurrent task
concurrent:
{
target: {
tasks: [
'karma:unit',
'sync:main',
'watch'
],
options: {
logConcurrentOutput: true
}
}
}
Personally, I'll probably be swapping this out with grunt-rsync because grunt-sync simply performs the file copy task inside [sync:main] What I want it to do is to only send deltas to the publish folder every time I save a file; that's a task for rsync.
I am trying to achieve a smooth workflow.
my problem:
My JS modifications are shown and minified and the live reload works fine. When I make changes to my SCSS files they do not run under the run command:
grunt
or the grunt plugin:
grunt watch
It only works when I invoke:
grunt sass
This was the output from the 'grunt sass' console window:
Macintosh:grunt-test Neil$ grunt sass
Running "sass:dist" (sass) task
File "css/global.css" created.
Done, without errors.
Notes:
When I run 'grunt watch' on a sass file I have noticed that grunt runs the minification on the javascript for no reason. Surely this be invoked when that file or one of its dependencies is effected?
Gruntfile.js Contents:
module.exports = function(grunt) {
// 1. All configuration goes here
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
options: {
files: ['css/*.css'],
livereload: true
},
css: {
files: ['css/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
},
scripts: {
files: ['js/*.js', 'scss/*.scss'],
tasks: ['concat', 'uglify'],
options: {
spawn: false,
}
}
},
sass: {
dist: {
options: {
style: 'compressed'
},
expand: true,
cwd: 'scss/',
src: ['*.scss'],
dest: 'css/',
ext: '.css'
}
},
concat: {
// 2. Configuration for concatinating files goes here.
dist: {
src: [
'js/libs/*.js', // All JS in the libs folder
'js/global.js' // This specific file
],
dest: 'js/build/production.js',
}
},
uglify: {
build: {
src: 'js/build/production.js',
dest: 'js/build/production.min.js'
}
},
imagemin: {
dynamic: {
files: [{
expand: true,
cwd: 'images-lossy/',
src: ['**/*.{png,jpg,gif}'],
dest: 'images/'
}]
},
png: {
options: {
optimizationLevel: 7
}
},
jpg: {
options: {
progressive: true
}
}
}
});
// 3. Where we tell Grunt we plan to use this plug-in.
// CONCATENATION PLUGIN
grunt.loadNpmTasks('grunt-contrib-concat');
// MINIFY PLUGIN
grunt.loadNpmTasks('grunt-contrib-uglify');
// IMG CRUSH PLUGIN
grunt.loadNpmTasks('grunt-contrib-imagemin');
// GRUNT WATCH PLUGIN
grunt.loadNpmTasks('grunt-contrib-watch');
// SASS LIBARY PLUGIN
grunt.loadNpmTasks('grunt-contrib-sass');
// 4. Where we tell Grunt what to do when we type "grunt" into the terminal.
grunt.registerTask('default', ['sass','concat', 'uglify', 'imagemin', 'watch']);
};
I hope the above information helps. I have previously used Codekit, and it a really great app. I want to move to grunt but maybe my configuration file is incorrect I am close.
Any help would be greatly appreciated.
Neil
It looks like both of your issues occur within the watch configuration.
First, the reason the SASS task isn't working during watch is due to the files entry pointing to the wrong location. Your current files entry points to the "css" folder, but it should point to the "scss" folder, according to what you've specified in the actual "sass" task. In other words, your entry should be: files: ['scss/*.scss'].
css: {
files: ['scss/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
}
Second, the JavaScript minification occurs during the watch whenever a SASS file changes because you have it listed here:
scripts: {
files: ['js/*.js', 'scss/*.scss'], // <-- scss is covered here
tasks: ['concat', 'uglify'],
options: {
spawn: false,
}
}
Change it to files: ['js/*.js'], instead to have the watch task kick in for JavaScript files only.
Once you address those issues, if things are slightly working you might want to expand the patterns so that it covers all files in the subdirectories for your JavaScript, CSS, SASS, etc. For example, js/*.js includes all .js files under the js folder, while js/**/*.js covers the js folder and its subfolders. You can read more under the GruntJS "globbing patterns" documentation.
EDIT: here's how the updated watch should look like...
watch: {
options: {
livereload: true
},
// css is really for Sass
css: {
files: ['scss/*.scss'],
tasks: ['sass'],
options: {
spawn: false,
}
},
// scripts will detect js changes
scripts: {
files: ['js/**/*.js'],
tasks: ['jshint', 'concat', 'uglify'],
options: {
spawn: false,
}
}
},
As mentioned, your individual tasks might need to use the ** pattern similar to what I've done with the "scripts" entry above: js/**/*.js