I'm a bit stumped with gulp. Based on the docs, in order to get sequential execution, I should be returning the stream from my tasks, so i tried to do the below for my gulpfile. But as best I can tell, there's a race condition. Half the time I get ENOENT, lstat errors, the other half it succeeds, but my deployDir has weird folder names and missing files all over.. Am I missing something? Is there a trick to this?
var gulp = require('gulp'),
filter = require('gulp-filter'),
mainBowerFiles = require('main-bower-files'),
del = require('del'),
inject = require("gulp-inject"),
uglify = require('gulp-uglifyjs');
var config = {
bowerDir: 'src/main/html/bower_components',
cssDir: 'src/main/html/css/lib',
fontsDir: 'src/main/html/fonts/lib',
imgDir: 'src/main/html/img/lib',
jsDir: 'src/main/html/js/lib',
deployDir: 'src/main/resources/html'
};
gulp.task('default', ['clean', 'bowerdeps', 'dev']);
gulp.task('clean', function() {
return del([
config.cssDir,
config.fontsDir,
config.jsDir,
config.deployDir
]);
});
gulp.task('dev', function() {
return gulp
.src(['src/main/html/**', '!src/main/html/{bower_components,bower_components/**}'])
.pipe(gulp.dest(config.deployDir));
});
gulp.task('bowerdeps', function() {
var mainFiles = mainBowerFiles();
if(!mainFiles.length) return; // No files found
var jsFilter = filterByRegex('.js$');
var cssFilter = filterByRegex('.css$');
var fontFilter = filterByRegex('.eot$|.svg$|.ttf$|.woff$');
return gulp
.src(mainFiles)
.pipe(jsFilter)
.pipe(gulp.dest(config.jsDir))
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe(gulp.dest(config.cssDir))
.pipe(cssFilter.restore())
.pipe(fontFilter)
.pipe(gulp.dest(config.fontsDir));
});
// Utility Functions
var filterByRegex = function(regex){
return filter(function(file){
return file.path.match(new RegExp(regex));
});
};
Dependencies run always parallel: ['clean', 'bowerdeps', 'dev'].
https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-tasks-in-series.md
You can use run-sequence for sequencing tasks.
Other thing: del doesn't return a stream. Use callback instead:
gulp.task('clean', function(cb) {
del([
config.cssDir,
config.fontsDir,
config.jsDir,
config.deployDir
], cb);
});
Related
I'm having a strange problem. I'm using gulp to compile a react app and am having it copy index.html to the appropriate web directory. When I first run gulp, all runs as expected, but when the file changes and the watch task is run, gulp copies an empty version of the file to the web directory. Does anyone know why this might be happening? Here is my gulpfile.js:
var gulp = require('gulp');
var browserify = require('browserify');
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var livereload = require('gulp-livereload');
gulp.task('livereload', function() {
console.log('reloading');
livereload();
});
gulp.task('copyindextodist', function() {
gulp.src('app/index.html')
.pipe(gulp.dest('dist'));
});
gulp.task('compilejs', function() {
browserify({
entries: 'app/index.js',
extensions: ['.js'],
debug: true
})
.transform('babelify', {presets: ['es2015', 'react']})
.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('dist'));
});
gulp.task('publishapp', function() {
gulp.src('dist/*.*')
.pipe(gulp.dest('../public'));
});
gulp.task('copypaste', function() {
gulp.src('app/index.html')
.pipe(gulp.dest('../public'));
});
gulp.task('watch', function() {
livereload.listen();
gulp.watch('app/index.html', ['copyindextodist']);
gulp.watch('dist/index.html', ['publishapp']);
gulp.watch('app/index.js', ['compilejs']);
gulp.watch('dist/app.js', ['publishapp']);
});
gulp.task('default', ['copyindextodist', 'compilejs', 'publishapp', 'watch']);
I had the same problem until I defined the dependencies correctly. You can define which tasks should be completed, before the current task starts:
gulp.task('compress', ['copy'], function() {
//.... your job
});
This means that the compress task will wait for the copy task to be finished. If you don't do that, you might end up with empty/truncated files and other strange results.
Just take care that your copy tasks return a stream object.
gulp.task('copy', function() {
// "return" is the important part ;-)
return gulp.src(['filepath/**/*'])
.pipe(gulp.dest('lib/newpath'))
});
If you have multiple copy commands running in your task this is tricky, but there is an extension for this:
var gulp = require('gulp');
var merge = require('merge-stream');
gulp.task('copy', function() {
var allStreams = [
gulp.src(['node_modules/bootstrap/dist/**/*'])
.pipe(gulp.dest('lib/bootstrap')),
gulp.src(['node_modules/jquery/dist/**/*'])
.pipe(gulp.dest('lib/jquery')),
];
return merge.apply(this, allStreams);
});
gulp.task('nextTask', ['copy'], function() {
// this task formerly produced empty files, but now
// has a valid dependency on the copy stream and
// thus has all files available when processed.
});
I have a gulpfile with some tasks. All task are combined in a default task, that has dependencies to all others tasks. I want to add a deploy task. The deploy can take a list of files. I want only deploy changed files.
Is there a way to get the pipes of all dependencies? Or any other way, without merge everything into one task?
Here a simple sample to explain:
var gulp = require('gulp');
var concat = require('gulp-concat');
var debug = require('gulp-debug');
var newer = require('gulp-newer');
gulp.task('default', ['js', 'css']);
gulp.task('js', function () {
return gulp.src('./app/**/*.js')
.pipe(newer('./dist/app.js'))
.pipe(concat('app.js'))
.pipe(gulp.dest('./dist/'));
});
gulp.task('css', function () {
gulp.src('./app/**/*.css')
.pipe(newer('./dist/style.css'))
.pipe(concat('style.css'))
.pipe(gulp.dest('./dist/'));
});
gulp.task('deploy', ['default'], function () {
gulp.src('./dist/*')
// Here I want only files changed in dist
.pipe(debug());
});
Update:
Here some more of my task:
gulp.task('default', ['js', 'css', 'images', 'templates']);
gulp.task('images', function () {
return gulp.src('./app/images/*')
.pipe(newer('./dist/app/images'))
.pipe(gulp.dest('./dist/app/images'));
gulp.task('templates', function () {
return gulp.src('./app/**/*.html')
.pipe(newer('./dist/app/templates.js'))
.pipe(minifyHTML({ empty: true }))
.pipe(templateCache({ module: 'app' }))
.pipe(uglify())
.pipe(gulp.dest('./dist/app'));
I added a deployed folder, where i keep track of all files that a deployed.
var gulp = require('gulp');
var concat = require('gulp-concat');
var debug = require('gulp-debug');
var newer = require('gulp-newer');
gulp.task('default', ['js', 'css']);
gulp.task('js', function () {
return gulp.src('./app/**/*.js')
.pipe(newer('./dist/app.js'))
.pipe(concat('app.js'))
.pipe(gulp.dest('./dist/'));
});
gulp.task('css', function () {
gulp.src('./app/**/*.css')
.pipe(newer('./dist/style.css'))
.pipe(concat('style.css'))
.pipe(gulp.dest('./dist/'));
});
gulp.task('deploy', ['default'], function () {
gulp.src('./dist/*')
.pipe(newer('./deployed'))
.pipe(debug())
.pipe(gulp.dest('./deployed'))
});
I've written a nice little build script that runs some pretty standard tasks like...
Cleaning out my deploy/ directory before initially
Building, concatenation, uglifying, and copying files from their dev/ directories to associated deploy/ directories
Watching for changes
etc.
But for better context, I've included just included it below:
var gulp = require('gulp');
var changed = require('gulp-changed');
var newer = require('gulp-newer');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var cssmin = require('gulp-minify-css');
var sourcemaps = require('gulp-sourcemaps');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var notify = require('gulp-notify');
var plumber = require('gulp-plumber');
var imagemin = require('gulp-imagemin');
var shopify = require('gulp-shopify-upload');
var watch = require('gulp-watch');
var rename = require('gulp-rename');
var filter = require('gulp-filter');
var flatten = require('gulp-flatten');
var del = require('del');
var argv = require('yargs').argv;
var runsequence = require('run-sequence');
var config = require('./config.json');
var plumberErrorHandler = {
errorHandler: notify.onError({
title: 'Gulp',
message: "Error: <%= error.message %>"
})
};
gulp.task('styles', function() {
return gulp.src(['dev/styles/updates.scss'])
.pipe(plumber(plumberErrorHandler))
.pipe(sourcemaps.init())
.pipe(sass({ errLogToConsole: true }))
.pipe(autoprefixer({ browsers: ['last 2 versions', 'ie >= 10', 'Android >= 4.3'] }))
.pipe(cssmin())
.pipe(sourcemaps.write())
.pipe(rename({ suffix: '.css', extname: '.liquid' }))
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('scripts', function() {
return gulp.src(['dev/scripts/**'])
.pipe(plumber(plumberErrorHandler))
.pipe(sourcemaps.init())
.pipe(concat('main.js'))
.pipe(uglify())
.pipe(sourcemaps.write())
.pipe(rename({ suffix: '.js', extname: '.liquid' }))
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('vendor', function() {
var styles = filter(['styles/**/*.scss']);
var scripts = filter(['scripts/**/*.js']);
return gulp.src(['dev/vendor/**'])
.pipe(plumber(plumberErrorHandler))
.pipe(styles)
.pipe(sass({ errLogToConsole: true }))
.pipe(cssmin())
.pipe(styles.restore())
.pipe(scripts)
.pipe(concat('vendor.js'))
.pipe(uglify())
.pipe(scripts.restore())
.pipe(flatten())
.pipe(gulp.dest('deploy/assets'));
});
gulp.task('copy', function() {
return gulp.src(['dev/liquid/**'], {base: 'dev/liquid'})
.pipe(plumber(plumberErrorHandler))
.pipe(newer('deploy/'))
.pipe(gulp.dest('deploy/'));
});
gulp.task('clean', function(cb) {
del(['deploy/**/*'], cb);
});
gulp.task('imagemin', function() {
return gulp.src(['dev/liquid/assets/*'])
.pipe(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true }))
.pipe(gulp.dest('dev/liquid/assets/'));
});
gulp.task('build', ['clean'], function(cb) {
runsequence(['copy', 'styles', 'scripts', 'vendor'], cb);
});
gulp.task('watch', ['build'], function() {
gulp.watch(['dev/styles/**/*.scss'], ['styles']);
gulp.watch(['dev/scripts/**/*.js'], ['scripts']);
gulp.watch(['dev/vendor/**/*.{js,scss}'], ['vendor']);
gulp.watch(['dev/liquid/**'], ['copy']);
});
gulp.task('upload', ['watch'], function() {
if (!argv.env) {
return false;
} else if (argv.env && config.shopify.hasOwnProperty(argv.env)) {
env = config.shopify[argv.env];
} else {
env = config.shopify.dev;
}
return watch('deploy/{assets|layout|config|snippets|templates|locales}/**')
.pipe(shopify(env.apiKey, env.password, env.url, env.themeId, env.options));
});
gulp.task('default', ['clean', 'build', 'watch', 'upload']);
The problem I've been running into is directly related to the upload task and copy task.
When running gulp --env [environment-name] (e.g. gulp --env staging) or just gulp --env, some of the time when I save a file living in one of the subdirectories of dev/liquid/, the copy task runs as expected, and the singular saved and copied file is then uploaded via. the upload task. However, occasionally I'll save a file and the copy task runs as usual, but then the watch upload freaks out and tries uploading every file inside of deploy/ (which causes an api call limit error, which naturally gives me problems).
I originally had used gulp-changed inside of my copy task, but then noticed that it only will do 1:1 mappings and not directories (not sure how correct I am on this). So I switched to gulp-newer, and things worked for a while, but then things started freaking out again.
I can't figure out what's causing this, I have my suspicions but I can't figure out how to act on them. Any advice, observations, suggestions for improvements, good places for a romantic dinner, reliable pet-sitter, etc. would be greatly appreciated.
tytytytyty!!!
_t
Edit: I've been having a hard time reproducing the freakout (i.e. all files trying to upload at once), and at times running the same gulp --env staging causes a freak out, and other times firing up the same task on the same set of files does nothing. Maybe it could possibly have something to do with gulp-newer and gulp-changed's use of date modified as its comparison??
Double Edit: Maybe it's a race condition cause it works sometimes, and sometimes not? I remember seeing something on the node-glob or minimatch github pages about race conditions....
I have the following gulpfile
gulp.task('browserify', function() {
bundle(false);
});
gulp.task('browserify-watch', function() {
bundle(true);
});
function bundle (performWatch) {
var bify = (performWatch === true
? watchify(browserify(finalBrowserifyOptions))
: browserify(finalBrowserifyOptions));
if (performWatch) {
bify.on('update', function () {
console.log('Updating project files...');
rebundle(bify);
});
}
bify.transform(babelify.configure({
compact: false
}));
function rebundle(bify) {
return bify.bundle()
.on('error', function () {
plugins.util.log('Browserify error');
})
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(plugins.sourcemaps.init({loadMaps: true}))
.pipe(plugins.sourcemaps.write('./'))
.pipe(gulp.dest(paths.build + assets.js));
}
return rebundle(bify);
}
The trouble is that gulp browserify works just fine. However, gulp browserify-watch detects the changes but the output never gets updated.
What am I doing wrong?
I encountered the same watchify failures in file-change detection (both with gulp and grunt). CLI watchify works as expected though. For example:
watchify ./src/app.js -t babelify --outfile ./build/bundle.js -v
Currently I switched to browserify-incremental. The perspective is different in regards to watchify approach. Here's the paragraph from their Github page which encopasses it best:
browserify-incremental can detect changes which occured in between
runs, which means it can be used as part of build systems which are
invoked on demand, without requiring a long lived process. Whereas
watchify is slow for the first run upon each startup,
browserify-incremental is fast every time after the very first.
Here's the "translated" CLI command to make use of browserify-incremental:
browserifyinc ./src/app.js -t babelify --outfile ./build/bundle.js -v
Here's a simple gulpfile.js script for watching and [re]bundling:
var gulp = require('gulp');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var babel = require('babelify');
var browserifyInc = require('browserify-incremental');
var bundleApp = function() {
var browserifyObj = browserify('./src/app.js', { debug: false, cache: {}, packageCache: {}, fullPaths: true }).transform(babel);
var bundler = browserifyInc(browserifyObj, {cacheFile: './browserify-cache.json'});
bundler.on('time', function (time) {
console.log('-> Done in ' + time/1000 + ' ms');
});
console.log('-> Bundling...');
bundler.bundle()
.on('error', function(err) { console.error(err); this.emit('end'); })
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./build'));
};
gulp.task('browserify', function () {
gulp.watch('./src/**/*.js', function () {
return bundleApp();
});
});
gulp.task('default', ['browserify']);
Looks like everything was fine my IDE, Webstorm, was caching the file. When I looked at the actual file on the box it was fine.
I don't understand what's wrong with this code. When I run it for the first time, rev_collector doesn't work. I mean: 'rev' and 'clean' works great, but css file name in index http didn't change ('rev_collector').
BUT it works properly when I start it again.
var gulp = require('gulp'),
less = require('gulp-less'),
rev_append = require('gulp-rev-append'),
rev = require('gulp-rev'),
revCollector = require('gulp-rev-collector'),
gutil = require('gulp-util'),
rimraf = require('rimraf'),
revOutdated = require('gulp-rev-outdated'),
path = require('path'),
through = require('through2');
gulp.task('rev', function(){
gulp.src('./src/less/*.less')
.pipe(less())
.pipe(rev())
.pipe(gulp.dest('./www/css/'))
.pipe(rev.manifest())
.pipe(gulp.dest('./src/manifest/'));
});
gulp.task('rev_collector', ['rev'], function(){
return gulp.src(['./src/manifest/**/*.json', './www/index.html'])
.pipe(revCollector({
replaceReved: true
}))
.pipe(gulp.dest('./www/'));
});
function cleaner() {
return through.obj(function(file, enc, cb){
rimraf( path.resolve( (file.cwd || process.cwd()), file.path), function (err) {
if (err) {
this.emit('error', new gutil.PluginError('Cleanup old files', err));
}
this.push(file);
cb();
}.bind(this));
});
}
gulp.task('clean', ['rev_collector'], function() {
gulp.src( ['./www/**/*.*'], {read: false})
.pipe( revOutdated(1) ) // leave 2 latest asset file for every file name prefix.
.pipe( cleaner() );
return;
});
gulp.task('rev_all', ['rev', 'rev_collector', 'clean']);
Today, I met the same problem.
After I got nothing from this page, I searched a lot.
I fount my problom came from the order the files loaded.
So I use a new plugin:
var runSequence = require('run-sequence');
then, I rewrite the load code:
gulp.task('default',['build']);
gulp.task('build', function (done) {
runSequence(
['clean'],
['images'],
['statcstyles', 'staticjs'],
['scripts'],
['styles'],
['html'],
done);
});
The code make sure that revCollector will always loaded after manifest create.
Then my problem solved.
I hope it helps you.