Gulp + Browserify + Globs - javascript

I am using the recipe from the official gulp repo, to make browserify work for multiple entry points. It worked out fine, when I followed the recipe for a single file, but when I try to run the task now, it prints
the following tasks did not complete: browserify.
Did you forget to signal async completion?
Unfortunately. I am using Gulp 4 for this. This is my adapted task:
gulp.task('browserify', function() {
var bundledStream = through();
bundledStream.pipe(source('./public/static/js-dev/bundles/*.js'))
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.on('error', gutil.log)
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(local.jsDist+'/bundles'));
globby(['./public/static/js-dev/bundles/*.js'], function(err, entries) {
if (err) {
bundledStream.emit('error', err);
return;
}
var b = browserify({
entries: entries,
debug: true
});
b.bundle().pipe(bundledStream);
});
return bundledStream;
});
I don't know what I am doing wrong - I just want this to work.

You need to callback the task zo add done to the function as argument and call it at last in your function as done();

Related

Gulp4 - tasks did not complete and forget to signal async completion

Just started learning gulp and followed this tutorial series:https://www.youtube.com/watch?v=oRoy1fJbMls&list=PLriKzYyLb28lp0z-OMB5EYh0OHaKe91RV
It works perfectly on gulp 3 but after updating npm to the current version it broke down and i tried converting my gulpfile.js from version 3 to 4, and after running the gulp command i have this error:
The following tasks did not complete: default, Did you forget to signal async completion? How do i solve this?
Here's my gulpfile:
const gulp = require('gulp');
const rename = require('gulp-rename');
const sass = require('gulp-sass');
const uglify = require('gulp-uglify');
const autoprefixer = require('gulp-autoprefixer');
const sourcemaps = require('gulp-sourcemaps');
const browserify = require('browserify');
const babelify = require('babelify');
const source = require('vinyl-source-stream');
const buffer = require('vinyl-buffer');
let styleSource = 'src/scss/style.scss';
let styleDestination = './build/css/';
let styleWatch = 'src/scss/**/*.scss';
let jsSource = 'main.js';
let jsFolder = 'src/js/';
let jsDestination = './build/js/';
let jsWatch = 'src/js/**/*.js';
let jsFILES = [jsSource];
let htmlWatch = '**/*.html';
/* Converting Sass to CSS */
gulp.task('styles',function(){
return gulp.src(styleSource)
.pipe(sourcemaps.init())
.pipe(sass({
errorLogToConsole: true,
outputStyle: 'compressed'
}))
.on('error', console.error.bind(console))
.pipe(autoprefixer({
browsers: ['last 2 versions'],
cascade: false
}))
.pipe(rename({suffix:'.min'}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(styleDestination));
});
/* Converting ES6 to Vanilla JS */
gulp.task('js',function(){
return jsFILES.map(function(entry){
return browserify({
entries: [`${jsFolder}${entry}`]
})
.transform(babelify, {presets:['env']})
.bundle()
.pipe(source(entry))
.pipe( rename({extname:'.min.js'}) )
.pipe(buffer())
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(jsDestination))
});
})
// default task to run all tasks
const compile = gulp.parallel(['styles','js']);
compile.description = 'Compile all styles and js files';
gulp.task('default', compile);
// watch default
const watch = gulp.series('default', function(){ // ,'browser-sync'
// keep running, watching and triggering gulp
gulp.watch(styleWatch, gulp.parallel('styles')); //, reload
gulp.watch(jsWatch, gulp.parallel('js')); //, reload
gulp.watch(htmlWatch);
});
watch.description = 'watch all changes in every files and folders';
gulp.task('watch', watch);
And here's the error after i run gulp:
Your js task returns an array, gulp doesn't understand that. A task can return a stream or a promise - or it must call the callback parameter to signal completion, like so:
gulp.task('js', function(cb) {
// Your js task code here
cb();
})
Also, read the latest gulp4 documentation.

gulp-ruby-sass Error: must provide pattern

This is my directory structure:
I set up my workstation, and I set up my Gulp File to work on my folder format, but it is not working properly.
This is my Gulp File:
var gulp = require('gulp'),
sass = require('gulp-ruby-sass'),
imagemin = require('gulp-imagemin'),
changed = require('gulp-changed'),
browserSync = require('browser-sync'),
livereload = require('gulp-livereload'),
gp_concat = require('gulp-concat'),
gp_rename = require('gulp-rename'),
gp_uglify = require('gulp-uglify'),
watch = require('gulp-watch');
gulp.task('sass', function () {
gulp.src('./app/template/css/style_v1.scss')
.pipe(sass())
.on('error', function (err) { console.log(err.message); })
.pipe(gulp.dest('./dist/css'))
.pipe(livereload());
});
gulp.task('compress', function() {
gulp.src('./app/*.js')
.pipe(gp_concat('concat.js'))
.pipe(gulp.dest('dist'))
.pipe(gp_rename('script.min.js'))
.pipe(gp_uglify())
.pipe(gulp.dest('./dist/js'));
});
gulp.task('jpg', function() {
gulp.src('./template/img/**/*.*')
.pipe(changed('./dist/img/'))
.pipe(imagemin({
progressive: true
}))
.pipe(gulp.dest('./dist/img/'));
});
gulp.task('browser-sync', function() {
browserSync.init(['./dist/css/**', 'index.php'], {
server: {
baseDir: './',
index: 'index.php'
}
});
});
gulp.task('watch', ['sass', 'browser-sync','compress'], function () {
return watch('./app/template/css/style_v1.scss', function () {
gulp.src('./app/template/css/style_v1.scss')
.pipe(gulp.dest('build'));
});
});
When I run gulp watch it returns this:
(node:6668) fs: re-evaluating native module sources is not supported. If you are using the graceful-fs module, please update it to a more recent version.
[08:42:23] Using gulpfile /var/www/html/evandro/sistema_metas/gulpfile.js
[08:42:23] Starting 'sass'...
[08:42:23] 'sass' errored after 7.09 ms
[08:42:23] Error: must provide pattern
What is the problem?
I have another code, the CSS Watch does not work, just watch HTML, What can it be?
gulp-ruby-sass works differently from other gulp plugins. You don't pass it to .pipe(). If you take a look at the documentation it says the following:
Use gulp-ruby-sass instead of gulp.src to compile Sass files.
That means you have to use it like this:
var sass = require('gulp-ruby-sass');
gulp.task('sass', function () {
return sass('./app/template/css/style_v1.scss')
.on('error', function (err) { console.log(err.message); })
.pipe(gulp.dest('./dist/css'))
.pipe(livereload());
});
Alternatively you can use the gulp-sass plugin instead of gulp-ruby-sass. It doesn't use the Ruby implementation of SASS, but rather the C implementation (libsass). It allows you to use .pipe() as you normally would for most other gulp plugins:
var sass = require('gulp-sass');
gulp.task('sass', function () {
return gulp.src('./app/template/css/style_v1.scss')
.pipe(sass())
.on('error', function (err) { console.log(err.message); })
.pipe(gulp.dest('./dist/css'))
.pipe(livereload());
});

Running a command with gulp to start Node.js server

So I am using gulp-exec (https://www.npmjs.com/package/gulp-exec) which after reading some of the documentation it mentions that if I want to just run a command I shouldn't use the plugin and make use of the code i've tried using below.
var exec = require('child_process').exec;
gulp.task('server', function (cb) {
exec('start server', function (err, stdout, stderr) {
.pipe(stdin(['node lib/app.js', 'mongod --dbpath ./data']))
console.log(stdout);
console.log(stderr);
cb(err);
});
})
I'm trying to get gulp to start my Node.js server and MongoDB. This is what i'm trying to accomplish. In my terminal window, its complaining about my
.pipe
However, I'm new to gulp and I thought that is how you pass through commands/tasks. Any help is appreciated, thank you.
gulp.task('server', function (cb) {
exec('node lib/app.js', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
exec('mongod --dbpath ./data', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
})
For future reference and if anyone else comes across this problem.
The above code fixed my problem. So basically, I found out that the above is its own function and therefore, doesn't need to:
.pipe
I thought that this code:
exec('start server', function (err, stdout, stderr) {
was the name of the task I am running however, it is actually what command I will be running. Therefore, I changed this to point to app.js which runs my server and did the same to point to my MongoDB.
EDIT
As #N1mr0d mentioned below with having no server output a better method to run your server would be to use nodemon. You can simply run nodemon server.js like you would run node server.js.
The below code snippet is what I use in my gulp task to run my server now using nodemon :
// start our server and listen for changes
gulp.task('server', function() {
// configure nodemon
nodemon({
// the script to run the app
script: 'server.js',
// this listens to changes in any of these files/routes and restarts the application
watch: ["server.js", "app.js", "routes/", 'public/*', 'public/*/**'],
ext: 'js'
// Below i'm using es6 arrow functions but you can remove the arrow and have it a normal .on('restart', function() { // then place your stuff in here }
}).on('restart', () => {
gulp.src('server.js')
// I've added notify, which displays a message on restart. Was more for me to test so you can remove this
.pipe(notify('Running the start tasks and stuff'));
});
});
Link to install Nodemon : https://www.npmjs.com/package/gulp-nodemon
This solution has stdout/stderr shown as they occur and does not use 3rd party libs:
var spawn = require('child_process').spawn;
gulp.task('serve', function() {
spawn('node', ['lib/app.js'], { stdio: 'inherit' });
});
You can also create gulp node server task runner like this:
gulp.task('server', (cb) => {
exec('node server.js', err => err);
});
If you want your console to output everything that the child process outputs, as well as pass to the child process all environment variables you already have set:
const exec = require('child_process').exec;
function runCommand(command, cb) {
const child = exec(command, { env: process.env }, function (err) {
cb(err);
})
child.stdout.on('data', (data) => {
process.stdout.write(data);
});
child.stderr.on('data', (data) => {
process.stdout.write(`Error: [${data}]`);
});
}
Note that both out and err write to stdout, this is intentional for my case but you can adapt to whatever you need.

Gulp less and then minify task

I have to make 2 steps in gulp:
Make a .css file form less
Minify generated css files
This is my gulpfile:
var gulp = require('gulp'),
watch = require("gulp-watch"),
less = require('gulp-less'),
cssmin = require('gulp-cssmin'),
rename = require('gulp-rename');
gulp.task('watch-less', function () {
watch({glob: './*.less'}, function (files) { // watch any changes on coffee files
gulp.start('compile-less'); // run the compile task
});
watch({
glob: ['./*.css', '!./*.min.css']
}, function(files) {
gulp.start('minify-css'); // run the compile task
});
});
gulp.task('compile-less', function () {
gulp.src('./*.less') // path to your file
.pipe(less().on('error', function(err) {
console.log(err);
}))
.pipe(gulp.dest('./'));
});
gulp.task('minify-css', function() {
gulp.src([
'./*.css',
'!./*.min.css'
])
.pipe(cssmin().on('error', function(err) {
console.log(err);
}))
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('./'));
})
gulp.task('default', ['watch-less']);
When i start it only first step is done.
Help me please.
You should keep in mind that with gulp you could simply chain operations on a glob pattern.
Don't really sure why you need gulp.watch when you can use the built-in watcher, this plugin is useful on tricky situations and that's don't seems be the case here, but you can stick with it if you really want to.
Don't forget to return your stream so gulp knows when a task is finished.
I also generally wrap all my watchers inside one watch task, not need to separate them.
To me, your gulpfile should look like this:
var gulp = require('gulp'),
less = require('gulp-less'),
cssmin = require('gulp-cssmin'),
rename = require('gulp-rename');
gulp.task('watch', function () {
gulp.watch('./*.less', ['less']);
});
gulp.task('less', function () {
return gulp.src('./*.less')
.pipe(less().on('error', function (err) {
console.log(err);
}))
.pipe(cssmin().on('error', function(err) {
console.log(err);
}))
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('./'));
});
gulp.task('default', ['less', 'watch']);
There is no needing after time, convinient solution for me was:
var gulp = require('gulp'),
less = require('gulp-less'),
cssmin = require('gulp-cssmin'),
plumber = require('gulp-plumber'),
rename = require('gulp-rename');
gulp.task('watch', function () {
gulp.watch('./styles/*.less', ['less']);
});
gulp.task('less', function () {
gulp.src('./styles/*.less')
.pipe(plumber())
.pipe(less())
.pipe(gulp.dest('./styles/'))
.pipe(cssmin())
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('./styles'))
});
gulp.task('default', ['less', 'watch']);
Best of both worlds might be to add the gulp.watch to the default gulp.task and if you require browser-sync it will reload when you make any changes to the folders being watched as shown below:
var gulp = require('gulp'),
less = require('gulp-less'),
cssmin = require('gulp-cssmin'),
rename = require('gulp-rename'),
browser = require('browser-sync');
gulp.task('less', function() {
return gulp.src('./*.less')
.pipe(less().on('error', function(err) {
console.log(err);
}))
.pipe(cssmin().on('error', function(err) {
console.log(err);
}))
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest('./'));
});
gulp.task('server', function() {
browser({
server: {
baseDir: './'
}
});
});
gulp.task('default', ['less', 'server'], function() {
gulp.watch('./*.less', ['less', browser.reload]);
});
This is the way I did it with sass. Kind of the same with less.
The difference with the previous answers is that I wanted one more step:
Get the sass
Transform it into a css and create the file
Get that file and minify it.
So the structure would be like this:
test.scss
test.css
test.min.css
var gulp = require("gulp"),
sass = require("gulp-sass"),
rename = require("gulp-rename");
var paths = {
webroot: "./wwwroot/"
};
paths.scss = paths.webroot + "css/**/*.scss";
gulp.task('sass', function() {
gulp.src(paths.scss)
.pipe(sass())
.pipe(gulp.dest(paths.webroot + "css"))
.pipe(cssmin())
.pipe(rename({
suffix: '.min'
}))
.pipe(gulp.dest(paths.webroot + "css"));
});
Added a new answer in case someone want the same thing as me.

Mongoose open connection issue with Supertest

I am unable to run multiple Supertest/Mocha tests as I get an error Error: Trying to open unclosed connection. - I found this post which suggest looping and checking connection status. Wondering if there is a better way? perhaps something that was added in Supertest recently to handle this.
In your Mocha tests add a before function to connect to MongoDB like so
var mongoose = require('mongoose');
describe('My test', function() {
before(function(done) {
if (mongoose.connection.db) return done();
mongoose.connect('mongodb://localhost/puan_test', done);
});
});
Ok - was pretty close. What I had to do was remove the describe method call and place a before() call in a common file to all tests - supertest or just straight mocha unit tests.
var db;
// Once before all tests - Supertest will have a connection from the app already while others may not
before(function(done) {
if (mongoose.connection.db) {
db = mongoose.connection;
return done();
}
db = mongoose.connect(config.db, done);
});
// and if I wanted to load fixtures before each test
beforeEach(function (done) {
fixtures.load(data, db, function(err) {
if (err) throw (err);
done();
})
});
By omitting the describe() call the above it makes it available to all tests.
// Also you can use the 'open' event to call the 'done' callback
// inside the 'before' Mocha hook.
before((done) => {
mongoose.connect('mongodb://localhost/test_db');
mongoose.connection
.once('open', () => {
done();
})
.on('error', (err) => {
console.warn('Problem connecting to mongo: ', error);
done();
});
});

Categories