I have this setup in my Gruntfile.js
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
options: {
compress: false,
yuicompress: false,
optimization: 0
},
files: {
// target.css file: source.less file
"assets/css/main.css": "assets/css/main.less"
},
}
},
watch: {
styles: {
// Which files to watch (all .less files recursively in the less directory)
files: ['assets/css/*.less', 'assets/less/*.less'],
tasks: ['less'],
},
// Live reload CSS
css: {
files: ['assets/css/*.css'],
options: {
nospawn: true,
interrupt: false,
livereload: true,
},
},
},
});
// Watch
grunt.loadNpmTasks('grunt-contrib-watch');
// Less Complile
grunt.loadNpmTasks('grunt-contrib-less');
grunt.registerTask('default', ['less','watch']);
};
My sylesheet is loaded like this:
<link rel="stylesheet" href="http://project.dev/wp-content/themes/project/style.css">
Whenever I change the css file the I get a 404 error in the browser for this url
http://project.dev/assets/css/main.css?livereload=1392748371895
Which is of course right because the css file lives in:
http://project.dev/wp-content/themes/project/assets/css/main.css
How do I get live reload to get the right URL?
You have to set the base so that Grunt knows where to run the application from. The files the tasks output should be set to reflect the structure Wordpress expects. Its all in the path configuration.
You can achieve a more flexible path structure if you configure it early on Grunt's configuration. Assuming that the Gruntfile.js is in the root of your site (besides the wp-content directory), you could do the following configuration:
grunt.initConfig({
// configurable paths
cfg: {
dist: './wp-content/themes/project'
},
// tasks configurations come here...
});
Then on the watch task, you'd set:
livereload: {
files: ['<%= cfg.dist %>/assets/css/*.css'],
options: {
nospawn: true,
interrupt: false,
livereload: true
}
}
The resulting Gruntfile.js would look like:
module.exports = function(grunt) {
grunt.initConfig({
// configurable paths
cfg: {
dist: './wp-content/themes/project'
},
less: {
development: {
options: {
compress: false,
yuicompress: false,
optimization: 0
},
files: {
'<%= cfg.dist %>/assets/css/main.css': '<%= cfg.dist %>/assets/css/main.less'
}
}
},
watch: {
styles: {
files: ['<%= cfg.dist %>/assets/css/*.less', '<%= cfg.dist %>/assets/less/*.less'],
tasks: ['less']
},
css: {
files: ['<%= cfg.dist %>/assets/css/*.css'],
options: {
nospawn: true,
interrupt: false,
livereload: true
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['less','watch']);
};
You'd still have to adjust the above to fit your needs, but the principle is there.
I don't have a setup I can test this on, but I think you need to set the base option:
// Project configuration.
grunt.initConfig({
connect: {
server: {
options: {
base: 'www-root'
}
}
}
});
See doc here: https://github.com/gruntjs/grunt-contrib-connect/blob/master/README.md#basic-use
Read down through multiple servers if relevant.
Related
I'm setting a grunt file for a task. My goal is to create a css file from a sass file (scss) and add an autoprefix to all the proprieties which require so. Initially I used the propriety multifiles but it didn't work, so now I'm using the target propriety that works fine, but my problem is, even if I target the very same file, it will create another file in my folder where I put all my sass files.
So far my file is the following:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dev: {
options: {
style: 'expanded',
sourcemap: 'none',
},
files: {
'../style.css': 'scss/style.scss'
}
},
dist: {
options: {
style: 'compressed',
sourcemap: 'none',
},
files: {
'../style-min.css': 'scss/style.scss'
}
}
},
autoprefixer: {
options: {
browsers: ['last 6 versions']
},
target: {
expand: true,
flatten: true,
src: '../style.css',
dest: ''
}
},
watch: {
css: {
files: '**/*.scss',
tasks: ['sass', 'autoprefixer']
}
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-autoprefixer');
grunt.registerTask('default', ['watch']);
}
My goal is to set up a global task for all my css files, like so:
target: {
expand: true,
flatten: true,
src: '*.css',
dest: ''
}
but it is not working even if I try something like:
target: {
expand: true,
flatten: true,
src: '../*.css',
dest: ''
}
Does anyone know why?
Use cwd (stands for current working directory) which is the path where grunt looks for the files matching the pattern in src. Also define the dest so that it would create the destination file in the same folder.
target: {
expand: true,
flatten: true,
cwd: '../',
src: [ '**/*.css' ],
dest: '../'
}
I'm trying to build a website with Bootstrap, using Grunt to run tasks. I have been trying to figure out why my gruntfile does not seem to be running any tasks except for 'watch', but I can't seem to find the answer. No errors show up either. In terminal, time-grunt will show the execution time (although no tasks are executed) and then it would say 'Waiting....' which means watch is running. Could someone shed some light on what I've done wrong in my gruntfile? Any help would be greatly appreciated :)
module.exports = function(grunt) {
//time
require('time-grunt')(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
dist: {
options: {
sourceMap: true,
style: 'compressed',
},
files: {
'assets/css/style.css' : 'assets/scss/style.scss',
}
}
},
copy: {
scripts: {
cwd: 'bower_components/jquery/dist/',
expand: true,
src: [
'jquery.min.js',
],
dest: 'assets/js/',
filter: 'isFile',
}
},
concat: {
options: {
separator: ';',
},
js: {
src: [
'bower_components/bootstrap-sass/assets/javascripts/bootstrap.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/button.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/collapse.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/modal.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/tab.js',
'bower_components/bootstrap-sass/assets/javascripts/bootstrap/transition.js',
],
dest: 'assets/js/bootstrap.js',
},
sass: {
src: [
'bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss',
'bower_components/bootstrap-sass/assets/stylesheets/bootstrap/**/*.scss'
],
dest: 'assets/scss/style.scss'
}
},
uglify: {
options: {
mangle: false,
},
my_target: {
files: {
'assets/css/style.min.css' : ['assets/css/style.css'],
'assets/js/bootstrap.min.js' : ['assets/js/bootstrap.js']
}
}
},
watch: {
gruntfile: {
files: 'Gruntfile.js',
tasks: ['jshint:gruntfile'],
options: {
livereload: true
}
},
src: {
files: ['assets/js/*.js', 'assets/scss/*.scss'],
tasks: ['default'],
options: {
livereload: true
}
}
},
jshint: {
all: ['Gruntfile.js', 'assets/**/*.js']
},
});
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('build', ['sass', 'copy', 'concat', 'uglify']);
grunt.registerTask('default', ['watch', 'jshint']);
};
Your tasks names and orders were a bit mixed up, here are 3 points to fully fix it - and provide StackOverflow with an answer to the question:
watch should always be the last task to run, as it does not end. So:
grunt.registerTask('default', ['jshint', 'watch']);
if you want to run a task (like build by just calling grunt, you have to put it in your default task, so:
grunt.registerTask('default', ['jshint', 'build', 'watch']);
your watch task must not launch a watch task itself, so watch.src should not call default (as default includes watch):
watch: {
gruntfile: {
files: 'Gruntfile.js',
tasks: ['jshint:gruntfile'],
options: {
livereload: true
}
},
src: {
files: ['assets/js/*.js', 'assets/scss/*.scss'],
tasks: ['jshint', 'build'],
options: {
livereload: true
}
}
},
I'm using Yeoman template to develop a static web site. grunt serve nicely works with the auto reload plugin.
For repeating elements I started to use {{mustache}} partials and it works like a blast. Now I want the auto reload to assemble my page, so I can look at the resulting page when editing one of the mustache files (either a main file or a partial).
I found a grunt task for it, but stitching it together eludes me. My config looks like this:
grunt.initConfig({
sass: {
dev: {
src: ['src/sass/*.sass'],
dest: 'dest/css/index.css',
},
},
watch: {
sass: {
// We watch and compile sass files as normal but don't live reload here
files: ['src/sass/*.sass'],
tasks: ['sass']
},
mustache: {
files: '**/*.mustache',
tasks: ['mustache_render'],
options: {
interrupt: true
},
},
livereload: {
options: { livereload: true },
files: ['dest/**/*']
}
},
mustache_render: {
options: {
{data: 'common-data.json'}
},
your_target: {
files: [
{expand: true,
template: '**/*.mustache',
dest: 'dest/'}
]
}
}
});
I must be missing something since the html files are not updated when I save the file.
You can add the livereload option directly to your mustache target options.
grunt.initConfig({
watch: {
mustache: {
files: '**/*.mustache',
tasks: ['mustache_render'],
options: {
interrupt: true,
livereload: true
},
}
},
mustache_render: {
options: {
{data: 'common-data.json'}
},
main: {
files: [
{expand: true,
template: '**/*.mustache',
dest: 'dest/'}
]
}
}
});
Also, if you're using grunt-contrib-connect to serve your files, don't forget to add the livereload option to it:
connect: {
http: {
options: {
hostname: "*",
port: process.env.PORT || 80,
livereload: true
}
}
}
I'm trying to use grunt to compile my less files into css while in development. While at it also, watch and reload. The file I've wrote is this:
module.exports = function(grunt) {
grunt.initConfig({
less: {
development: {
options: {
compress: true,
yuicompress: true,
optimization: 2
},
files: {
// target.css file: source.less file
"public/css/bootstrap.css": "./public/less/bootstrap.less"
}
}
},
watch: {
styles: {
// Which files to watch (all .less files recursively in the less directory)
files: ["public/less/*"],
tasks: ['less'],
options: {
livereload: true,
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default', ['watch']);
};
And I have this saved as a gruntfile.js in my project root's directory. What am I doing wrong?
PS: I'm using forever to start my app and in the same terminal window I'm using the command grunt watch, however when I change my less files nothing happens.
PPS: My file structure is as follows:
root
-- public
-- less
-- css
As you can see above my main less file is located at root/public/less/bootstrap.less and I'd like the css to be compiled at root/public/css/bootstrap.css
Many thanks
Your setup seems to be good but I found a problem here... may be it solves your Question
"public/css/bootstrap.css": "./public/less/bootstrap.less"
^^
your url is same but in second appearance you have add extra "./" I think if you remove this it will work.
This is my own code and it is working fine.
module.exports = function(grunt){
grunt.initConfig({
//pkg:grunt.file.readJSON('package.json'),
less:{
development:{
options:{
compress: true,
yuicompress: true,
optimization: 2
},
files:{
'webroot/css/meer/index/index2.css' : 'webroot/css/meer/index/index2.less'
}
}
},
watch: {
styles:{
options:{
livereload: true,
spawn: false,
event: ['added','deleted','changed']
},
files:['webroot/css/meer/index/*.less'],
tasks:['less']
}
}
});
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.registerTask('default',['watch']);
}
I am trying to use TypeScript inside a Yeoman / Grunt project. To compile TypeScript I use a grunt plugin called grunt-ts, the compilation of the .ts files works just fine, but the live reload doesn't works:
When I run grunt server I correctly get this:
Running "ts:dev" (ts) task
Compiling.
Success: 3.37s for 2 typescript files
Watching all Typescript files under : /home/mimo/webroot/tsyong/app/scripts
But then the liveReload task is not loaded.
This is how I configured my Gruntfile.js about grunt-ts.
grunt.initConfig({
...
ts: {
options: { // use to override the default options, http://gruntjs.com/configuring-tasks#options
target: 'es3', // es3 (default) / or es5
module: 'commonjs', // amd , commonjs (default)
sourcemap: true, // true (default) | false
declaration: false, // true | false (default)
nolib: false, // true | false (default)
comments: false // true | false (default)
},
dev: { // a particular target
src: ['<%= yeoman.app %>/scripts/{,*/}*.ts'], // The source typescript files, http://gruntjs.com/configuring-tasks#files
reference: '<%= yeoman.app %>/scripts/reference.ts', // If specified, generate this file that you can use for your reference management
out: '<%= yeoman.app %>/scripts/out.js', // If specified, generate an out.js file which is the merged js file
watch: '<%= yeoman.app %>/scripts/', // If specified, configures this target to watch the specified director for ts changes and reruns itself.
options: { // override the main options, http://gruntjs.com/configuring-tasks#options
sourcemap: true,
declaration: true
},
},
build: { // another target
src: ['<%= yeoman.app %>/scripts/*.ts'],
options: { // overide the main options for this target
sourcemap: false,
}
},
},
...
...
grunt.task.run([
...
'ts',
...
]);
...
grunt.registerTask('build', [
...
'ts',
...
]);
You can have a look at the full Gruntfile.js: https://github.com/mimo84/tsyong/blob/master/Gruntfile.js
Short answer: remove the watch config line https://github.com/mimo84/tsyong/blob/master/Gruntfile.js#L46 and add something like https://github.com/mimo84/tsyong/blob/master/Gruntfile.js#L60
But for ts. i.e.
ts: {
files: ['<%= yeoman.app %>/scripts/{,*/}*.ts'],
tasks: ['ts:dev']
},
Reason: That's because when you ask grunt-ts to watch a folder, grunt-ts marks itself as an async task. This means that then no other tasks can execute afterwards. Its the same with grunt-contrib-watch I think which is why you must have it as the last task:
grunt.task.run([
'clean:server',
'concurrent:server',
'ts',
'connect:livereload',
'open',
'watch' // last task
]);
In short you can only have one task do your watching :) In your case it would have to be grunt-contrib-watch.
I use a very fast and simple way, using browserify & typescriptifier (<2s reload):
module.exports = function (grunt) {
grunt.initConfig({
clean: {
dev: ['dest/**/*.*']
},
browserify: {
dev: {
src: ['src/root.ts'],
dest: 'dest/App.js',
options: {
external: ['angular'],
transform: ['typescriptifier'],
debug: true,
bundleOptions: { debug: true },
browserifyOptions: { debug: true }
}
}
},
express: {
dev: {
options: {
bases: ['src'],
port: 5000,
hostname: '0.0.0.0',
livereload: false
}
}
},
watch: {
ts: {
files: ['src/**/*.ts', '!src/**/*.d.ts'],
tasks: ['dest'],
options: {
livereload: true,
debug: false,
debounceDelay: 100
}
},
html: {
files: ['src/**/*.css', 'src/**/*.html'],
options: {
livereload: true,
debug: false,
debounceDelay: 100,
spawn: false
}
}
}
});
grunt.loadNpmTasks('grunt-express');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.registerTask('dev', ['rebuild', 'express:dev', 'watch' ]);
grunt.registerTask('build', ['browserify:dev']);
grunt.registerTask('rebuild', ['clean:dev', 'build']);
};
See
https://www.npmjs.org/package/typescriptifier
Not exactly the answer but goes to the underlying point: fast workflow.