Gulp - TypeError: Cannot assign to read only property 'cwd' of bower / bootstrap.css - css

I'm just getting to grips with Gulp.js and this is the only error I can't seem to get around.
I have install bootstrap via bower, and I'm trying to minify the bootstrap css.
Here's my gulp task;
gulp.task('minifycss', function() {
gulp.src('www/css/animate.css', 'www/bower_components/bootstrap/dist/css/bootstrap.css')
.pipe(minifycss({compatibility: 'ie8'}))
.pipe(gulp.dest('www-deploy/css/'));
});
However when I run my main gulp task. It states that the file is "read only"
Karls-MacBook-Pro:cmp-2015 karltaylor$ gulp
[13:48:50] Using gulpfile ~/Documents/web/cmp-2015/gulpfile.js
[13:48:50] Starting 'sassMin'...
[13:48:50] Finished 'sassMin' after 12 ms
[13:48:50] Starting 'minifycss'...
[13:48:50] 'minifycss' errored after 508 μs
[13:48:50] TypeError: Cannot assign to read only property 'cwd' of www/bower_components/bootstrap/dist/css/bootstrap.css
at Object.gs.createStream (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-stream/index.js:19:46)
at Object.gs.create (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-stream/index.js:68:42)
at Gulp.src (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/vinyl-fs/lib/src/index.js:33:23)
at Gulp.<anonymous> (/Users/karltaylor/Documents/web/cmp-2015/gulpfile.js:35:7)
at module.exports (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7)
at Gulp.Orchestrator._runTask (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/index.js:273:3)
at Gulp.Orchestrator._runStep (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/index.js:214:10)
at /Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/index.js:279:18
at finish (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:21:8)
at module.exports (/Users/karltaylor/Documents/web/cmp-2015/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:60:3)
Things I've tried:
Reinstalling bootstrap
Moving the actual bootstrap.css file to my css file, however it does exactly the same thing.
EDIT: SOLVED = To use multiple sources you have to put them in an array.
Source: https://github.com/gulpjs/gulp/blob/master/docs/recipes/using-multiple-sources-in-one-task.md

Like #topleft mentioned, it was error in the syntax from using multiple files in my gulp.src. To use multiple sources you need to put them in an array.
Example:
var gulp = require('gulp');
var concat = require('gulp-concat');
gulp.task('default', function() {
return gulp.src(['foo/*', 'bar/*'])
.pipe(concat('result.txt'))
.pipe(gulp.dest('build'));
});

I had this issue when I tried to output 2 css files and I didn't use array [].
Instead of:
gulp.src('www/css/animate.css', 'www/bower_components/bootstrap/dist/css/bootstrap.css')
.pipe(minifycss({compatibility: 'ie8'}))
.pipe(gulp.dest('www-deploy/css/'));
});
Use this:
gulp.src(['www/css/animate.css', 'www/bower_components/bootstrap/dist/css/bootstrap.css'])
.pipe(minifycss({compatibility: 'ie8'}))
.pipe(gulp.dest('www-deploy/css/'));
});
Explanation:
gulp.src(['./file1.scss', './file2.scss']);

alternatively you could also try with
return gulp.src('www/**/*.css')
it should add every .css in your directories if thats the wanted effect

Related

How come I am getting this error when running gulp sass 'gulp-sass 5 does not have a default Sass compiler; please set one yourself'

How come I am getting this error when running gulp sass 'gulp-sass 5 does not have a default Sass compiler; please set one yourself'
I am trying to compile my sass for a shopify theme. But I get this error after running gulp sass
Error
Both the `sass` and `node-sass` packages are permitted. I added the line of code they recommended but that still did work.
For example, in your gulpfile:
var sass = require('gulp-sass')(require('sass'));
[01:12:12] The following tasks did not complete: sass
[01:12:12] Did you forget to signal async completion?
My code
const gulp = require('gulp')
const themekit = require('#shopify/themekit')
const sass = require('gulp-sass')
gulp.task('sass', function() {
return gulp.src('scss/global.scss')
.pipe(sass())
.pipe(gulp.dest('assets'))
});
I am using "gulp-sass": "^5.0.0"
Thank you in advance

Gulp webp function not respecting watch command

Ok, so I am using the typical image minification process. I have functions for jpg, pngs and I have a separate function to convert those to webp.
I have the following gulpfile (only the relevant parts are here):
function clean(done) {
rimraf(folder.public_img, done);
}
function images() {
return gulp.src([folder.preimages+'/**/*.{gif,png,jpg,svg}'])
.pipe(cache(imagemin([
imageminPngquant({
speed: 1,
quality: [0.95, 1]
}),
imageminZopfli({
more: true
}),
imageminMozjpeg({
quality: 65
}),
])))
.pipe(gulp.dest(folder.public_img));
}
gulp.task('webp', () =>
gulp.src([folder.preimages+'/**/*.{gif,png,jpg}'])
.pipe(webp({
quality: 65,
method: 6
}))
.pipe(gulp.dest(folder.public_img))
);
function serve() {
gulp.watch(folder.preimages+"/**/*.{gif,png,jpg,svg}", images);
gulp.watch(folder.preimages+"/**/*.{gif,png,jpg}", webp);
}
gulp.task('clean', clean);
gulp.task('images', images);
gulp.task('serve', gulp.series('clean', 'images', 'webp', serve));
gulp.task('default', gulp.series('clean', 'images', 'webp', serve));
So, basically when I run gulp the first time, all the processes run fine and the webp images are generated. BUT, if I add a new image, the images() function runs, but for some reason the webp() function doesn't execute, it's as if it doesn't see changes, and I have it configured the same way as images.
I tried two alternatives:
I added the webp process directly inside the images() function, but that way my JPG and PNG files were directly converted to webp and I didn't have fallback images.
I tried to create the webp function with the same format as the others function webp() { ... }, but when I tried to run gulp it showed this error:
The following tasks did not complete: default,
Did you forget to signal async completion?
So I found that I could use the format above gulp.task('webp', () =>... and that works, but doesn't respect the watch function. I think it could be related to the function to name assignation in the end of the file, but I am not that familiar with the syntax.
What should I change so that it watches correctly?
I was able to recreate your code and get it to work as follows:
In creating your gulp tasks, something goofy seems to be happening because you've created a series of tasks to run with your gulp.task('serve'). Instead, you can write out your tasks like this:
gulp.task(clean);
gulp.task(images);
gulp.task(serve);
gulp.task('default', gulp.series(clean, images, webp, serve));
You may want to call your webp function something else - I was getting a conflict because of also importing gulp-webp as const = webp. You also don't need to put quotation marks around the name of the function in the task and then also reference it in the task again. So gulp.task(clean) works just fine. You don't need gulp.task('clean', clean).
You can probably also write your default task as follows:
gulp.task('default', gulp.series(clean, serve);
This had the same effect for me as also including the images and webp tasks in the series. This setup worked for me. Running gulp, it first ran the clean function to remove the public_img folder, then ran images followed by webp. It worked up the initial run as well as when I added a new image to the preimages folder.
Update
Here's the complete gulpfile I got to work:
const gulp = require('gulp');
const imagemin = require('gulp-imagemin');
const rimraf = require('rimraf');
const webp = require('gulp-webp');
const folder = {
preimages: 'src/images',
public_img: 'src/public_img',
};
function clean(done) {
rimraf(folder.public_img, done);
}
function images() {
return gulp
.src([folder.preimages + '/**/*.{gif,png,jpg,svg}'])
.pipe(imagemin())
.pipe(gulp.dest(folder.public_img));
}
function webpTask() {
return gulp
.src([folder.preimages + '/**/*.{gif,png,jpg}'])
.pipe(webp())
.pipe(gulp.dest(folder.public_img));
}
function serve() {
gulp.watch(folder.preimages + '/**/*.{gif,png,jpg,svg}', images);
gulp.watch(folder.preimages + '/**/*.{gif,png,jpg}', webpTask);
}
gulp.task('clean', clean);
gulp.task('images', images);
gulp.task('default', gulp.series('clean', 'images', webpTask, serve));
Notes: I removed the gulp serve task. I couldn't get that to work under any configuration. I think you are running into a conflict by naming both the task and the function serve, although I'm not 100% positive. I changed the webp task name to webpTask, as I was getting a conflict by naming both the webp import and the webp function webp. I didn't include any of the webp() or imagemin() configuration options, but that shouldn't matter.
You should also be able to remove the calls for both the images and webpTask functions in the gulp default task, as running the serve function should trigger both of those.
This setup worked for me both when adding new images to my preimages folder while the gulp default task was running as well as when restarting the gulp default task.
FYI: I'm using gulp version 4.0.1., but I don't think that should make a difference for this.

Gulp Task: CleanCSS and Paths

I've created a task with Gulp that is supposed to:
Join multiple CSS files;
Minify + remove unnecessary CSS;
Fix paths for url() directives and others;
Generate source maps;
My current code for this is:
var gulp = require("gulp"),
concat = require("gulp-concat"),
cleanCSS = require("gulp-clean-css"),
sourcemaps = require("gulp-sourcemaps");
var styleList = [
"Resources/Include/ionicons/css/ionicons.css",
"Resources/base.css",
"Resources/extra.css",
];
gulp.task("deploy-css", function() {
gulp.src(styleList)
.pipe(sourcemaps.init())
.pipe(concat("style.min.css"))
.pipe(cleanCSS({
debug: true,
compatibility: "ie8",
keepSpecialComments : 0,
target: "Resources/",
relativeTo: "Resources/"
})
)
.pipe(sourcemaps.write())
.pipe(gulp.dest("Resources/"))
});
url() path example, taken from file Resources/Include/ionicons/css/ionicons.css:
#font-face { font-family: "Ionicons"; src: url("../fonts/ionicons.eot?v=2.0.0");
This is my current file structure:
./Resources/style.min.css // -> Final processed file
./Resources/base.css
./Resources/extras.css
./Resources/Include/ // -> Original CSS files with URL (installed via Bower)
Test folder: https://dl.dropboxusercontent.com/u/2333896/gulp-path-test.zip (install and then run with gulp deploy-css).
Almost everything works as expected, except for when CSS files include references to images or fonts using the url() option. After running the task (and style.min.css created) those references are broken - no change was made to the paths found on the original CSS files.
Isn't cleanCSS supposed to check where the referenced files are and fix the paths automatically? Aren't the options target and relativeTo used to control that?
How can I fix this? Thank you.
I managed to fix the issue, my main problems were a misplaced concat operation breaking gulp-clean-css rebase feature and wrong target and relativeTo options. Apparently I didn't think much about the previous workflow.
var gulp = require("gulp"),
concat = require("gulp-concat"),
cleanCSS = require("gulp-clean-css"),
sourcemaps = require("gulp-sourcemaps");
var styleList = [
"Resources/Include/ionicons/css/ionicons.css",
"Resources/base.css",
"Resources/extra.css",
"Resources/Include/teste/base.css"
];
gulp.task("deploy-css", function() {
gulp.src(styleList)
.pipe(sourcemaps.init())
.pipe(cleanCSS({
compatibility: "ie8",
keepSpecialComments : 0,
target: "Resources",
relativeTo: ""
})
)
.pipe(concat("style.min.css", {newLine: ""}))
.pipe(sourcemaps.write())
.pipe(gulp.dest("Resources"))
});
This new workflow works as:
Optimize all individual CSS files - including rebasing urls;
Contact individual optimized files into the final file - (note newLine: "" avoids line breaks in the file);
Write the file.

How to get gulp to watch my sass file changes and create one css file?

I am working on an application that is developed using ASP.NET MVC 5 framework. I am using Visual Studio 2013 to write my application.
I need to utilize gulp to automate the process of compiling my sass file and publishing them into a bundle.css file.
To do that, here is what I have done
Installed NodeJs on my machine
Installed gulp globally using npm install -g gulp
Created a file called gulpfile.js in the root project of the project
created the package.json file using npm init command
Added gulp to my development dependencies by executing the following command from the root of my project npm install gulp --save-dev
Added the code below to my gulpfile.js
From the command console I fired gulp command which displayed the following info
Using gulpfile ...gulpfile.js
Starting 'watch'...
Finished 'watch' after 21 ms
Starting 'default'...
Finished 'default' after 31 µs
But when I write code into my ~/Assets/Sass/**/*.sass nothing gets saved into ~/Public/Css/bundle.css as expected
Here is what gulpfile.js looks like
const gulp = require('gulp'),
sass = require('gulp-ruby-sass');
// Default task which will be be fired when the runner is started
gulp.task('default', ['watch']);
// listener task
gulp.task('watch', function(){
//Watch any change in the sass directory and trigger the "compileSass" for every save
gulp.watch('~/Assets/Sass/**/*.sass', ['compileSass']);
});
// Task to compile the sass files
gulp.task('compileSass', () =>
sass('~/Assets/Sass/**/*.sass')
.on('error', sass.logError)
.pipe(gulp.dest('~/Public/Css/bundle.css'))
);
What am I missing here? How can I get the watched to watch and fire the tasks after each save?
Updated
I switch from using gulp-ruby-sass plugin into using gulp-scss. Now, I got the task to run every time I save a scss file but for some reason it wont update the destination file.
Here is how my gulpfile.js file looks like
const gulp = require('gulp'),
scss = require('gulp-scss');
// Default task which will be be fired when the runner is started
gulp.task('default', ['watch']);
// listener task
gulp.task('watch', function(){
//Watch any change in the "Sass" directory and trigger the "compileScss" for every save
gulp.watch('./Assets/Scss/**/*.scss', ['compileScss']);
});
// Task to compile the "Scss" files
gulp.task('compileScss', function () {
gulp.src('./Assets/Scss/**/*.scss')
.pipe(scss({ "bundleExec": true }))
.pipe(gulp.dest('./Public/Css/bundle.css'));
});
You may be missing the require for gulp-watch:
var watch = require('gulp-watch');
From gulp-watch:
watch(glob, [options, callback]) Creates a watcher that will spy on
files that are matched by glob which can be a glob string or array of
glob strings.
Returns a pass through stream that will emit vinyl files (with
additional event property) that corresponds to event on file-system.
You have to provide a function. Meaning that a task name is not sufficient.
Try using gulp-batch to run some tasks withing your watch:
npm install gulp-batch --save-dev
Your watch task:
// listener task
gulp.task('watch', function(){
var watch = require('gulp-watch');
var batch = require('gulp-batch');
//Watch any change in the sass directory and trigger the "compileSass" for every save
watch('~/Assets/Sass/**/*.sass', batch(function (events, done) {
// run your compileSass task
gulp.start('compileSass', done);
}));
});
Edit:
You can run tasks from Visual Studio 2015 in the "Task Runner Explorer" window.
However, if you have a prompt running gulp-watch it should have the same effect and run your compile task when it detect changes to the files that you are watching regardless of where they were edited.
Basic things to check are folder location existence, file names, and read/write permissions.
Example gulpfile.js that uses gulp.watch and gulp-load-plugins in a Zurb Foundation 6 project using (foundation-cli).
Note that .pipe(gulp.dest('../your/path/css'));
does not include a ~ or specify a file name or extension. It only specifies a path. The file placed in that path is given the default name of style.css since the source files name is style.scss. See line gulp.src('scss/style.scss').
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
// Multiple locations of SCSS to combine
var sassPaths = [
'bower_components/foundation-sites/scss',
'bower_components/motion-ui/src'
];
gulp.task('sass', function() {
return gulp.src('scss/style.scss') // SCSS Source file
.pipe($.sass({
includePaths: sassPaths,
outputStyle: 'compressed' // if css compressed **file size**
})
.on('error', $.sass.logError))
.pipe($.autoprefixer({
browsers: ['last 2 versions', 'ie >= 9']
}))
.pipe(gulp.dest('../your/path/css')); // OUTPUT Destination
});
gulp.task('default', ['sass'], function() {
gulp.watch(['scss/**/*.scss'], ['sass']); // FILES to Watch
});

How can I skip a grunt task if a directory is empty

I'm using grunt-contrib's concat and uglify modules to process some javascript. Currently if src/js/ is empty, they will still create an (empty) concat'd file, along with the minified version and a source map.
I want to task to detect if the src/js/ folder is empty before proceeding, and if it is, then the task should skip (not fail). Any ideas how to do this?
The solution may not be the prettiest, but could give you an idea. You'll need to run something like npm install --save-dev glob first. This is based on part of the Milkshake project you mentioned.
grunt.registerTask('build_js', function(){
// get first task's `src` config property and see
// if any file matches the glob pattern
if (grunt.config('concat').js.src.some(function(src){
return require('glob').sync(src).length;
})) {
// if so, run the task chain
grunt.task.run([
'trimtrailingspaces:js'
, 'concat:js'
, 'uglify:yomama'
]);
}
});
A gist for comparison: https://gist.github.com/kosmotaur/61bff2bc807b28a9fcfa
With this plugin:
https://www.npmjs.org/package/grunt-file-exists
You can check file existence. (I didn't try, but the source looks like supporting grunt expands. (*, ** ...)
For example like this::
grunt.initConfig({
fileExists: {
scripts: ['a.js', 'b.js']
},
});
grunt.registerTask('conditionaltask', [
'fileExists',
'maintask',
]);
But maybe if the file doesn't exist it will fail with error instead of simple skip.
(I didn't test it.)
If this is a problem you can modify a bit the source of this plugin to run the related task if the file exists:
The config:
grunt.initConfig({
fileExists: {
scripts: ['a.js', 'b.js'],
options: {tasks: ['maintask']}
},
});
grunt.registerTask('conditionaltask', [
'fileExists',
]);
And you should add this:
grunt.task.run(options.tasks);
In this file:
https://github.com/alexeiskachykhin/grunt-file-exists/blob/master/tasks/fileExists.js
after this line:
grunt.log.ok();
Maybe this is just a more up-to-date answer as the others are more than a year old, but you don't need a plugin for this; you can use grunt.file.expand to test if files matching a certain globbing pattern exist.
Update of #Kosmotaur's answer (path is just hard-code here though for simplicity):
grunt.registerTask('build_js', function(){
// if any file matches the glob pattern
if (grunt.file.expand("subdir/**/*.js").length) { /** new bit here **/
// if so, run the task chain
grunt.task.run([
'trimtrailingspaces:js'
, 'concat:js'
, 'uglify:yomama'
]);
}
});

Resources