I am trying to convert my style.scss (which has some other files link to it such as _variable.scss, _mixins.scss) file to css via grunt.js and npm. however I got this error:
Error: File to import not found or unreadable: compass.
on line 5 of sass/style.scss
1: // typorgraphy
2: #import "base/typography";
3:
4: // compass
5: #import "compass";
6:
7: // import files
8: #import "base/import";
9:
10: // mixins
Here's my gruntfile.js:
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
compass: {
dist: {
options: {
sassDir: 'sass',
cssDir: 'css',
environment: 'production'
}
},
dev: {
options: {
sassDir: 'sass',
cssDir: 'css'
}
}
},
watch: {
sass:{
files: ['sass/*.scss'],
tasks: ['sass', 'cssmin']
}
},
sass: {
dist: {
files: {
'css/style.css' : 'sass/style.scss'
}
}
},
concat: {
options: {
separator: ';',
stripBanners: true,
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
dist: {
src: ['js/*.js'],
dest: 'js/main.min.js'
}
},
uglify:{
options: {
manage: false,
preserveComments: 'all' //preserve all comments on JS files
},
my_target:{
files: {
'js/main.min.js' : ['js/*.js']
}
}
},
cssmin:{
my_target:{
files: [{
expand: true,
cwd: 'css/',
src: ['*.css', '!*.min.css'],
dest: 'css/',
ext: '.min.css'
}]
}
}
});
// Load the plugin that provides the "compass" task.
grunt.loadNpmTasks('grunt-contrib-compass');
// Load the plugin that provides the "watch" task.
grunt.loadNpmTasks('grunt-contrib-watch');
// Load the plugin that provides the "sass" task.
grunt.loadNpmTasks('grunt-contrib-sass');
// Load the plugin that provides the "uglify" task.
grunt.loadNpmTasks('grunt-contrib-uglify');
// Load the plugin that provides the "concat" task.
grunt.loadNpmTasks('grunt-contrib-concat');
// Load the plugin that provides the "cssmin" task.
grunt.loadNpmTasks('grunt-contrib-cssmin');
// Default task(s).
grunt.registerTask('default', ['uglify','cssmin']);
};
When I run grunt sass, it gave me those error. Compass was already installed and I type "grunt compass" to make sure its running.
Any idea?
use grunt-contrib-sass instead of grunt-sass.
grunt-contrib-sass ruby compiler that support compass.
This task requires you to have Ruby and Sass installed. If you're on
OS X or Linux you probably already have Ruby installed; test with ruby
-v in your terminal. When you've confirmed you have Ruby installed, run gem install sass to install Sass.
Also make sure to compass option to true. By default, it's set to false.
Read this for more information : compass option
Here is an example :
sass: {
dist: {
options: {
compass: true,
},
files: {
'css/style.css' : 'sass/style.scss'
}
}
},
grunt-sass uses libsass which is a Sass compiler in C++ that doesn't support compass.
This task uses libsass which is a Sass compiler in C++. In contrast to
the original Ruby compiler, this one is much faster, but is missing
some features, though improving quickly. It also doesn't support
Compass. Check out grunt-contrib-sass if you prefer something more
stable, but slower.
Related
edit for clarity
old question: grunt watch task leading zeros in minified css for some styles truncated
new diagnosis: There are several people that push to the same repository and I have observed a different behavior to minified files with the same setup of grunt watch.
end edit
In my repo I have multiple stylesheets. I use grunt to watch for scss changes and only modify the correlating CSS file. I've had a problem lately where grunt will see a modified file in older, non modified CSS files.
Here's the problem:
I pull from master.
I run grunt in the command line.
I make no changes to a scss file but save the file anyway.
I stop grunt and git status.
Git sees four modifications in the minified CSS files.
I save the changes commit and push to a branch.
When I git diff I can see that grunt has removed some of the leading zeros in front of decimal points for opacity.
Here is a screenshot of the diff.
If I commit and push these modifications to my branch I can go about making other changes and only modifying the correlating CSS minified files. But after merging these changes to master and then pulling from master again, when I run grunt locally I will see these same four "ghost" modifications with the same zero's being removed in the minified file. I've tried changing my version of node, sass, and grunt but all different versions have the same result!
Has anyone else experienced this or know how to stop grunt from making these changes and bloating the repo with excessive recompiling and commits?
Version of node: 5.1.0
Version of sass: 3.4.19
Version of grunt 0.4.5
Version of grunt cli: 0.1.13
I just recently updated my version of node from 0.10.33 to 5.1.0
And here is my gruntfile:
module.exports = function(grunt) {
require('time-grunt')(grunt);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
// set notifications that run after other tasks
notify: {
uglify: {
options: {
title: 'Task Complete',
message: 'Uglify finished running',
}
},
sass: {
options: {
title: 'Task Complete',
message: 'Sass finished running',
}
}
},
// concat and minify js task
uglify: {
site: {
files: {
'assets/four/js/site.js': [
'assets/four/js/src/plugins/*.js',
'assets/four/js/src/global.js',
'assets/four/js/src/data/*.js',
'assets/four/js/src/forms/*.js',
'assets/four/js/src/modules/*.js',
'assets/four/js/src/pages/*.js'
],
'assets/four/js/analytics.min.js': ['assets/four/js/src/analytics.js'],
'assets/four/js/social.js': ['assets/four/js/src/social.js']
}
},
pages: {
files: grunt.file.expandMapping(['assets/js/pages/**/*.js', '!assets/js/pages/**/*.min.js'], 'assets/js/pages', {
rename: function(destBase, destPath) {
return destPath.replace('pageassets/js/pages', destBase).replace('.js', '.min.js');
}
})
}
},
//concat and minify scss -> css task
sass: {
options: {
sourceMap: true,
outputStyle: 'compressed'
},
dist: {
files: {
'assets/css/style.css': 'assets/css/scss/style.scss',
'assets/css/old.css': 'assets/css/scss/old.scss',
'assets/css/pages/brand.css': 'assets/css/pages/scss/brand.scss',
'assets/css/pages/custom-design-showcase.css': 'assets/css/pages/scss/custom-design-showcase.scss',
'assets/css/landings.css': 'assets/css/scss/landings.scss',
// 4.0
'assets/four/css/site.css': 'assets/four/css/scss/site.scss',
'assets/four/css/ie.css': 'assets/four/css/scss/ie.scss',
'assets/four/css/interim.css': 'assets/four/css/scss/interim.scss'
}
}
},
// compress images losslessly task
imagemin: {
dynamic: {
options: {
optimizationLevel: 3,
progressive: true,
svgoPlugins: [{removeUselessStrokeAndFill: false}]
},
files: [{
expand: true,
cwd: 'assets/four/img',
src: ['**/*.{png,jpg,gif,svg}'],
dest: 'assets/four/img'
}]
}
},
// watch for changes in repo and run tasks automatically
watch: {
options: {
// Google Extension: https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei?hl=en
livereload: true
},
html: {
files: ['templates/default_site/**/*.html']
},
js: {
files: [
'assets/js/*.js',
'assets/four/js/src/global.js',
'assets/four/js/src/plugins/*.js',
'assets/four/js/src/data/*.js',
'assets/four/js/src/forms/*.js',
'assets/four/js/src/pages/*.js',
'assets/four/js/src/modules/*.js',
//dont
'!assets/four/js/*.min.js',
'!assets/four/js/*.js',
'!assets/js/*.min.js',
'assets/js/pages/**/*.js',
'!assets/js/pages/**/*.min.js',
'assets/js/geo/**/*.js',
'!assets/js/geo/**/*.min.js'
],
tasks: ['uglify', 'notify:uglify']
},
sass: {
options: {
livereload: true
},
files: ['assets/css/scss/*.scss', 'assets/four/css/scss/*.scss', 'assets/four/css/scss/pages/*.scss', 'assets/four/css/scss/modules/*.scss', 'assets/css/scss/modules/*.scss', 'assets/css/pages/scss/*.scss'],
tasks: ['sass:dist', 'notify:sass']
},
css: {
files: ['assets/css/*.css', 'assets/four/css/*.css', 'assets/css/pages/*.css']
}
},
});
//load plugins
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-notify');
// to run watch task, enter 'grunt' command line in project DIR
grunt.registerTask('default', ['watch']);
};
I am new to Grunt and all its plugins, but I want to learn and setup some awesome front-end tools. With that said, I have been following the Grunt docs and some's similar issue with Grunt and Babel via Github, but I seem to keep getting the following traceback:
Running "babel:dist" (babel) task
Warning: Unable to write "dist" file (Error code: EISDIR). Use --force to continue.
Aborted due to warnings.
Any clearer explanation to this newbie would be HIGHLY appreciated. I'm new to programming in JS and setting up DevOps, so some helpful tips and best practices are encouraged.
Setup:
js_practice/ (Root Project)
|----package.json
All the distributions and packages
|---node_modules/
Server-Side (Node) support
|---es6/
| ------ test.js
|---dist/
Client (browser) support
|----public/
|---es6/ (this is within the public folder)
| ----- test2.js
|---dist/ (this is within the public folder)
Here is my current code:
Grunt file.js
module.exports = function(grunt) {
// All of your Grunt code must be specified inside this function!
// Setup configuration...
// Load tasks...
// Define tasks...
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
babel: {
options: {
sourceMap: true,
presets: ['babel-preset-es2015']
},
dist: {
files: [
// Node source
{
src: ['es6/**/*.js'],
dest: 'dist'},
// Browser source
{
src: ['public/es6/**/*.js'],
dest: 'public/dist'},
],
},
},
browserify: {
dist: {
options: {
transform: [["babelify", { "stage": 0 }]]
},
files: {
"build/bundle.js": "src/main.js"
}
}
},
jshint: {
scripts: {
src: ['scripts/**.js', 'lib/**.js']
},
tests: { // We can have more than one jshint task, this ones called `jshint:tests`
src: 'tests/**.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build: {
src: 'src/<%= pkg.name %>.js',
dest: 'build/<%= pkg.name %>.min.js'
},
scripts: {
expand: true,
cwd: 'scripts/',
src: '**.js',
dest: 'build/',
ext: '.min.js'
}
},
watch: {
scripts: {
files: ['**/*.js'],
tasks: ['jshint'],
},
styles: {
files: 'styles/**.less',
task: 'less:styles'
}
}
});
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-less');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-babel');
grunt.registerTask('default', ['babel','browserify','jshint']);
grunt.registerTask('build', ['jshint', 'uglify']);
};
Just expanding on what I said in the comments
Any clearer explanation to this newbie would be HIGHLY appreciated.
Nodejs is trying to write a file called dist, but produces an error because a directory with this name exists.
The cause of this is found in the babel task.
files: [{
src: ['es6/**/*.js'],
dest: 'dist'
},
// Browser source
{
src: ['public/es6/**/*.js'],
dest: 'public/dist'
}]
You have to tell Babel to take each file in es6/, transform them and place the new files in the dist/ folder. As it stand now, the transformer tries to create a file called dist. Rewriting it to
files: [{
expand: true,
cwd: 'es6/'
src: ['**/*.js'],
dest: 'dist/'
},
// Browser source
{
expand: true,
cwd: 'public/es6/'
src: ['**/*.js'],
dest: 'public/dist/'
}]
should yield a better result, but play around with it. Like I mentioned, I haven't used Grunt in a while. Take a look at the documentation on building the files object
And like I said in the comments, use jshint or other such tools (eslint is all the hype...) to keep your own code neat. Don't waste time by running a jshint task on lib files that you probably don't want to fix yourself anyway. And always run jshint on the source files, not files that are transformed by babel or browserify. It's just a tool to help you write better code, not some generator.
I have defined a simple Gruntfile.js per the official instructions and yet I am getting a warning when I run the grunt watch ('$ grunt watch') or grunt default task ('$ grunt ').
The error is:
(node) warning: Recursive process.nextTick detected. This will break
in the next version of node. Please use setImmediate for recursive
deferral.
I have read the related StackOverflow question and answer here: grunt throw "Recursive process.nextTick detected", but that didn't resolve my issue.
My Gruntfile.js is:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
separator: ';'
},
dist: {
src: ['client/app/**/*.js'],
dest: 'client/dist/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
},
dist: {
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
}
},
jshint: {
files: ['client/app/**/*.js', 'server/**/*.js'],
options: {
// options here to override JSHint defaults
globals: {
jQuery: true,
console: true,
module: true,
document: true
}
}
},
watch: {
files: ['<% jshint.files %>'],
tasks: ['jshint']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['watch']);
grunt.registerTask('test', ['jshint']);
grunt.registerTask('build-dev', ['jshint', 'concat']);
grunt.registerTask('build', ['jshint', 'concat', 'uglify']);
};
OK. I figured it out. And dagnabbit, the bug was in the same Gruntfile that I copied hither from thither.
Node did NOT like the watch instructions to reference the jshint.files property and then call the jshint task. So instead, I put the files in explicitly as follows. After changing the following lines (with context):
watch: {
files: ['client/app/**/*.js', 'server/**/*.js'],
tasks: ['jshint']
}
the grunt watch and default tasks (the default task was performing the watch task), it worked without any warnings!
So I know this question has been answered, but I'll share my insights into this error as it proved to be a colossal waste of time.
Here's my original Gruntfile:
module.exports = function (grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
watch: {
dev: {
files: ['**/*.js', 'public/stylesheets/**/*.scss'],
tasks: ['express:dev'],
options: {
spawn: false
}
}
},
express: {
dev: {
options: {
script: 'server.js',
node_env: 'development'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express-server');
grunt.registerTask('default', ['express:dev', 'watch']);
};
In a similar vain to Chad, I resolved the issue by removing js files from my watch task, which restarts Express. The below configuration of the aforementioned task works fine for me:
watch: {
dev: {
files: ['public/stylesheets/**/*.scss'],
tasks: ['express:dev'],
options: {
spawn: false
}
}
},
I have recently discovered grunt as it is used within an opensource project I have started to work on. Having not worked with grunt before I am struggling to see how it works, or in my case doesn't.
The grunt file is supplied by the project and I assume it works for everyone else. I have installed grunt and the necessary grunt modules have all installed in the "Node_modules" directory.
When running the grunt file the first process performs a number of concatenations and this seems to work fine. The concatenated files are created.
All of the other steps do not seem to execute. The files they are intended to create are not created. There is no error message displayed on the console when grunt is executed.
I'm stumped - anyone have any clues what might be the problem.
The grunt file is :
/*global module:false*/
module.exports = function(grunt) {
// Project configuration...
grunt.initConfig({
manifest: grunt.file.readJSON('chrome/manifest.json'),
concat: {
dist: {
src: ['chrome/js/requester/**/*.js'],
dest: 'chrome/js/requester.js'
},
requester_html: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/footer.html'
],
dest: 'chrome/requester.html'
},
requester_tester: {
src: [
'chrome/html/requester/header.html',
'chrome/html/requester/sidebar.html',
'chrome/html/requester/main.html',
'chrome/html/requester/modals/*.html',
'chrome/html/requester/loggers/*.html',
'chrome/html/requester/footer.html',
'chrome/html/requester/tester.html'
],
dest: 'chrome/tester.html'
}
},
mindirect: {
dist: {
src: ['chrome/js/requester.js'],
dest: 'chrome/js/requester.min.js'
}
},
watch: {
requester_templates: {
files: ['chrome/html/requester/templates/*'],
tasks: ['handlebars'],
options: {
livereload: true
}
},
requester_js: {
files: ['chrome/js/requester/**/*.js'],
tasks: ['concat:dist'],
options: {
livereload: true
}
},
requester_html: {
files: ['chrome/html/requester/*', 'chrome/html/requester/modals/*', 'chrome/html/requester/loggers/*'],
tasks: ['concat:requester_html', 'concat:requester_tester'],
options: {
livereload: true
}
},
requester_css: {
files: ['chrome/css/**/*.scss'],
tasks: ['sass'],
options: {
livereload: true
}
}
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true
}
},
handlebars: {
compile: {
options: {
partialsUseNamespace: true,
namespace: 'Handlebars.templates',
processPartialName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
},
processName: function(filePath) {
var pieces = filePath.split("/");
var name = pieces[pieces.length - 1].split(".")[0];
return name;
}
},
files: {
"chrome/html/requester/templates.js": "chrome/html/requester/templates/*"
}
}
},
sass: {
dist: {
files: {
'chrome/css/requester/styles.css': 'chrome/css/requester/styles.scss'
}
}
},
compress: {
main: {
options: {
archive: 'releases/v<%= manifest.version %>.zip'
},
files: [
{src: ['chrome/**', '!chrome/tests/**', '!chrome/manifest_key.json', '!chrome/tester.html'], dest: '/'}, // includes files in path and its subdirs
]
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-handlebars');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-mindirect');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-compress');
// Default task.
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
};
The output from the console is as follows :
Running "jshint:globals" (jshint) task
>> 0 files lint free.
Running "concat:dist" (concat) task
File "chrome/js/requester.js" created.
Running "concat:requester_html" (concat) task
File "chrome/requester.html" created.
Running "concat:requester_tester" (concat) task
File "chrome/tester.html" created.
Done, without errors.
Given that the tasks are defined like this:
grunt.registerTask('default', ['jshint', 'concat']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
the output you show is what you'd expect if you are running grunt without a task name. It runs the jshint and concat tasks.
If you want to run the tasks associated with package, then you have to run grunt package to run those tasks.
It looks like I did not understand "tasks" within grunt.
Instead of executing "grunt" which runs the "default" tasks, I had to execute "grunt package" which runs the tasks that I was interested in.
As Louis said, you have to specify the right task to run.
But you can also create or modify the tasks you have in order to make it simpler. In your example you may include package in the default task. Because concat task is already executed inside package, you may just replace it in the default task:
grunt.registerTask('default', ['jshint', 'package']);
grunt.registerTask('package', ['concat', 'handlebars', 'sass', 'compress']);
and, in order to build your site, just type
grunt
both jshint and package tasks will be executed
I would really love to be able to have a development grunt file and using the same file an production version of the script.
I have tried the suggestion on SO but my script will just fail when trying to call a dev/prod argument. I believe that the answer is for an older version of grunt, or maybe the plugins I am using.
module.exports = function (grunt) {
// load all grunt tasks
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
compass: {
dev: {
options: {
config: 'config.rb',
force: true,
livereload: true
}
}
},
uglify: {
build: {
src: ['docroot/js/*.js', 'docroot/components/**/*.js'],
dest: 'docroot/dis/main.min.js'
}
},
watch: {
options: {
dateFormat: function(time) {
grunt.log.writeln('The watch finished in ' + time + 'ms at' + (new Date()).toString());
grunt.log.writeln('Waiting for more changes...');
},
livereload: true
},
sass: {
files: ['docroot/sass/*.scss'],
tasks: ['compass:dev']
},
/* watch and see if our javascript files change, or new packages are installed */
js: {
files: '<%= uglify.build.src %>',
tasks: ['uglify']
},
/* watch our files for change, reload */
livereload: {
files: ['*.html', 'docroot/css/*.css', 'docroot/img/*', 'docroot/js/{main.min.js, plugins.min.js}'],
options: {
livereload: true
}
}
}
});
grunt.registerTask('default', 'watch');
};
Really, so long as I can get two version running by calling them with, for example:
grunt //local
grunt prod //live
then I can play around with the scripts and what to load.
You can also just register a task that calls an array of tasks
grunt.registerTask('prod', ['tasks1','task2']);
before your default task, that would be
$ grunt prod