Here's my gulp file. It should compile scss and upload file after change. It uploads, but not always. What am I doing wrong?
var gulp = require('gulp'),
watch = require('gulp-watch'),
gutil = require( 'gulp-util' ),
sass = require('gulp-sass'),
ftp = require( 'vinyl-ftp' );
gulp.task( 'deploy', function () {
var conn = ftp.create( {
host: 'host',
user: 'user#host',
password: 'pass',
parallel: 10,
log: gutil.log
} );
var globs = [
'src/**',
'css/**',
'build/**',
'js/**',
'fonts/**',
'index.html'
];
// using base = '.' will transfer everything to /public_html correctly
// turn off buffering in gulp.src for best performance
return gulp.src( globs, { base: '.', buffer: false } )
.pipe( conn.newer( '/test' ) ) // only upload newer files
.pipe( conn.dest( '/test' ) );
} );
gulp.task('css', function () {
return gulp.src('scss/**/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('css'))
});
gulp.task('watch', function (){
gulp.watch('scss/**/*.scss', ['css', 'deploy']);
});
This line doesn't do what you think it does:
gulp.watch('scss/**/*.scss', ['css', 'deploy']);
This does not run the css task followed by the deploy task. Gulp executes all tasks with maximum concurrency unless you tell it otherwise.
That means your css and deploy tasks both start running immediately whenever a .scss file is changed. Depending on whether your css task finishes compiling your .scss files before your deploy task starts transmitting them, this might work or it might not.
You need to tell gulp to execute the deploy task only after the css task has finished:
gulp.task( 'deploy', ['css'], function () {
//...
});
Related
I have a gulp task to build css files from sass files as following:
gulp.task("sass", () => {
return (
gulp.src([
src_assets_folder + "sass/*.scss"
], {
since: gulp.lastRun("sass"),
})
.pipe(debug({title: "sass-debug:"}))
.pipe(sourcemaps.init())
.pipe(plumber({errorHandler: onError}))
.pipe(dependents())
.pipe(sass({ fiber: Fiber }))
.pipe(autoprefixer())
.pipe(minifyCss())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(dist_folder))
.pipe(browserSync.reload({ stream: true }))
);
});
gulp.watch([src_assets_folder + 'sass/**/*.scss'], gulp.series("sass"));
The sass files I'm building are the ones found immediately under sass folder and not all the files that are in the sass subfolders, but my watcher is on all the files inside the sass folder recursivly.
The problem I'm having is that when Browsersync is up, and then I update a sass file that is not found immediately under sass folder, Browsersync doesn't detect any changes, but when I update a sass file that is found immediately under sass folder, Browsersync detects the changes.
How can I solve that?
Finally I found a solution on how to fix my issue.
The idea is to include the partials in the task src and then filter them to prevent building them.
The final solution looks like this:
gulp.task("sass", () => {
const partials = readdirSync(src_sass_folder, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => `!${src_sass_folder + dirent.name}/**/*.scss`);
return (
gulp.src([
src_sass_folder + "*.scss",
src_sass_folder + "**/*.scss"
], {
since: gulp.lastRun("sass"),
})
.pipe(dependents())
.pipe(filter(['**'].concat(partials))) // =====================> HERE
.pipe(debug({title: "sass-debug:", showCount: false}))
.pipe(sourcemaps.init())
.pipe(plumber({errorHandler: onError}))
.pipe(sass({ fiber: Fiber }))
.pipe(autoprefixer())
.pipe(minifyCss())
.pipe(sourcemaps.write("."))
.pipe(gulp.dest(dist_folder + "Content"))
.pipe(browserSync.stream({match: '**/*.css'}))
);
});
This seems to be related to the since option of src(). With that option enabled, that task doesn't create any Vinyl objects to pipe unless there are detectable changes in the files immediately under sass folder since the last time the task was run. Removing that option should fix the issue.
I need to run jekyll build during gulp watch task and I did that as per the following code.
var gulp = require('gulp-help')(require('gulp')),
sass = require('gulp-sass');
gulp.task('sass', function(){
return gulp.src(sassFiles)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest(cssDest));
});
gulp.task('jekyll-build', function (done) {
return cp.spawn(jekyll, ['build'], {stdio: 'inherit'})
.on('close', done);
});
gulp.task('default', ['sass'], function(){
gulp.watch(['_includes/**/*.js', '_includes/**/*._', 'assets/styles/**/*.scss'], ['jekyll-build', 'sass']);
});
When I make some changes in any file and try to save at once, command runs in terminal but it is not getting reflected in UI. I need to save twice or thrice to get the changes reflected. Not sure what's the issue or whether its the issue of the gulp watch code added here. Any help is appreciated.
When you say the changes are not reflected do you mean the browser is not refreshing?
The line to launch jekyll build is different for mac vs Windows, your looks like it is for a Mac, on Windows I use jekyll.bat on this line (jekyll, ['build'].
In your watch step you are not watching very much. Rather than try to tell gulp to watch every different thing I do the opposite and tell gulp to watch everything **/*.* and then tell it what not to watch like !_site/**/*. This also lets you watch the config file for changes.
Also, it doesn't look like you are live-reloading with browser sync, that is half the fun of using gulp with jekyll (other half is having gulp do sass processing as it is much faster than jekyll).
Here is a gulp file that I use and a link to a write up I did about it:
https://rdyar.github.io/2017/10/01/speed-up-jekyll-by-using-gulp-for-sass-and-other-assets/
var gulp = require('gulp');
var browserSync = require('browser-sync');
var cp = require('child_process');
var sass = require('gulp-sass');
var postcss = require('gulp-postcss');
var sourcemaps = require('gulp-sourcemaps');
var autoprefixer = require('autoprefixer');
var watch = require('gulp-watch');
var uglify = require('gulp-uglify');
var cssnano = require('cssnano');
var imagemin = require('gulp-imagemin');
var htmlhint = require("gulp-htmlhint");
var messages = {
jekyllBuild: '<span style="color: grey">Running:</span> $ jekyll build'
};
// Gulp as asset manager for jekyll. Please note that the assets folder is never cleaned
//so you might want to manually delete the _site/assets folder once in a while.
// this is because gulp will move files from the assets directory to _site/assets,
// but it will not remove them from _site/assets if you remove them from assets.
/**
* Build the Jekyll Site - for windos. If you are on a Mac/linux change jekyll.bat to just jekyll
*/
gulp.task('jekyll-build', function (done) {
browserSync.notify(messages.jekyllBuild);
return cp.spawn('jekyll.bat', ['build'], {stdio: 'inherit'})
.on('close', done);
});
/**
* Rebuild Jekyll & do page reload when watched files change
*/
gulp.task('jekyll-rebuild', ['jekyll-build'], function () {
browserSync.reload();
});
/**
* Wait for jekyll-build, then launch the Server
*/
gulp.task('serve', ['jekyll-build'], function() {
browserSync.init({
server: "_site/"
});
});
/**
* Watch jekyll source files for changes, don't watch assets
*/
gulp.task('watch', function () {
gulp.watch(['**/*.*', '!_site/**/*','!_assets/**/*','!node_modules/**/*','!.sass-cache/**/*' ], ['jekyll-rebuild']);
});
//watch just the sass files - no need to rebuild jekyll
gulp.task('watch-sass', ['sass-rebuild'], function() {
gulp.watch(['_assets/sass/**/*.scss'], ['sass-rebuild']);
});
// watch just the js files
gulp.task('watch-js', ['js-rebuild'], function() {
gulp.watch(['_assets/js/**/*.js'], ['js-rebuild']);
});
// watch just the image files
gulp.task('watch-images', ['images-rebuild'], function() {
gulp.watch(['_assets/img/**/*.*'], ['images-rebuild']);
});
//if sass files change just rebuild them with gulp-sass and what not
gulp.task('sass-rebuild', function() {
var plugins = [
autoprefixer({browsers: ['last 2 version']}),
cssnano()
];
return gulp.src('_assets/sass/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass())
.pipe(sourcemaps.init())
.pipe(postcss(plugins))
.pipe(sourcemaps.write('.'))
.pipe( gulp.dest('_site/assets/css/') )
.pipe(browserSync.reload({
stream: true
}))
});
gulp.task('js-rebuild', function(cb) {
return gulp.src('_assets/js/**/*.js')
.pipe(uglify())
.pipe( gulp.dest('_site/assets/js/') )
.pipe(browserSync.reload({
stream: true
}))
});
gulp.task('images-rebuild', function(cb) {
return gulp.src('_assets/img/**/*.*')
.pipe( gulp.dest('_site/assets/img/') )
.pipe(browserSync.reload({
stream: true
}))
});
/**
* Default task, running just `gulp` will
* compile the jekyll site, launch BrowserSync & watch files.
*/
gulp.task('default', ['serve', 'watch','watch-sass','watch-js','watch-images']);
//build and deploy stuff
gulp.task('imagemin', function() {
console.log('Minimizing images in source!!');
return gulp.src('_assets/img/**/*')
.pipe(imagemin())
.pipe(gulp.dest(function (file) {
return file.base;
}));
});
gulp.task('w3', function() {
gulp.src("_site/**/*.html")
.pipe(htmlhint())
.pipe(htmlhint.reporter())
})
// validate from the command line instead, works better
// npm install htmlhint -g
// htmlhint _site/**/*.html
I'm developing a Jekyll plugin. When I run the jekyll serve command, site files are regenerated when I change any markdown, html, or plugin files, as expected. The problem I've found is that while markdown/HTML files are regenerated, the plugins themselves are not reloaded. I have to terminate jekyll serve and issue the command again for the plugin changes to go into effect. Is there a way to make it so that the plugins get reloaded automatically when changed?
This is for Jekyll 3.1.2.
Based on the suggestion from #DavidJacquel and the gist I found here, I used Gulp with this gulpfile
'use strict';
var gulp = require('gulp'),
express = require('express'),
spawn = require('child_process').spawn;
var jekyll_file = process.platform === 'win32' ? 'jekyll.bat' : 'jekyll';
gulp.task('jekyll', () => {
var jekyll = spawn(jekyll_file, ['build', '--incremental']);
var output = '';
jekyll.stdout.on('data', (t) => { output += t; });
jekyll.stderr.on('data', (t) => { output += t; });
jekyll.on('exit', (code) => {
if (code)
console.log(`Jekyll exited with code: ${code}\n${output}`);
else
console.log("Finished Jekyll build");
});
});
gulp.task('serve', () => {
var server = express();
server.use(express.static('_site/'));
server.listen(4000);
});
gulp.task('watch', () => {
gulp.watch(['**/*.html', '**/*.md', '_plugins/*.rb', '!_site/**/*'], ['jekyll']);
});
gulp.task('default', ['jekyll', 'serve', 'watch']);
to get the desired effect. Also created issue here.
Half an year a go I was using this gulpfile.js (shown below) and it worked flawlessly. Now, on windows 8.1 64bit I can't get it to properly work since hours. I'm using LiveReload in Firefox to see the changes in RealTime and Growl to get the notifications that it was changed.
The entire source code is:
var gulp = require('gulp'),
gutil = require('gulp-util'),
notify = require('gulp-notify'),
autoprefix = require('gulp-autoprefixer'),
minifyCSS = require('gulp-minify-css'),
exec = require('child_process').exec,
sys = require('sys'),
uglify = require('gulp-uglify'),
changed = require('gulp-changed'),
livereload = require('gulp-livereload'),
rename = require('gulp-rename'),
imagemin = require('gulp-imagemin'),
cache = require('gulp-cache'),
path = require('path'),
watch = require('gulp-watch'),
sass = require('gulp-sass');
// Which directory should Sass compile to?
var targetDir = 'resources/compiled';
// .pipe(minifyCSS())
gulp.task('scss', function () {
gulp.src('resources/uncompiled/**/*.scss')
.pipe(changed(targetDir))
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefix('last 15 version'))
.pipe(changed(targetDir))
.on('error', gutil.log)
.pipe(gulp.dest(targetDir));
//! .sass files -> compile, minify, autoprefix and publish
watch('resources/uncompiled/**/*.scss', function(files) {
return files.pipe(changed(targetDir))
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefix('last 15 version'))
.on('error', gutil.log)
.pipe(gulp.dest(targetDir))
.pipe(notify({
message: "File: <%= file.relative %>",
title: "SASS compiled, minified and published."
}));
});
});
gulp.task('js', function() {
gulp.src('resources/uncompiled/**/*.js')
.pipe(changed(targetDir))
.pipe(uglify())
.pipe(changed(targetDir))
.pipe(gulp.dest(targetDir))
.pipe(notify({
message: "File: <%= file.relative %>",
title: "JavaScript minified and published."
}));
//! .js files -> compress and publish
watch('resources/uncompiled/**/*.js', function(files) {
return files.pipe(changed(targetDir))
.pipe(uglify())
.pipe(rename(function(path) {
path.dirname = path.dirname.replace(/assets\//g, "");
}))
.pipe(changed(targetDir))
.pipe(gulp.dest(targetDir))
.pipe(notify({
message: "File: <%= file.relative %>",
title: "JavaScript minified and published."
}));
});
});
gulp.task('images', function() {
gulp.src(['resources/uncompiled/**/*.png', 'resources/uncompiled/**/*.jpg', 'resources/uncompiled/**/*.ico', 'resources/uncompiled/**/*.gif'])
.pipe(changed(targetDir))
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
.pipe(changed(targetDir))
.pipe(gulp.dest(targetDir));
//! image files -> compress and publish
watch(['resources/uncompiled/**/*.png', 'resources/uncompiled/**/*.jpg', 'resources/uncompiled/**/*.ico', 'resources/uncompiled/**/*.gif'], function(files) {
return files.pipe(changed(targetDir))
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
.pipe(rename(function(path) {
path.dirname = path.dirname.replace(/assets\//g, "");
}))
.pipe(changed(targetDir))
.pipe(gulp.dest(targetDir))
.pipe(notify({
message: "Image: <%= file.relative %>",
title: "Image optimized and published."
}));
});
});
gulp.task('watch', function () {
// Create LiveReload server
var server = livereload();
// Watch any files in public dir, reload on change
gulp.watch(['resources/compiled/**']).on('change', function(file) {
server.changed(file.path);
});
});
// What tasks does running gulp trigger?
gulp.task('default', ['scss', 'js','images', 'watch']);
Now, I noticed that I need to change these lines
gulp.watch(['resources/compiled/**']).on('change', function(file) {
server.changed(file.path);
});
to
livereload.listen();
gulp.watch('resources/uncompiled/**/*.scss', ['scss']);
to comply with ver3. of gulp (or gulp-notifications?) but it still didn't resolve it.
My issue is that currently I can't get the script to work like before, to notice changes in the main.sass and to compress that file to .css file and to also notice if i've placed images/js files and move them accordingly. The images part is not that important, but the SASS is. It should put it in /compiled/css or /compiled/images accordingly.
Every time I try to change and save the sass files, I get this:
path.js:146
throw new TypeError('Arguments to path.resolve must be strings');
^
TypeError: Arguments to path.resolve must be strings
at Object.win32.resolve (path.js:146:13)
at DestroyableTransform._transform (L:\xampp\htdocs\node_modules\gulp-changed\index.js:72:22)
at DestroyableTransform.Transform._read (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_modules
\readable-stream\lib\_stream_transform.js:172:10)
at DestroyableTransform.Transform._write (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_module
s\readable-stream\lib\_stream_transform.js:160:12)
at doWrite (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_modules\readable-stream\lib\_stream_
writable.js:326:12)
at writeOrBuffer (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_modules\readable-stream\lib\_s
tream_writable.js:312:5)
at DestroyableTransform.Writable.write (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_modules\
readable-stream\lib\_stream_writable.js:239:11)
at DestroyableTransform.Writable.end (L:\xampp\htdocs\node_modules\gulp-changed\node_modules\through2\node_modules\re
adable-stream\lib\_stream_writable.js:467:10)
at File.pipe (L:\xampp\htdocs\node_modules\gulp-watch\node_modules\vinyl\index.js:103:14)
at L:\xampp\htdocs\fusion\_designs\cms-design\gulpfile.js:33:22
at write (L:\xampp\htdocs\node_modules\gulp-watch\index.js:123:9)
at L:\xampp\htdocs\node_modules\gulp-watch\node_modules\vinyl-file\index.js:52:4
at L:\xampp\htdocs\node_modules\gulp-watch\node_modules\vinyl-file\node_modules\graceful-fs\graceful-fs.js:76:16
at fs.js:334:14
at L:\xampp\htdocs\node_modules\gulp-watch\node_modules\vinyl-file\node_modules\graceful-fs\graceful-fs.js:42:10
at L:\xampp\htdocs\node_modules\gulp-watch\node_modules\chokidar\node_modules\readdirp\node_modules\graceful-fs\grace
ful-fs.js:42:10
Of course I tried to change the paths, tried to use directly paths in the functions instead of passing variables, but to no avail.
Any suggestions? I've been struggling for 4 hours now and I did manage to get it to work to some extend, but I had to remove a lot of the functionality and to restart gulp every time. I couldn't get the images to get "minified" as well.
Well, several days later and I solved my issue on my own.
First of all, I had to set a gulp.watch for each type. I changed the gulp.tasks to perform one thing only.
Now every .scss sass, .js javascript, .jpg/.png/.bmp image file gets checked for changes and if so, the needed task gets called, which on it's own then compiled/minifies/moves the respected file and fires a (growl) notification.
Since I'm on Windows 8.1 I do have OS notifications but I'd rather use Growl, hence the growlNotifications are used.
Full source code of my gulpfile.js:
var gulp = require('gulp'),
gutil = require('gulp-util'),
notify = require('gulp-notify'),
autoprefix = require('gulp-autoprefixer'),
minifyCSS = require('gulp-minify-css'),
exec = require('child_process').exec,
sys = require('sys'),
uglify = require('gulp-uglify'),
changed = require('gulp-changed'),
livereload = require('gulp-livereload'),
rename = require('gulp-rename'),
imagemin = require('gulp-imagemin'),
cache = require('gulp-cache'),
path = require('path'),
watch = require('gulp-watch'),
growl = require('gulp-notify-growl'),
sass = require('gulp-sass');
// Initialize the Growl notifier instead of the default OS notifications
// meaning, this: https://i.imgur.com/ikkINZr.png
// changes to this: https://i.imgur.com/zz9m9k6.png
var growlNotifier = growl({
hostname : 'localhost' // IP or Hostname to notify, default to localhost
});
// Which directory should the files compile to?
var targetDir = 'resources/compiled';
gulp.task('scss', function () {
gulp.src('resources/uncompiled/**/*.scss')
.pipe(changed(targetDir))
//.pipe(minifyCSS()) //makes it hard to debug , to be used for in-production only
.pipe(sass({errLogToConsole: true}))
.pipe(autoprefix('last 15 version'))
.pipe(changed(targetDir))
.on('error', gutil.log)
.pipe(gulp.dest(targetDir))
.pipe(growlNotifier({ // change to notify if you wish to use your default OS notifications
message: "File: <%= file.relative %>",
title: "SASS compiled, minified and published."
}))
.pipe(livereload()); //this is how we notify LiveReload for changes
});
gulp.task('js', function() {
//needs testing, but it should be OK
gulp.src('resources/uncompiled/**/*.js')
.pipe(changed(targetDir))
.pipe(uglify())
.pipe(changed(targetDir))
.on('error', gutil.log)
.pipe(gulp.dest(targetDir))
.pipe(notify({
message: "File: <%= file.relative %>",
title: "Javascript minified and published."
}))
.pipe(livereload());
});
gulp.task('images', function() {
gulp.src(['resources/uncompiled/**/*.png', 'resources/uncompiled/**/*.jpg', 'resources/uncompiled/**/*.ico', 'resources/uncompiled/**/*.gif'])
.pipe(changed(targetDir))
//imagemin causes errors for me: http://pastebin.com/eDF3SeS6
//.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))
.pipe(changed(targetDir))
.on('error', gutil.log)
.pipe(gulp.dest(targetDir))
.pipe(growlNotifier({
message: "Image: <%= file.relative %>",
title: "Image optimized and published."
}))
.pipe(livereload());
});
gulp.task('watch', function() {
livereload.listen(); //we need to tell gulp to listen for livereload notification
//this is how we watch for changes in specific files and fire specific tasks
gulp.watch('resources/uncompiled/**/*.scss', ['scss']);
gulp.watch('resources/uncompiled/**/*.js', ['js']);
gulp.watch(['resources/uncompiled/**/*.png', 'resources/uncompiled/**/*.jpg', 'resources/uncompiled/**/*.ico', 'resources/uncompiled/**/*.gif'], ['images']);
});
// What tasks does running gulp trigger?
gulp.task('default', ['scss', 'js','images', 'watch']);
Everything is almost working, compass is compiling the CSS and a few other tasks are running to minify, rename, rev etc. The problem is that when a style change occurs LiveReload is reloading the page instead of injecting the style. If I switch back to compass watch then style injection occurs. Is it possible to have style injection with Gulp, Compass and LiveReload? I hope so because if not I will have to run compass watch in 1 terminal and gulp in another which seems a bit clunky. Here is the relevant code from the gulpfile.js
var gulp = require('gulp'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat'),
compass = require('gulp-compass'),
minifyCSS = require('gulp-minify-css'),
rev = require('gulp-rev'),
rename = require('gulp-rename'),
clean = require('gulp-clean'),
lr = require('tiny-lr'),
server = lr(),
livereload = require('gulp-livereload');
gulp.task('compass', function() {
gulp.src('./static/scss/*.scss')
.pipe(compass({
css: 'static/css',
sass: 'static/scss',
image: 'static/images',
font: 'static/fonts',
javascript: 'static/js',
comments: false,
style: 'expanded',
bundle_exec: true,
require: ['wegowise_styles/compass']
}))
.on('error', function(err) {})
.pipe(gulp.dest('./static/css/'))
.pipe(livereload(server))
.pipe(minifyCSS())
.pipe(rename({suffix: '.min'}))
.pipe(rev())
.pipe(gulp.dest('./static/production/'))
.pipe(rev.manifest())
.pipe(rename('css-manifest.json'))
.pipe(gulp.dest('./static/production/'));
});
gulp.task('clean', function() {
return gulp.src(['static/production'], {read: false})
.pipe(clean());
});
gulp.task('watch', function() {
gulp.watch('static/scss/**/*.scss', ['compass']);
gulp.watch('static/js/**/*.js', ['scripts']);
});
gulp.task('default', ['clean', 'watch']);
ps. I am using the LiveReload chrome extension
Yes, it is possible. I haven't seem in your code (maybe because you removed the rest of the file) when you start tiny-lr, i.e.:
var gutil = require('gulp-util');
gulp.task('tiny', function(next) {
server.listen(35729, function() {
gutil.log('Server listening on port: ', gutil.colors.magenta(port));
next();
});
});
// add as a dependency in your watch task
gulp.task('watch', ['tiny'], function() {
gulp.watch('static/scss/**/*.scss', ['compass']);
gulp.watch('static/js/**/*.js', ['scripts']);
});
The error might be related to the scripts task as well, so maybe include it in the question so we can take a look. Maybe, finally, there is some other task causing the issue.
In order to be sure, I just created a test here, and created a index.html file inside the static folder, pointing to css/file.css.
Created a simple static/scss/file.scss with a body background-color. I've used the same code snippet you provided for the rest of the gulpfile.
Also created a node-static server and served all files under static/ folder.
At the end, is there any other automated task involved in the building process?