Part of my gulpfile.js
const del = require('del');
const chrome_dir = 'build/chrome';
const ff_dir = 'build/firefox';
gulp.task('clean', function (cb) {
del([chrome_dir, ff_dir], cb);
});
gulp.task('default', ['clean'], function () {
gulp.start('build packages', 'JS Backend', 'i18n', 'ExtRes', 'styles', 'JS Content', 'templates');
});
worked well.
Then I installed a new system and there maybe got new versions of gulp and del and whatever.
Now gulp stops after cleaning.
I can call all tasks manually, that's working fine.
Could only be a change in the behaviour of del...
How can I fix this?
One of the most important changes on v2 is that now it returns a Promise instead of using a callback to handle async. From del documentation.
You simply have to re-write this part of your code:
gulp.task('clean', function (cb) {
del([chrome_dir, ff_dir], cb);
});
like this:
gulp.task('clean', function () {
return del([chrome_dir, ff_dir]);
});
Related
I'm refactoring my gulpfile now I'm using gulp v4 and am having an issue with gulp watch not running my stylesCompileIncremental function. Any help or pointers would be much appreciated.
My refactoring includes:
Switching to using functions instead of gulp.task
Using series and parallel as per the docs
Exporting public tasks at the bottom of my gulpfile ie exports.stylesWatch = stylesWatch;
Adding callbacks in functions to tell Gulp the function is complete
The code for the affected tasks is as follows (directory paths are stored in package.json file hence pathConfig.ui... values):
// Compile only particular Sass file that has import of changed file
function stylesCompileIncremental(cb) {
sassCompile({
source: getResultedFilesList(changedFilePath),
dest: pathConfig.ui.core.sass.dest,
alsoSearchIn: [pathConfig.ui.lib.resources]
});
cb();
}
// Compile all Sass files and watch for changes
function stylesWatch(cb) {
createImportsGraph();
var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel(devServReloadStyles));
watcher.on('change', function(event) {
changedFilePath = event;
});
cb();
}
// reload css separated into own function. No callback needed as returning event stream
function reloadCss() {
return gulp.src(generateFilePath)
.pipe($.connect.reload()); // css only reload
}
function devServReloadStyles(cb) {
gulp.series(stylesCompileIncremental, reloadCss);
cb();
}
When I run gulp stylesWatch using my refactored code I get the below output (notice the stylesCompileIncremental task is not run):
So my watch tasking is successfully running but there's something wrong when the devServReloadStyles is run for the stylesCompileIncremental function to not kick in.
The original code before refactoring (when using gulp v3) is below:
// Compile only particular Sass file that has import of changed file
gulp.task('styles:compile:incremental', () => {
return sassCompile({
source: getResultedFilesList(changedFilePath),
dest: pathConfig.ui.core.sass.dest,
alsoSearchIn: [pathConfig.ui.lib.resources]
});
});
// Compile all Sass files and watch for changes
gulp.task('styles:watch', () => {
createImportsGraph();
gulp.watch(
pathConfig.ui.core.sass.src + '**/*.scss',
['devServ:reload:styles']
).on('change', event => changedFilePath = event.path);
});
// Reload the CSS links right after 'styles:compile:incremental' task is returned
gulp.task('devServ:reload:styles', ['styles:compile:incremental'], () => {
return gulp.src(generateFilePath) // css only reload
.pipe($.connect.reload());
});
The original task output when running styles:watch is this:
And this is the sassCompile variable used inside stylesCompileIncremental which I've currently not changed in anyway.
/**
* Configurable Sass compilation
* #param {Object} config
*/
const sassCompile = config => {
const sass = require('gulp-sass');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const postProcessors = [
autoprefixer({
flexbox: 'no-2009'
})
];
return gulp.src(config.source)
.pipe($.sourcemaps.init({
loadMaps: true,
largeFile: true
}))
.pipe(sass({
includePaths: config.alsoSearchIn,
sourceMap: false,
outputStyle: 'compressed',
indentType: 'tab',
indentWidth: '1',
linefeed: 'lf',
precision: 10,
errLogToConsole: true
}))
.on('error', function (error) {
$.util.log('\x07');
$.util.log(error.message);
this.emit('end');
})
.pipe(postcss(postProcessors))
.pipe($.sourcemaps.write('.'))
.pipe(gulp.dest(config.dest));
};
UPDATE
This is due to an issue with my devServReloadStyles function, although I'm still unsure why. If I change my stylesWatch function to use the original devServ:reload:styles task stylesCompileIncremental gets run.
// Compile all Sass files and watch for changes
function stylesWatch(cb) {
createImportsGraph();
var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel('devServ:reload:styles'));
watcher.on('change', function(event) {
changedFilePath = event;
});
cb();
}
It would still be good to not use the old task and have this as a function though.
Can anybody tell me why my refactored version doesn't work and have any suggestions as to how this should look?
I've fixed this now.
gulp.series and gulp.parallel return functions so there was no need to wrap stylesCompileIncremental and reloadCss inside another function ie. devServReloadStyles.
As per Blaine's comment here.
So my function:
function devServReloadStyles(cb) {
gulp.series(stylesCompileIncremental, reloadCss);
cb();
}
Can just be assigned to a variable:
const devServReloadStyles = gulp.series(stylesCompileIncremental, reloadCss);
And my stylesWatch task is already calling devServReloadStyles:
// Compile all Sass files and watch for changes
function stylesWatch(cb) {
createImportsGraph();
var watcher = gulp.watch(pathConfig.ui.core.sass.src + '**/*.scss', gulp.parallel(devServReloadStyles));
watcher.on('change', function(event) {
changedFilePath = event;
});
cb();
}
So running gulp stylesWatch now runs the stylesCompileIncremental job (notice how devServReloadStyles doesn't show as it's not a function).
I'm bundling my javascript files using the task runner gulp js, during the development of an application I'm noticing a certain issue.
When I add the new feature(reveal a password) script refuses to work because of the form modal script which can be seen below.
'use strict';
var modal__button = document.getElementById("enquiry-form-trigger");
var close__button = document.getElementById("close");
modal__button.addEventListener("click", function (){
var modal = document.getElementById("modal-form");
modal.classList.add("fadeIn");
modal.style.visibility = "visible";
});
close__button.addEventListener("click", function (){
var modal = document.getElementById("modal-form");
modal.classList.remove("fadeIn");
modal.style.visibility = "hidden";
});
When the above script and this other script below
"use strict"
document.getElementById("password-reveal-modal").addEventListener("click", function (){
var x = document.getElementById("password-modal");
if (x.type === "password") {
x.type = "text";
} else {
x.type = "password";
}
});
The password reveal feature doesn't work, but when I paste it in chrome's dev tools works perfectly.
I'm not sure why it wont work without pasting it into the dev tools, it's baffling me, I'm not sure if its my setup or if its the custom javascript.
This is my gulp file setup in case anyone wants to check it, I don't see an issue but Ive only been using gulp for about 3 or 4 months.
var gulp = require("gulp"),
sass = require("gulp-sass"),
image = require("gulp-image"),
concat = require("gulp-concat"),
browserSync = require('browser-sync').create(),
reload = browserSync.reload,
minifyEjs = require("gulp-minify-ejs"),
stripEJSComments = require('gulp-strip-comments'),
nodemon = require('gulp-nodemon'),
plumber = require("gulp-plumber"),
ejs = require("ejs"),
uglify = require("gulp-uglify");
//Build task
gulp.task("build", ["ejs", "styles", "images", "javascript", "routes", "models", "middleware"], function () {
console.log("Build Success");
});
//start up sequence tasks
gulp.task('init', ["nodemon"], function () {
browserSync.init({
proxy: 'http://localhost:2000', //Index.js port number
port: 2128, // The port browser sync runs on
serveStatic: [ './public/', "./assets/"], // What files browser sync should have access to
reloadOnRestart: true, // Enable auto reload
ghostMode:false, //Stops session mirroring
open: "external", //Opens up on an external address (xxx.xxx.x.xx:3128)
});
});
//Starts the express server
gulp.task('nodemon', function (done) {
var running = false; //Default State
return nodemon({
script: 'index.js', //Index file for the JS project
watch: ["./assets/", "./public/"] //What nodemon has access to
})
.on('start', function () {
if (!running) {
done();
}
running = true;
})
//Minor Delay Of 500ms Upon Restart
.on('restart', function () {
setTimeout(function () {
reload();
}, 500);
});
});
//SCSS Task
gulp.task("styles", function () {
gulp.src("./assets/stylesheet/APP.scss")
.pipe(plumber())
.pipe(sass({
outputStyle: 'compressed'
}))
.pipe(gulp.dest("./public/stylesheet/"))
.pipe(browserSync.stream({ stream: true }));
});
//Compiles the express route/s
gulp.task("routes", function () {
gulp.src([
"./assets/routes/*.js"
])
.pipe(plumber())
.pipe(gulp.dest("./public/routes/"))
.pipe(browserSync.stream({ stream: true }));
});
//Compiles the express route/s
gulp.task("models", function () {
gulp.src("./assets/models/*.js")
.pipe(plumber())
.pipe(gulp.dest("./public/models/"))
.pipe(browserSync.stream({ stream: true }));
});
//Image minification
gulp.task("images", function () {
return gulp.src("./assets/images/*")
.pipe(image())
.pipe(gulp.dest("./public/images"))
.pipe(browserSync.stream({ stream: true }));
});
//Client javascript
gulp.task("javascript", function () {
gulp.src([
"./node_modules/jquery/dist/jquery.js",
"./node_modules/tether/dist/js/tether.js",
"./node_modules/bootstrap/dist/js/bootstrap.js",
"./assets/scripts/**/**/*.js"
])
.pipe(plumber())
.pipe(concat("main.js"))
.pipe(gulp.dest("./public/scripts/"))
.pipe(browserSync.stream({ stream: true }));
});
//Middleware task
gulp.task("middleware", function () {
gulp.src("./assets/middleware/*.js")
.pipe(plumber())
.pipe(concat("index.js"))
.pipe(gulp.dest("./public/middleware/"))
.pipe(browserSync.stream({ stream: true }));
});
//EJS task
gulp.task("ejs", function () {
gulp.src("./assets/views/**/*.ejs")
.pipe(plumber())
.pipe(stripEJSComments())
.pipe(minifyEjs({}))
.pipe(gulp.dest("./public/views"))
.pipe(browserSync.stream({ stream: true }));
});
//Default task array
gulp.task("default", ["init", "build"], function (done) {
gulp.watch("./assets/stylesheet/**/*.scss", ["styles"]);
gulp.watch("./assets/scripts/*", ["javascript"]);
gulp.watch("./assets/routes/*.js", ["routes"]);
gulp.watch("./assets/models/*.js",["models"]);
gulp.watch("./assets/images/*",["images"]);
gulp.watch("./assets/views/**/*.ejs",["ejs"]);
browserSync.reload();
done();
});
The two files which are causing the issue are the only files as I have tested each files and its only these two files weirdly so something is causing it to clash.
If you want me to upload my project to github just let me know and I will upload the latest version to my update branch.
I have exhausted all my knowledge into this problem and I am completely stuck now.
If anyone could help a fellow developer out it would be greatly appreciated.
cheers,
alex
I needed to ensure the DOM had fully loaded before the script could be executed.
Inside my gulpfile I have the following task, where I would like to log the changed file's name:
gulp.task('watch', function() {
var stylesWatcher = gulp.watch(resolvePath(paths().source.scss) + '/**/*.scss', { awaitWriteFinish: true });
stylesWatcher.on('change', gulp.series('styles', function(cb) {
// Log filename here
cb();
}));
});
Keep in mind that 'styles' is a gulp task.
I have tried to log it in multiple ways, i.e. using function(path, stats) instead of function(cb), like it's shown in the gulp 4 documentation.
An example of a result I get when I console.log the path while using the path and stats parameters like in the docs is:
function done() {
d.removeListener('error', onError);
d.exit();
return cb.apply(null, arguments);
}
When I remove the 'styles' and the gulp.series though and just leave a function like this:
stylesWatcher.on('change', function(path, stats) {
console.log(path);
});
The path is indeed logged in the console.
Is there any way to console log the path when using gulp.series?
I'm trying to use gulp-inject but something is not syncing up properly. I think it has to do with my cleaning task.
gulp.task("clean", function () {
return gulp.src([
"tmp/client/**/*",
"wwwroot/**/*.css",
"wwwroot/**/*.js"
], { read: false })
.pipe(plumber())
.pipe(clean());
});
This runs before my compile tasks, such as:
gulp.task("dev:tsc", ["clean"], function () {
return tsResult.js
.pipe(sourceMaps.write("."))
.pipe(gulp.dest("wwwroot/js"));
});
Then all my compile steps run before a build task:
function injectTask(assets) {
var layout = gulp.src("Views/Shared/_Layout.cshtml");
var sources = gulp.src(assets, { read: false });
return layout.pipe(inject(sources, {
ignorePath: "wwwroot",
addPrefix: "~",
addRootSlash: false
})).pipe(gulp.dest("Views/Shared"));
}
gulp.task("dev:build", ["dev:tsc", "...other tasks..."], function () {
var vendorSources = vendorConfig.map(function (vendor) {
return ["wwwroot/js", vendor.srcFile].join("/");
});
return injectTask(vendorSources.concat([
"wwwroot/css/*.css",
"wwwroot/js/*.js"
]));
});
Sometimes all my files get injected, sometimes some are missing. Sometimes I get an error about a file missing. I suspect I'm missing some step to correctly declare dependencies on the streams and prevent them from overlapping, I just can't see what it is. The complete gulpfile is here. Any ideas?
I have a generator-generator app with its own local sub-generator app. The situation is that I want the sub-generator to invoke atleast once with pre-defined argument when I run the main 'app' generator. Everything works fine except the npm test fails.
Main 'app' generator: yo mygen.
Sub generator: yo mygen:foo "lorem ipsum".
Here is the test.js
/*global describe, beforeEach, it*/
'use strict';
var path = require('path'),
yg = require('yeoman-generator');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-assert');
describe(' running `yo mygen`', function () {
before(function (done) {
var deps = [
[helpers.createDummyGenerator(), 'mygen:foo', 'blah blah blah']
];
helpers.run(path.join(__dirname, '../app'))
.inDir(path.join(__dirname, './temp')) // Clear the directory and set it as the CWD
.withOptions({ mongoose: 'app', 'skip-install': true }) // Mock options passed in
.withPrompts({
'dbName': 'demo',
'useUserAuth': false
})
.withGenerators(deps)
.on('end', done);
//done();
});
it('can be imported without blowing up', function () {
var app = require('../app');
assert(app !== undefined);
});
it('creates all required MVC files', function (done) {
var expected = [
// add files you expect to exist here.
'package.json',
'app.js',
'bower.json',
'routes/index.js',
'public/css/style.css',
'public/js/script.js',
'views/index.html',
'README.md',
'.editorconfig',
'.jshintrc'
];
assert.file(expected);
done();
});
});
describe('í ¼ running `yo mygen:foo`', function () {
before(function (done) {
helpers.run(path.join(__dirname, '../schema'))
.inDir(path.join(__dirname, './temp')) // Clear the directory and set it as the CWD
.withOptions({ mongoose: 'schema' }) // Mock options passed in
.withArguments(['ha ha ha ha hha'])
.on('end', done);
//done();
});
describe('foo generator', function () {
it('foo can be imported without blowing up', function () {
var app = require('../foo');
assert(app !== undefined);
});
it('created new MVC files for foo', function (done) {
var expected = [
// add files you expect to exist here.
'view/t1.js',
'models/t1.js',
'controller/t1.js'
];
assert.file(expected);
done();
})
});
});
And in app/index.js, in order to invoke the sub-generator, i have used:
mygenGenerator.prototype.install = function install(){
this.installDependencies();
this.composeWith("mygen:foo", {args: ["humpty dumpty saton a wall"]});
};
Searched all possible answers on stackoverflow and everywhere else. Can't figure out what to do.
Test Cases for npm test fails:
Remove the composeWith line from index.js and the test passes.
keep the composeWith line, the test goes to infinity, eventually exceed 2000ms quota and failing.