Gulp 'watch' not saving files rendered with gulp-swig - gulp

I've used Gulp a number of times but this problem has me totally stumped. I have a render task to save an HTML template piped through gulp-swig. It works perfectly fine when invoked manually via gulp render but will not save when the task is triggered by gulp.watch. So, to clarify, the watcher does trigger the task but the rendered file doesn't actually get saved to its destination.
I've boiled the problem down to the following, removing all other tasks from my gulpfile, axed plumber, context data, etc. Any help appreciated!
var gulp = require( 'gulp' ),
browserSync = require( 'browser-sync' ).create(),
rename = require( 'gulp-rename' ),
swig = require( 'gulp-swig' ),
reload = browserSync.reload;
gulp.task( 'render', function() {
return gulp.src( './dev/template.html' )
.pipe( swig() )
.pipe( rename( 'index.html' ) )
.pipe( gulp.dest( './preview' ) )
.on( 'end', reload );
});
gulp.task( 'serve', function() {
browserSync.init( { server: './preview' } );
gulp.watch( './dev/*.html', [ 'render' ] );
});
gulp.task( 'default', [ 'serve' ] );

Duh, got it working. It appears that swig caches the template by default (?) so it was in fact saving the file but it was identical. I noticed a 'cache' option in another (unrelated) post about swig which did the trick. So, I needed to pass in an options object, like so:
.pipe( swig({
defaults: { cache: false }
}) )

Related

Gulp + Browsersync is compiling but localhost is not working

I have a Gulp + Browsersync setup which is compiling everything but when I try to view the site in the browser the localhost (Access URLs) is not working.
my code looks like below:
const browsersync = done => {
browserSync.init({
proxy: config.projectURL, // Proxing website.local:8000
open: config.browserAutoOpen, //false
injectChanges: config.injectChanges, //true
watchEvents: [ 'change', 'add', 'unlink', 'addDir', 'unlinkDir' ]
});
done();
};
// Helper function to allow browser reload with Gulp 4.
const reload = done => {
browserSync.reload();
done();
};
Running as follows:
gulp.task(
'default',
gulp.parallel( 'styles', 'customJS', 'images', browsersync, () => {
gulp.watch( config.watchPhp, reload ); // Reload on PHP file changes.
gulp.watch( config.watchStyles, gulp.parallel( 'styles' ) ); // Reload on SCSS file changes.
gulp.watch( config.watchJsCustom, gulp.series( 'customJS', reload ) ); // Reload on customJS file changes.
gulp.watch( config.imgSRC, gulp.series( 'images', reload ) ); // Reload on customJS file changes.
})
);
Any ideas would be greatly appreciated.
Thanks

How to create directory with name given by a prompt question with gulp

I would like to run a gulpfile.js task which asks in prompt the directory name to create it inside the build folder.
Structure
gulfile.js
build/
foo/ <-- directory name given by a question
gulpfile task
gulp.task( 'questions', function( callback ) {
return gulp.src('build')
.pipe( prompt.prompt({
type: 'input',
name: 'dir_name',
message: 'What is directory name ?'
}, function( res ){
//console.log(res.dir_name);
//make directory called res.dir_name in build/
}))
.pipe(gulp.dest('build'));
});
How can I do this ?
I found a solution thanks gulp-prompt package.
This example copy content base folder in build folder.
const prompt = require('gulp-prompt');
var my_dirname, project_build_path ;
gulp.task( 'questions', function( callback ) {
return gulp.src('./base/**/*')
.pipe( prompt.prompt({
type: 'input',
name: 'dir_name',
message: 'What is directory name ?'
}, function( res ){
my_dirname = res.dir_name;
project_build_path = 'build/' + my_dirname;
gulp.src( './base/**/*' ).pipe( gulp.dest( project_build_path ) );
}));
});

gulp add folder in zip archive

gulp.task( 'zip', function () {
return gulp.src( './dist/**' )
.pipe(zip( 'dist.zip' ))
.pipe(gulp.dest( './' ));
});
I have next structure
dist.zip
all-files
How do I make the following structure in the archive?
dist.zip
dist
all-files
Your code is fine except for the gulp.dest which takes a string (or a function):
gulp.task( 'zip', function () {
return gulp.src( './dist/**' )
.pipe(zip( 'dist.zip' ))
// .pipe(gulp.dest( ./ )); your code, note the apostrophes below
.pipe(gulp.dest( './' ));
});

Change stream file names on the go in gulp-watch task

Even though it is not that necessary I want to have my dev-environment as clean as possible and therefore automatically remove deleted files from my build directory.
Since I'm using TypeScript I want to have the compiled and static files in one directory on the fly. I'm achieving this with watching static files and copying them to a build folder (I probably should rename that in the future).
Deleted files should then also be removed from the build directory. I tried this and almost succeeded. The only thing I'm trying to find out is how to change a stream file name from app/tmp.html to build/app/tmp.html.
This is my watch-task so far:
let gulp = require( 'gulp' );
let watch = require( 'gulp-watch' );
let filter = require( 'gulp-filter' );
let clean = require( 'gulp-clean' );
gulp.task( 'watch', function() {
let deletedFilter = filter( file => {
return file.event !== 'unlink' && file.event !== 'deleted';
}, { restore: true } );
let newFilter = filter( file => {
return file.event !== 'add';
} );
watch( './app/**/*.{html,css,js,map,svg,png,jpg}' )
.pipe( deletedFilter )
.pipe( gulp.dest( './build/app/' ) )
.pipe( newFilter )
.pipe( deletedFilter.restore ) // this line here
.pipe( clean() ); // and that line there still make
// some trouble
} );
Thank you so much for any help!
Okay, I was taking a little break and dug into a little deeper. Looking at gulp-debug I came up with a solution, using the following, additional node modules to gulp and gulp-watch:
gulp-filter to filter out deleted files in the first place
through2 to go through all filtered (deleted) files
path to get the relative path
gulp-clean to actually remove the files from the build directory
All together it looks something like this (as of writing this answer, I'm using NodeJS 5.10.1):
'use strict';
let staticFilePattern = `./app/**/*.{html,css,js,map,svg,png,jpg}`;
let buildDirectory = 'build';
let gulp = require( 'gulp' );
let watch = require( 'gulp-watch' );
let filter = require( 'gulp-filter' );
let clean = require( 'gulp-clean' );
let through = require( 'through2' );
let path = require( 'path' );
let changeToBuildDirectory = function() {
return through.obj( function( file, enc, cb ) {
file.path = process.cwd() + `/${buildDirectory}/` + path.relative( process.cwd(), file.path );
cb( null, file );
});
};
gulp.task( 'watch', function() {
let deletedFilter = filter( file => {
return file.event !== 'unlink' && file.event !== 'deleted';
}, { restore: true } );
let newFilter = filter( file => {
return file.event !== 'add';
} );
watch( staticFilePattern )
.pipe( deletedFilter )
.pipe( gulp.dest( `./${buildDirectory}/app/` ) )
.pipe( newFilter )
.pipe( debug( { title: 'Foo' } ) )
.pipe( deletedFilter.restore )
.pipe( changeToBuildDirectory() )
.pipe( clean() );
} );
I don't find it very clean, since I'm just modifying the path on the file object, but it works, so I'm pleased. If you got a more clean solution, you are welcome to post another answer or leave it in the comments
I hope it is useful to some extend.
Cheers!

Using Browserify with a revision manifest in Gulp, getting "Error: write after end"

I'm trying to compile a React app, append a hash to the output filename and produce a revision manifest, so that I can tell the browser to cache it forever. The problem is that the dozen or so tools involved don't all work together perfectly, at least as far as I can figure out by trying to assimilate all of their readmes and juggle .pipe calls.
Gulpfile: gist
Gulp task:
gulp.task( 'compile:js', function() {
var browserifyTransform = transform( function( filename ) {
return browserify( filename )
.transform( reactify )
.bundle();
});
return gulp.src( 'src/index.js' )
.pipe( browserifyTransform )
.pipe( sourcemaps.init({ loadMaps: true }))
.pipe( uglify() )
.pipe( rev() )
.pipe( gulp.dest( 'static/dist' ));
});
update Simplified version, same error:
gulp.task( 'compile:js', function() {
var browserifyTransform = transform( function( filename ) {
return browserify( filename )
.transform( reactify )
.bundle();
});
return gulp.src( 'src/index.js' )
.pipe( browserifyTransform )
.pipe( gulp.dest( 'static/dist' ));
});
Error stack:
[15:55:04] Using gulpfile ~/Projects/pixsplodr/gulpfile.js
[15:55:04] Starting 'compile:js'...
Error: write after end
at writeAfterEnd (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:161:12)
at Labeled.Writable.write (/home/dan/Projects/pixsplodr/node_modules/browserify/node_modules/readable-stream/lib/_stream_writable.js:208:5)
at write (_stream_readable.js:601:24)
at flow (_stream_readable.js:610:7)
at _stream_readable.js:578:7
at process._tickCallback (node.js:419:13)
There are a few open bugs that result in this error (example: github.com/hughsk/vinyl-transform/issues/1). The problem with them is that when the original src stream ends, it ends the writable stream, which is still being used. Hence the error.
Try this instead.
gulp.task( 'compile:js', function() {
var browserifyTransform = transform( function( filename ) {
return browserify( filename )
.transform( reactify )
.bundle();
});
gulp.src( 'src/index.js' )
.pipe( browserifyTransform )
.pipe( sourcemaps.init({ loadMaps: true }))
.pipe( uglify() )
.pipe( rev() )
.pipe( gulp.dest( 'static/dist' ));
return gulp.src( '');
});
By returning a seperate gulp.src, gulp is forced to wait until the initial command is finished in order to return the new src.
I resolve this issue using gulp-streamify package.
I had to rewrite my task as follow:
gulp = require('gulp');
rev = require('gulp-rev'); // add hash to filename
rimraf = require('gulp-rimraf'); // delete folder
gulpsync = require('gulp-sync')(gulp); // sync gulp task
babel = require('gulp-babel'); // es6 transpiler
browserify = require('browserify');
source = require('vinyl-source-stream');
streamify = require('gulp-streamify');
gulp.task('compile-es6', function(){
var stream = browserify('app/assets/javascript/application.js')
.transform("babelify", {presets: ["es2015"]})
.bundle();
return stream.pipe(source('bundle.js'))
.pipe(streamify(rev()))
.pipe(gulp.dest('public/javascripts'))
.pipe(rev.manifest('./rev-manifest.json',{merge:true}))
.pipe(gulp.dest(''));
});
Well, I have solution that satisfies my requirements, but it isn't perfect.
Let Browserify start the stream from a file name, instead of using gulp.src
Use vinyl-source-stream to transform Browserify's Node stream to a Gulp stream, before passing the data on to other gulp plugins
I am also using gulp-rev to append a hash to generated filenames, and to create a manifest that maps them to their original filename.
I was having trouble with source maps earlier too, but I have found that using Browserify transforms and settings seems to work better than using Gulp plugins on Browserify's output. That might be entirely due to user error, but I have been seeing so many conflicting Browserify / Gulp examples and minimal examples that I was unable to extend in an intuitive way, that I am just glad to have a working build with all of the features that I wanted.
var gulp = require( 'gulp' );
var gutil = require( 'gulp-util' );
var watchify = require( 'watchify' );
var browserify = require( 'browserify' );
var source = require( 'vinyl-source-stream' );
var buffer = require( 'vinyl-buffer' );
var sass = require( 'gulp-sass' );
var _ = require( 'lodash' );
var rev = require( 'gulp-rev' );
// Dev build
gulp.task( 'watch', [ 'sass' ], function() {
gulp.watch( 'node_modules/quiz/style/**/*.scss', [ 'sass' ]);
builder( './src/app/index.js', true ).bundle( './dist/static', 'quiz-app.min.js' );
});
// Production build
gulp.task( 'build', [ 'sass' ], function() {
builder( './src/app/index.js', false ).bundle( './dist/static', 'quiz-app.min.js' );
});
// snip //
function builder( entry, isDev ) {
var bundler;
if( isDev ) {
bundler = watchify( browserify(
'./src/app/index.js',
_.extend( watchify.args, { debug: true })
));
} else {
bundler = browserify(
'./src/app/index.js'
);
}
bundler.transform( 'reactify' );
bundler.transform( 'es6ify' );
bundler.transform({ global: true }, 'uglifyify' );
bundler.on( 'log', gutil.log ); // Help bundler log to the terminal
function bundle( dest, filename ) {
return bundler.bundle()
.on( 'error', gutil.log.bind( gutil, 'Browserify error' )) // Log errors during build
.pipe( source( filename ))
.pipe( buffer() )
.pipe( rev() )
.pipe( gulp.dest( dest ))
.pipe( rev.manifest() )
.pipe( gulp.dest( dest ));
}
return { bundle: bundle };
}
I also tried just using the tools from NPM scripts, but I was unable to find a good way to do incremental builds while watching a set of files.