Grunt-watch livereload does not work with compiled files (stylus, jade, etc.) - css

My livereload is "working" in that it live reloads the page when a file is changed, but only if I modify the file directly. If the file is generated through the grunt stylus or jade compiler, nothing happens.
When I look at grunt with verbose turned on, the Live reloading root.css... line appears only if I save root.css directly. If root.css is modified through the stylus compiler, the line does not appear. It's as if watch doesn't detect the file has been changed if it's changed through a compiler. This same issue occurs with jade as well.
Here's my stylus task (trimmed):
stylus: {
options: {
compress: false,
use: [
require('autoprefixer-stylus')
]
},
src: [
'app/styl/**/*.styl'
],
dest: 'build/css/root.css'
}
And here's my watch task (trimmed):
livereload: {
options: {
livereload: 1337,
},
files: 'build/**/*'
},
stylus: {
files: [
'app/styl/**/*.styl',
],
tasks: ['stylus:dev']
},
I really hope I'm just doing something stupid. I can't find any problems similar to this one.
EDIT:
Just in case this helps, I discovered that by changing my grunt task from running ['clean','jade:dev', 'stylus:dev', 'connect:dev', 'watch'] to only running ['connect:dev', 'watch'], livereload works as intended once, then never again. (Modifying the css directly still works though.)
EDIT 2:
I was able to fix this by adding livereload to each specific task in watch, like so:
livereload: {
options: {
livereload: 1337,
},
files: 'build/**/*'
},
stylus: {
files: [
'app/styl/**/*.styl',
],
tasks: ['stylus:dev'],
options: {
livereload: 1337
}
},
As to why this works, I have no idea. If anyone can shed some light on this, it'd be much appreciated. Though to be honest, I don't know why I didn't try this earlier.

Related

Grunt run task depending of file modified, it's possible?

can you help-me with this problem?
I need run a specific task depending of file modified, for example:
Modifie: _header.scss
Run: sass:header task
Modifie: _footer.scss
Run: sass:footer task
Modifie: _banners.scss
Run: sass:banners task
I've been trying to get the name of the file at save time to use it as a parameter, but I can not figure out ways to do this.
My project allows more people to work simultaneously but the work of defining which component of the project will be exported to CSS is manual, so I am trying to make this process of compiling the final CSS of each module as automatic.
My problem is how I can identify the name of the modified file, not the type of file.
Thank you very much!
It should look like this. When sass files are changed, grunt generates css files and copies (to dist directory) changed files only. Also as far as you can see connect and watch task implement live reload.
connect: {
options: {
port: ...
livereload: 35729,
hostname: '127.0.0.1'
},
livereload: {
options: {
base: [
'some dist'
]
}
}
},
// check that files are changed
watch: {
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'your dist/*.css'
]
},
// when sass file is changed, tasks will run
// newer:copy means that we have to do task copy with changed files only
sass: {
files: ['your dir/*.sass'],
tasks: ['sass', ...some other tasks like cssmin..., 'newer:copy']
}
},
sass: {
dist: {
files: [
...sass to css
]
}
},
copy: {
css: {
....
}
}
Also you can be interested in task like grunt-changed. The task configures another task to run with src files that have been changed. For more information please check the page grunt-changed

Task "typescript" failed in grunt

I have written below code in gruntFile.js.
typescript: {
base: {
options: {
target: 'es5',
sourceMap: true,
noImplicitAny: true
}
},
default: {
files: [
{ src: 'source/tests/**/*.ts', dest: 'build'},
{ src: 'source/scripts/**/*.ts', dest: 'build'}
]
}
},
and I am trying to run "grunt typescript" command from command line. It is showing below error.
I have tryed "grunt typescript --force" command also. but still it is not working.
still it is not create build folder and it means that task is not working properly. Thanks in advance.
EDIT:- I have change my gruntfile.js to below as suggest in answer.
typescript: {
base: {
src: ['source/tests/**/*.ts'],
dest: 'build/',
options: {
target: 'es5',
sourceMap: true,
noImplicitAny: true
}
},
}
But still I am facing same problem.
Looking at the most current documentation that I could find for grunt-typescript, your syntax is wrong. I have a feeling that you actually want to be using grunt-ts. It's also the plugin I know of that is compatible with the syntax you've supplied.
My personal opinion: Use grunt-ts, it's been much easier to work with, and I've gone through a few iterations of trying out a bunch of tools to get to our current build environment.

Why is it recommended to use concat then uglify when the latter can do both?

I keep seeing the recommendation for making JS files ready for production to be concat then uglify.
For example here, in on of Yeoman's grunt tasks.
By default the flow is: concat -> uglifyjs.
Considering UglifyJS can do both concatenation and minification, why would you ever need both at the same time?
Thanks.
Running a basic test to see if there is a performance difference between executing concat and then uglify vs. just uglify.
package.json
{
"name": "grunt-concat-vs-uglify",
"version": "0.0.1",
"description": "A basic test to see if we can ditch concat and use only uglify for JS files.",
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-concat": "^0.5.0",
"grunt-contrib-uglify": "^0.6.0",
"load-grunt-tasks": "^1.0.0",
"time-grunt": "^1.0.0"
}
}
Gruntfile.js
module.exports = function (grunt) {
// Display the elapsed execution time of grunt tasks
require('time-grunt')(grunt);
// Load all grunt-* packages from package.json
require('load-grunt-tasks')(grunt);
grunt.initConfig({
paths: {
src: {
js: 'src/**/*.js'
},
dest: {
js: 'dist/main.js',
jsMin: 'dist/main.min.js'
}
},
concat: {
js: {
options: {
separator: ';'
},
src: '<%= paths.src.js %>',
dest: '<%= paths.dest.js %>'
}
},
uglify: {
options: {
compress: true,
mangle: true,
sourceMap: true
},
target: {
src: '<%= paths.src.js %>',
dest: '<%= paths.dest.jsMin %>'
}
}
});
grunt.registerTask('default', 'concat vs. uglify', function (concat) {
// grunt default:true
if (concat) {
// Update the uglify dest to be the result of concat
var dest = grunt.config('concat.js.dest');
grunt.config('uglify.target.src', dest);
grunt.task.run('concat');
}
// grunt default
grunt.task.run('uglify');
});
};
In src, I've put a bunch of JS files, including the uncompressed source of jQuery, copied several times, spread around into subfolders. Much more than what a normal site/app usually has.
Turns out the time it takes to concat and compress all of these files is essentially the same in both scenarios.
Except when using the sourceMap: true option on concat as well (see below).
On my computer:
grunt default : 6.2s (just uglify)
grunt default:true : 6s (concat and uglify)
It's worth noting that the resulting main.min.js is the same in both cases.
Also, uglify automatically takes care of using the proper separator when combining the files.
The only case where it does matter is when adding sourceMap: true to the concat options.
This creates a main.js.map file next to main.js, and results in:
grunt default : 6.2s (just uglify)
grunt default:true : 13s (concat and uglify)
But if the production site loads only the min version, this option is useless.
I did found a major disadvantage with using concat before uglify.
When an error occurs in one of the JS files, the sourcemap will link to the concatenated main.js file and not the original file. Whereas when uglify does the whole work, it will link to the original file.
Update:
We can add 2 more options to uglify that will link the uglify sourcemap to concat sourcemap, thus handling the "disadvantage" I mentioned above.
uglify: {
options: {
compress: true,
mangle: true,
sourceMap: true,
sourceMapIncludeSources: true,
sourceMapIn: '<%= paths.dest.js %>.map',
},
target: {
src: '<%= paths.src.js %>',
dest: '<%= paths.dest.jsMin %>'
}
}
But it seems highly unnecessary.
Conclusion
I think it's safe to conclude that we can ditch concat for JS files if we're using uglify, and use it for other purposes, when needed.
In the example you mention, which I'm quoting below, the files are first concatenated with concat and then uglified/minified by uglify:
{
concat: {
'.tmp/concat/js/app.js': [
'app/js/app.js',
'app/js/controllers/thing-controller.js',
'app/js/models/thing-model.js',
'app/js/views/thing-view.js'
]
},
uglifyjs: {
'dist/js/app.js': ['.tmp/concat/js/app.js']
}
}
The same could be achieved with:
{
uglifyjs: {
'dist/js/app.js': [
'app/js/app.js',
'app/js/controllers/thing-controller.js',
'app/js/models/thing-model.js',
'app/js/views/thing-view.js'
]
}
}
Typically, the task clean would then run after tasks that write to a temporary folder (in this example concat) and delete whatever content is in that folder. Some people also like to run clean before tasks like compass, to delete things like randomly named image sprites (which are newly generated every time the task runs). This would keep wheels turning even for the most paranoid.
This is all a matter of preference and workflow, as is with when to run jshint. Some people like to run it before the compilation, others prefer to run it on compiled files.
Complex projects with an incredible amount of JavaScript files - or with a increasingly broad number of peers & contributors, might choose to concatenate files outside uglify just to keep things more readable and maintainable. I think this was the reasoning behind Yeoman's choice of transformation flow.
uglify can be notoriously slow depending of the project's configuration, so there might be some small gain in concatenating it with concat first - but that would have to be confirmed.
concat also supports separators, which uglify doesn't as far as README.md files are concerned.
concat: {
options: {
separator: ';',
}
}

Grunt LiveReload is really slow

This is probably an affect of my inefficient setup and not a problem with grunt/livereload.
Here's my watch test in my grunfile.js:
watch: {
images: {
files: ['images/**/*.{png,jpg,gif}', 'images/*.{png,jpg,gif}'],
tasks: ['imagemin'],
options: {
spawn: false
}
},
js: {
files: ['js/*.js','js/**/*.js'],
tasks: ['jshint'],
options: {
spawn: false
}
},
svgs: {
files: ['images/*.svg','images/**/*.svg'],
task: ['svgmin'],
options: {
span: false
}
},
scss: {
files: ['sass/*.scss', 'sass/**/*.scss'],
tasks: ['sass','autoprefixer'],
sourceComments: 'normal',
options: {
nospawn: true,
livereload: true
}
}
},
This will recompile my SASS and the reload the page, but it takes 5-6 seconds to complete the CSS compilation, then it does a full page refresh, instead of just reloading the CSS file that changed.
So my questions are this:
How do I keep it from taking so long to compile the SASS and refresh the page, or am I just being to picky, and this is an inherit part of grunt?
How keep if from reloading the entire page, and just reload the CSS file that changed from my SASS compilation?
Check my other answer: Fastest way to compile SCSS (Compass) + refresh the browser?
grunt-contrib-sass uses Ruby sass which is very slow, it has nothing to do with grunt itself.
Use grunt-sass instead, it uses libsass which is lighting fast c implementation of sass.
Read this article:
http://benfrain.com/lightning-fast-sass-compiling-with-libsass-node-sass-and-grunt-sass/
The best solution is to move from grunt-contrib-sass to grunt-sass, but if you don't have much time to fix this, i think, you should move your 'autoprefixer' task from watch section to deploy section.
scss: {
files: ['sass/*.scss', 'sass/**/*.scss'],
tasks: ['sass',
sourceComments: 'normal',
options: {
nospawn: true,
livereload: true
}
}
In my project this trick help me, because 'autoprefixer' task works very slowly
Or you could use a live reloader tool, like fast-live-reload, in combination with the ruby sass compiler.
Note that they offer their own watcher that is very fast (e.g. for compass run: compass watch).
Disclaimer: I am the creator of fast-live-reload.

Refresh less css which has other imported less files without page load

I want to use watch mode in my development environment. It works fine with single less file. But I have so many less files which are imported to app.less. My app.less looks
#import "variables";
#import "mixins";
It seems I can not use watch mode in this setting. Is there any other ways?
Upd. This syntax is for old grunt versions so it should not be used.
You need to use LiveReload app for this. Or maybe another software that can reload page with LiveReload browser extension (maybe Sublime Text editor with a plugin).
Possible setup is Node.js with Grunt which has grunt-contrib-less and grunt-reload modules installed.
Your grunt.js config should look like this:
module.exports = function(grunt) {
grunt.initConfig({
// Start LiveReload server
reload: {
port: 35729,
liveReload: {}
},
// Simple css compilation
less: {
src: 'less/app.less',
dest: 'css/app.css'
},
// Reload files on change
watch: {
less: {
files: ['less/*.less'],
tasks: 'less'
},
reload: {
files: ['*.html',
'css/app.css',
'js/*.js'],
tasks: 'reload'
}
}
});
// Third party modules
grunt.loadNpmTasks('grunt-reload');
grunt.loadNpmTasks('grunt-contrib-less');
// Register default task
grunt.registerTask('default', 'less');
};
Then you need to run
$ grunt watch:less
and
$ grunt watch:reload
in two separate terminal windows.
I'm totally agree with this comment
Refresh less css which has other imported less files without page load .
Thanks, thevasya.
But there's no need to start several terminals.
watch: {
less: {
files: ['less/*.less'],
tasks: 'less'
},
reload: {
files: ['*.html',
'css/app.css',
'js/*.js'],
tasks: 'reload'
}
}
after that you can start watching by
$ grunt watch
and that's it. If you change any less file, it will start only less task.
P.S.: This answer was updated for proper work with grunt 0.4.

Resources