Using gulp-watch with babel.js - node.js

Below is a Gulp ES6 transpilation task. It works fine, but I'm trying to replace gulp.watch with the gulp-watch plugin so new files will be caught. The problem is that gulp-watch isn't giving me what gulp.watch does in the callback, and I'm not sure what to do about it.
Here's my original working task:
var gulp = require('gulp'),
rename = require('gulp-rename'),
plumber = require('gulp-plumber'),
gprint = require('gulp-print'),
notify = require('gulp-notify'),
babel = require('gulp-babel');
gulp.task('default', function() {
return gulp.watch('../**/**-es6.js', function(obj){
if (obj.type === 'changed') {
gulp.src(obj.path, { base: './' })
.pipe(plumber({
errorHandler: function (error) { /* elided */ }
}))
.pipe(babel())
.pipe(rename(function (path) {
path.basename = path.basename.replace(/-es6$/, '');
}))
.pipe(gulp.dest(''))
.pipe(gprint(function(filePath){ return "File processed: " + filePath; }));
}
});
});
And here's all that I have so far with gulp-watch:
var gulp = require('gulp'),
rename = require('gulp-rename'),
plumber = require('gulp-plumber'),
gprint = require('gulp-print'),
notify = require('gulp-notify'),
babel = require('gulp-babel'),
gWatch = require('gulp-watch');
gulp.task('default', function() {
return gWatch('../**/**-es6.js', function(obj){
console.log('watch event - ', Object.keys(obj).join(','));
console.log('watch event - ', obj.event);
console.log('watch event - ', obj.base);
return;
if (obj.type === 'changed') {
gulp.src(obj.path, { base: './' })
.pipe(plumber({
errorHandler: function (error) { /* elided */ }
}))
.pipe(babel())
.pipe(rename(function (path) {
path.basename = path.basename.replace(/-es6$/, '');
}))
.pipe(gulp.dest(''))
.pipe(gprint(function(filePath){ return "File processed: " + filePath; }));
}
});
});
The output of the logging is this:
watch event - history,cwd,base,stat,_contents,event
watch event - change
watch event - ..
How do I get gulp-watch to give me the info I had before, or, how can I change my task's code to get this working again with gulp-watch?

According to the tests, obj.relative should contain the relative filename, and obj.path will still hold the absolute file path, just as it did in your original code. Also, the callback accepts a Vinyl object, which is documented here: https://github.com/wearefractal/vinyl
You probably can't see them in your logs since Object.keys doesn't enumerate properties in the prototype chain.
Using a for..in loop, you should be able to see all the properties.

Related

Gulp 4.0 version problem - parallel is not a function

I need help with my gulp project. Drops me error in terminal: TypeError: parallel is not a function Already searched information whole internet. Answer is to update Gulp version to 4.0.. Already updated. still shows the "parallel function" issue
My file:
const { src, dest, parallel, series, watch } = import('gulp');
const twig = import('gulp-twig');
const sass = import('gulp-sass');
const prefix = import('gulp-autoprefixer');
const data = import('gulp-data');
const sourcemaps = import('gulp-sourcemaps');
const concat = import('gulp-concat');
const plumber = import('gulp-plumber');
const browsersync = import('browser-sync');
const gulpcopy = import('gulp-copy');
const fs = import('fs');
const del = import('del');
const path = import('path');
var paths = {
build: {
html: 'dist/',
js: 'dist/assets/js/',
css: 'dist/assets/css/',
img: 'dist/assets/img/',
fonts: 'dist/assets/fonts/',
icons: 'dist/assets/icons/',
json: 'dist/assets/'
},
src: {
html: 'src/*.{htm,html,php}',
js: 'src/assets/js/*.js',
css: 'src/assets/sass/style.scss',
img: 'src/assets/img/**/*.*',
fonts: 'src/assets/fonts/**/*.*',
icons: 'src/assets/icons/**/*.*',
json: 'src/assets/*.json'
},
watch: {
html: 'src/**/*.{htm,html,php}',
js: 'src/assets/js/**/*.js',
css: 'src/assets/sass/**/*.scss',
img: 'src/assets/img/**/*.*',
fonts: 'src/assets/fonts/**/*.*',
icons: 'src/assets/icons/**/*.*',
json: 'src/assets/*.json'
},
clean: './dist'
};
// SCSS bundled into CSS task
function css() {
return src('client/scss/vendors/*.scss')
.pipe(sourcemaps.init())
// Stay live and reload on error
.pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
.pipe(sass({
includePaths: [paths.src.css + 'vendors/'],
outputStyle: 'compressed'
}).on('error', function (err) {
console.log(err.message);
// sass.logError
this.emit('end');
}))
.pipe(prefix(['last 15 versions','> 1%','ie 8','ie 7','iOS >= 9','Safari >= 9','Android >= 4.4','Opera >= 30'], {
cascade: true
}))
//.pipe(minifyCSS())
.pipe(concat('bootstrap.min.css'))
.pipe(sourcemaps.write('.'))
.pipe(dest('build/assets/css'));
}
// JS bundled into min.js task
function js() {
return src('dist/js/*.js')
.pipe(sourcemaps.init())
.pipe(concat('scripts.min.js'))
.pipe(sourcemaps.write('.'))
.pipe(dest('build/assets/js'));
}
function twigTpl () {
return src(['./dist/templates/*.twig'])
// Stay live and reload on error
.pipe(plumber({
handleError: function (err) {
console.log(err);
this.emit('end');
}
}))
// Load template pages json data
.pipe(data(function (file) {
return JSON.parse(fs.readFileSync(paths.data + path.basename(file.path) + '.json'));
}).on('error', function (err) {
process.stderr.write(err.message + '\n');
this.emit('end');
})
)
// Load default json data
.pipe(data(function () {
return JSON.parse(fs.readFileSync(paths.data + path.basename('default.twig.json')));
}).on('error', function (err) {
process.stderr.write(err.message + '\n');
this.emit('end');
})
)
// Twig compiled
.pipe(twig()
.on('error', function (err) {
process.stderr.write(err.message + '\n');
this.emit('end');
})
)
.pipe(dest(paths.build));
}
function copyAssets() {
// Copy assets
return src(['./dist/assets/**/*.*','!./dist/assets/**/*.psd','!./dist/assets/**/*.*.map'],
del(paths.build + 'assets/**/*')
)
.pipe(gulpcopy(paths.build + 'assets', { prefix: 2 }));
}
// BrowserSync
function browserSync() {
browsersync({
server: {
baseDir: paths.build
},
notify: false,
browser: "google chrome",
// proxy: "0.0.0.0:5000"
});
}
// BrowserSync reload
function browserReload () {
return browsersync.reload;
}
// Watch files
function watchFiles() {
// Watch SCSS changes
watch(paths.scss + '**/*.scss', parallel(css))
.on('change', browserReload());
// Watch javascripts changes
watch(paths.js + '*.js', parallel(js))
.on('change', browserReload());
// Watch template changes
watch(['dist/templates/**/*.twig','dist/data/*.twig.json'], parallel(twigTpl))
.on('change', browserReload());
// Assets Watch and copy to build in some file changes
watch('dist/assets/**/*')
.on('change', series(copyAssets, css, css_vendors, js, browserReload()));
}
const watching = parallel(watchFiles, browserSync);
exports.js = js;
exports.css = css;
exports.default = parallel(copyAssets, css, js, twigTpl);
exports.watch = watching;
My gulp version:
"node": "18.12.1"
"gulp": "^4.0.2",
On terminal when i write gulp -v it shows:
CLI version: 2.3.0
Local version: 4.0.2
Expecting professional help
Since your gulpfile is a CommonJS module, use require instead of import:
const { src, dest, parallel, series, watch } = require('gulp');
const twig = require('gulp-twig');
const sass = require('gulp-sass');
const prefix = require('gulp-autoprefixer');
const data = require('gulp-data');
const sourcemaps = require('gulp-sourcemaps');
const concat = require('gulp-concat');
const plumber = require('gulp-plumber');
const browsersync = require('browser-sync');
const gulpcopy = require('gulp-copy');
const fs = require('fs');
const del = require('del');
const path = require('path');
Using an ESM style gulpfile is also an option, but it's not as simple as just replacing require with import (btw the syntax is import sass from 'gulp-sass';...), you will also need to rename the file to "gulpfile.mjs", change the style of your exports, and probably more.

How to use fs.createReadStream() in sync without call back

I am planning to copy a file content from the zip and place the binary contents in another file. which will be used when I require a package.
example:-
func_name(CURRENT_DIR);
const MainController = require('./src/controllers/mainController');
// This mainController file will require the binary file which is create the func_name function
controller = new MainController(
context,
db2ConnectOutputChannel,
undefined /*vscodeWrapper*/
);
context.subscriptions.push(controller);
controller.activate();
func_name defination
var odbcBindingsNode;
var ODBC_BINDINGS = path.resolve(CURRENT_DIR, 'node_modules\/ibm_db\/build\/Release\/odbc_bindings.node');
odbcBindingsNode = 'build\/Release\/odbc_bindings_e' + electron_version + '.node';
readStream = fs.createReadStream(BUILD_FILE);
readStream.pipe(unzipper.Parse())
.on('entry', function (entry) {
if(entry.path === odbcBindingsNode) {
entry.pipe(fstream.Writer(ODBC_BINDINGS));
} else {
entry.autodrain();
}
})
.on('error', function(e) {
console.log('Installation Failed! \n',e);
})
.on('finish', function() {
console.log("\n" +
"===================================\n"+
"installed successfully!\n"+
"===================================\n");
})
The problem is the first function will not wait till the second function completes. It moves to the next line and tries to require maincontroller file which requires this .node file and returns .node is not found.
But .node is created after the require is called. Is there a way to make it in sync?
I tried callback which returns that require cannot be used in callback.
CallBack Code:-
function akhil(CURRENT_DIR){
var BUILD_FILE = path.resolve(CURRENT_DIR, 'folder\/build.zip');
var odbcBindingsNode;
var ODBC_BINDINGS = path.resolve(CURRENT_DIR, 'folder\/build\/Release\/odbc_bindings.node');
odbcBindingsNode = 'build\/Release\/odbc_bindings_e' + electron_version + '.node'
readStream = fs.createReadStream(BUILD_FILE);
/*
* unzipper will parse the build.zip file content and
* then it will check for the odbcBindingsNode
* (node Binary), when it gets that binary file,
* fstream.Writer will write the same node binary
* but the name will be odbc_bindings.node, and the other
* binary files and build.zip will be discarded.
*/
readStream.pipe(unzipper.Parse())
.on('entry', function (entry) {
if(entry.path === odbcBindingsNode) {
entry.pipe(fstream.Writer(ODBC_BINDINGS));
} else {
entry.autodrain();
}
})
.on('error', function(e) {
console.log('Installation Failed! \n',e);
})
.on('finish', function() {
console.log("\n" +
"===================================\n"+
"installed successfully!\n"+
"===================================\n");
console.log("This is rebuild");
const MainController = require('./src/controllers/mainController');
controller = new MainController(
context,
db2ConnectOutputChannel,
undefined /*vscodeWrapper*/
);
context.subscriptions.push(controller);
controller.activate();
})
return 1;
}
Using the ADM-zip package I was able to solve this issue.

Gulp 4 - Error: write after end

I'm getting an error when I watch for changes in index.html (full path in CONFIG.APP.INDEX). All my tasks are in separate files. this is tasks/watch.ts, for example:
import * as CONFIG from '../config';
export default done => {
// other watches
gulp.watch(CONFIG.APP.INDEX, gulp.series('inject'));
};
on first change task is executed normally, but on second change I'm getting this error:
c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:203
var er = new Error('write after end');
^
Error: write after end
at writeAfterEnd (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:203:12)
at DestroyableTransform.Writable.write (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_writable.js:239:20)
at DestroyableTransform.ondata (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:531:20)
at emitOne (events.js:77:13)
at DestroyableTransform.emit (events.js:169:7)
at readableAddChunk (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:198:18)
at DestroyableTransform.Readable.push (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_readable.js:157:10)
at DestroyableTransform.Transform.push (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:123:32)
at afterTransform (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:79:51)
at TransformState.afterTransform (c:\~\node_modules\through2\node_modules\readable-stream\lib\_stream_transform.js:58:12)
at c:\~\node_modules\vinyl-fs\lib\src\getContents\bufferFile.js:18:5
at c:\~\node_modules\graceful-fs\graceful-fs.js:78:16
at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:404:3)
tasks/inject.ts task:
declare var require;
const gulp = require('gulp');
const plugins = require('gulp-load-plugins')();
import * as CONFIG from '../config';
export default done => {
return gulp
.src(CONFIG.APP.INDEX)
.pipe(require('../util/inject/fixes').default) // <--- PROBLEM IS HERE
// other stuff...
.pipe(gulp.dest(CONFIG.DST.BUILD))
.on('error', plugins.util.log);
};
util/inject/fixes.ts task
declare var require;
const plugins = require('gulp-load-plugins')();
// errors even with this...
export default plugins.util.noop();
Tasks are loaded from gulpfile.ts/index.ts like this:
fs.readdirSync('./gulpfile.ts/tasks').map(file => {
let name = file.replace(/\.ts$/, '');
let task = require(path.join(path.resolve('.'), 'gulpfile.ts', 'tasks', file));
gulp.task(name, task.default);
});
I've managed to identify where the error comes from, but no idea what's causing it, or how to fix it. Problem only occurs when watching index.html after first change and task execution. Running task manually works normally (gulp inject), and all other watches and tasks work normally.
I suspect that your implementation of fixes.ts is reusing the same noop() result instead of recreating the result each time the task is run.
Try converting the fixes.ts to return a factory function that will return a new noop instance each time the task is invoked.
util/inject/fixes.ts:
declare var require;
const plugins = require('gulp-load-plugins')();
// Return a function that will return a new `noop` instance each time:
export default () => {
return plugins.util.noop();
};
For context, I just had a similar problem in my project where I was accidentally reusing a gulp stream and getting the "write after end" error.
I suspect your code is doing the same sort of thing with the noop() result because that one value will be cached as the value of that module.
Incorrect version of my gulpfile.js - the result of my gulp.dest() calls was being reused each time.
let gulp = require('gulp');
let merge = require('merge-stream');
let _path = require('path');
let files = {
'html': {
src: _path.join('public', 'index.html'),
dest: gulp.dest('public') // <-- WRONG use of `gulp.dest()`, causes result to be reused and gives "write after end" error
},
'files': 'html': {
src: _path.join('files', '*'),
dest: gulp.dest('files') // <-- WRONG use of`gulp.dest()`
},
};
gulp.task('copy', function(){
let html = gulp.src(files.html.src)
.pipe(files.html.dest); // <-- `gulp.dest()` should be here
let files = gulp.src(files.files.src)
.pipe(files.files.dest); // <-- `gulp.dest()` should be here
return merge(html, files);
});
gulp.task('copy-watch', function(){
let srcList = Object.keys(files).map(i => files[i].src);
gulp.watch(srcList, ['copy']);
});
Fixed version of my gulpfile.js - gulp.dest() is being called each time the task is run:
let files = {
'html': {
src: _path.join('public', 'index.html'),
dest: 'public' // <-- removed `gulp.dest()` call from here
},
'files': 'html': {
src: _path.join('files', '*'),
dest: 'files' // <-- removed `gulp.dest()` call from here
},
};
gulp.task('copy', function(){
let html = gulp.src(files.html.src)
.pipe(gulp.dest(files.html.dest)); // <-- CORRECT use of`gulp.dest()`
let files = gulp.src(files.files.src)
.pipe(gulp.dest(files.files.dest)); // <-- CORRECT use of `gulp.dest()`
return merge(html, files);
});

How to load contents of an external file into gulp browser-sync

I am loading browser-sync proxy and want to load search and replace terms from an external file in order to amend the page as it is loaded into a browser.
The reason I want to load the search and replace terms from a separate file is because I want to make use of gulp-watch and reload browser-sync as the search and replace terms are updated.
My Project folder:
regex/search.txt <- search term is stored in this file
regex/replace.txt <- replace term is stored in this file
gulpfile.js
Contents of gulpfile.js:
var gulp = require('gulp'),
fs = require("fs"),
browserSync = require('browser-sync');
var proj_url = "http://www.example.com";
var search_text = "";
var replace_text = "";
gulp.task('readRegEx', function() {
return gulp.src('regex/*.txt')
.pipe(fs.readFile("regex/search.txt", "utf-8", function(err, data) {
search_text = data;
}))
.pipe(fs.readFile("regex/replace.txt", "utf-8", function(err, data) {
replace_text = data;
}))
});
gulp.task('browser-sync', function() {
browserSync({
proxy: {
target: proj_url
},
rewriteRules: [
{
match: search_text,
fn: function (match) {
return replace_text;
}
}
]
});
});
gulp.task('default', ['readRegEx','browser-sync'], function() {
gulp.watch(['regex/*.txt'], [browserSync.reload]);
});
This doesn't work. I get the following error:
TypeError: Cannot call method 'on' of undefined ...
For that to work you need to make browser-sync dependant in readRegEx
gulp.task('browser-sync', ['readRegEx'], function() {
this guarantees the proper execution order.
then you can make readRegEx sync (and simpler) this way:
gulp.task('readRegEx', function() {
search_text = fs.readFileSync("regex/search.txt", "utf-8").toString();
replace_text = fs.readFileSync("regex/replace.txt", "utf-8").toString();
});

Gulp stops watching

I'm using gulp to watch certain files and run certain tasks however after the first few runs it seems to stop watching. If I save html files in the pages directory, after the first two to five updates, the templates task seems to stop running. I've included my gulpfile below.
// Include gulp
var gulp = require('gulp');
// Include plugins
var jshint = require('gulp-jshint');
var sass = require('gulp-sass');
var notify = require('gulp-notify')
var htmlv = require('gulp-html-validator')
var swig = require('gulp-swig');
var plumber = require('gulp-plumber');
// Linting
gulp.task('lint', function() {
return gulp.src('js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
gulp.task('sass', function() {
return gulp.src('./resources/scss/*.scss')
.pipe(sass()
.on('error', notify.onError(function(error) {
return 'Error: ' + error.message;
}))
)
.pipe(gulp.dest('./css'));
});
gulp.task('validate', function() {
return gulp.src('./**.html')
.pipe(htmlv({format: 'xhtml'}))
.pipe(gulp.dest('./validation_out'));
});
gulp.task('watch', function() {
gulp.watch('js/*.js', ['lint']);
gulp.watch('./resources/scss/*.scss', ['sass']);
gulp.watch('./pages/*.html', ['templates']);
});
gulp.task('templates', function() {
return gulp.src('./pages/*.html')
.pipe(swig({
load_json: true,
defaults: {
cache: false
}
}
))
.pipe(gulp.dest('.'));
});
gulp.task('default', ['lint', 'sass', 'templates', 'watch']);

Resources