Gulp - Watch multiple folders and output to relative dist folder - gulp

I want to use gulp to compile SASS for my custom Wordpress plugins.
All plugin folder share same folder structure:
wp-content/plugins/pluginname
assets
dist -
src - scss
GULP TASK
gulp.task('plugin-css', () => {
// Main SASS Style Sheet
const pluginSass = gulp.src(`wp-content/plugins/**/assets/src/*.scss`)
.pipe(plumber(plumberErrorHandler))
.pipe(sass());
// Merge the two streams and concatenate their contents into a single file
return merge(pluginSass)
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(gulp.dest(function(file) {
return file.base;
}));
});
Currently my compiled css file is being output into the same folder as the src sass. How can I output my compiled sass into 'dist' folder?

It is not clear to me what you are trying to do with the merges (so NOTE I simplified those out) but here is something that should help you get to putting your result into a dist folder where you want it to be:
var path = require('path');
var rename = require('gulp-rename');
gulp.task('default', function () {
const pluginSass = gulp.src("wp-content/plugins/**/assets/src/*.scss")
.pipe(sass())
// return merge(pluginSass)
.pipe(rename(function (file) {
var temp = path.dirname(file.dirname);
console.log('temp = ' + temp);
file.dirname = path.join(temp, "dist");
console.log("file.dirname = " + file.dirname);
}))
.pipe(cssmin())
// .pipe(autoprefixer())
.pipe(gulp.dest("wp-content/plugins"));
});
gulp-rename is useful for these situations and always seems to be easier to use that gulp.dest(function... path manipulation).

Pass the dist folder to the gulp.dest function.
const path = require('path')
return merge(pluginSass)
.pipe(autoprefixer())
.pipe(cssmin())
.pipe(gulp.dest(function (file) {
return path.join(file.base, './dist') // ← Put your folder path here
}));
See docs here: https://github.com/gulpjs/gulp/blob/master/docs/API.md#gulpdestpath-options

Related

Gulp webserver task and watch task not works together

Here I have a watch task that will create my build directory according to my src. My build directory will contain two main sub directories named debug and release. Watch task will look inside of my src directory(my working directory) and will transfer appropriate format of files inside the src into both release and debug directories. Now I also have a webserver task using gulp-webserver(live reloading) package in order to watching my index.html file inside my debug directory. My problem is that each task works independently, but I don't know how run them simultaneously. Here is what I've tried but it didn't work(just one of them will be start). Let me know if further information is needed.
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
.
.
.
var default_tasks = ['build', 'webserver', 'watch'];
gulp.task('default',gulp.series('clean',...default_tasks));
EDIT:
Here is my full gulpfile.js:
const gulp = require('gulp');
const uglify = require('gulp-uglify-es').default;
const sass = require('gulp-sass');
const del = require('del');
const webServer = require('gulp-webserver');
//-------------------------------------------------------------------------------------------------
const build_tasks=['js','js-min','sass','sass-min','cp','cp-min'];
const buildOptions={
releasePath:'build/release/',
debugPath:'build/debug/',
};
const pathJS = 'src/js/**/*.js'
const pathSCSS = 'src/style/**/*.scss'
//-------------------------------------------------------------------------------------------------
// JavaScript Task
gulp.task('js',()=>{
return gulp.src([pathJS])
.pipe(gulp.dest(buildOptions.debugPath+'/js/'));
});
gulp.task('js-min',()=>{
return gulp.src([pathJS])
.pipe(uglify().on('error',uglify=>console.error(uglify.message)))
.pipe(gulp.dest(buildOptions.releasePath+'/js/'));
})
// sass Task
gulp.task('sass',()=>{
return gulp.src([pathSCSS])
.pipe(sass().on('error',sass.logError))
.pipe(gulp.dest(buildOptions.debugPath+'/style/'));
});
gulp.task('sass-min',()=>{
return gulp.src([pathSCSS])
.pipe(sass({outputStyle: 'compressed'}).on('error',sass.logError))
.pipe(gulp.dest(buildOptions.releasePath+'/style/'))
})
// copy files
gulp.task('cp',()=>{
return gulp.src(['src/**/*.*','!'+pathJS,'!'+pathSCSS])
.pipe(gulp.dest(buildOptions.debugPath));
});
gulp.task('cp-min',()=>{
return gulp.src(['src/**/*.*','!'+pathJS,'!'+pathSCSS])
.pipe(gulp.dest(buildOptions.releasePath));
});
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
//-------------------------------------------------------------------------------------------------
gulp.task('clean',function(){return del(['build']);});
gulp.task('build',gulp.parallel(...build_tasks));
//-------------------------------------------------------------------------------------------------
function build(){
var default_tasks = ['build', 'webserver', 'watch'];
//var default_tasks = ['build', 'watch'];
gulp.task('default',gulp.series('clean',...default_tasks));
}
build();
I solve my problem by using gulp.parallel for both webserver and watch tasks :
// watch
gulp.task('watch',()=>{
gulp.watch(pathJS,gulp.series('js','js-min'));
gulp.watch(pathSCSS,gulp.series('sass','sass-min'));
gulp.watch(['src/**/*.*','!'+pathJS,'!'+pathSCSS],gulp.series('cp','cp-min'));
});
// webserver
gulp.task('webserver',()=>{
gulp.src(buildOptions.debugPath)
.pipe(webServer({
fallback: 'index.html',
port:'4000',
livereload:true,
open:true
}))
});
.
.
.
gulp.task('default',gulp.series('clean','build',gulp.parallel('webserver', 'watch')));//Here is my change!

Gulp: only compile changed files AND compile parents when imported SCSS file is edited

At work we used to use Ruby to compile SCSS. I had the Ruby compiler set up as a file watcher in PhpStorm, and when I edited a partial imported by another file, the CSS file corresponding to the ancestor file was updated without any fuss.
I want to get Gulp and Libsass to work the same way. Most solutions I've seen just compile all the SCSS files in a project when a single one changes, but our projects have way too much SCSS for that to be an acceptable solution.
gulp-cached seemed like a great solution to this problem. But when I use gulp-cached the CSS output file doesn't change when I edit partials, only their ancestor SCSS files.
I've seen a few SCSS dependency-graph solutions thrown around but I can't get them to work correctly or they simply don't do what I need. I've tried gulp-sass-graph, gulp-sass-inheritance, and gulp-sass-partials-imported.
Here's my gulp file
const gulp = require('gulp');
const glob = require('glob');
const sass = require('gulp-sass');
const sourcemaps = require('gulp-sourcemaps');
const cached = require('gulp-cached');
const sassGraph = require('gulp-sass-graph');
const sassGlobs = [
'./sites/all/libraries/gl/**/*.scss',
'./sites/all/modules/custom/**/*.scss',
'./sites/all/themes/{bcp_bootstrap3,gl_parent,gl_shiny,gli_bootstrap3,pru_bootstrap3,pru_bootstrap3v2,ubc_bootstrap3}/**/*.scss',
];
let sassPaths = [];
for (let j = 0; j < sassGlobs.length; ++j) {
glob(sassGlobs[j], function (er, files) {
let path;
for (let i = 0; i < files.length; ++i) {
path = files[i].substring(0, files[i].lastIndexOf('/'), '');
if (sassPaths.indexOf(path) === -1) {
sassPaths.push(path);
}
}
});
}
gulp.task('sass', function () {
return gulp
.src(sassGlobs, {base: "./"})
// .pipe(sassGraph(sassPaths))
.pipe(cached('sasscache'))
.pipe(sourcemaps.init())
.pipe(
sass({outputStyle: 'compressed'})
.on('error', sass.logError)
)
.pipe(sourcemaps.write())
.pipe(gulp.dest((file) => file.base));
});
gulp.task('watch', function () {
return gulp.watch(sassGlobs, ['sass']);
});
gulp.task('default', ['sass', 'watch']);
what I use to solve this problem is gulp-cached + gulp-dependents + gulp-filter
the key point here is gulp-dependents, it will find all the parent files that depends on the current file.
in your case, you just need:
const cached = require('gulp-cached');
const dependents = require('gulp-dependents');
const filter = require('gulp-filter');
const f = filter(['**', '!*src/partial']); //adjust this filter to filter the file you want to compile(pass to the sourcemap init method)
gulp.task('sass', function () {
return gulp
.src(PATH_TO_ALL_SASS_FILES, {base: "./"})
.pipe(cached('sasscache'))
.pipe(dependents())// this will find all parents of current changed files
.pipe(f) //exclude the partial files,get the files you want to compile
.pipe(sourcemaps.init())
.pipe(
sass({outputStyle: 'compressed'})
.on('error', sass.logError)
)
.pipe(sourcemaps.write())
.pipe(gulp.dest((file) => file.base)); // you might need to adjust the base path here, depend on your folder structure.
});

Using parent directory of file-directory as destination in gulp

How can I use the parent directory of a file-directory of a wildcard source in gulp?
Source files:
|gulpfile.js (just to show where the base is)
|elements/foundations/A/js/src/mainA.js
|elements/foundations/A/js/src/subA.js
|elements/foundations/B/js/src/mainB.js
...
|elements/foundations/F/js/src/mainF.js
Desired target/result:
|elements/foundations/A/js/mainA.min.js
|elements/foundations/A/js/subA.min.js
|elements/foundations/B/js/mainB.min.js
...
|elements/foundations/F/js/mainF.min.js
I've tried different approaches, but eventually none of them worked.
This one runs without errors but doesn't generate any files.
gulp.task('scripts', function () {
return gulp.src('./elements/foundations/**/js/src/*.js', {base: './elements/foundations/**/'})
.pipe(rename({suffix: '.min'}))
// .pipe(uglify()) and others ...
.pipe(gulp.dest('./'))
;
});
This one generates files, but directly in the src directory.
gulp.task('scripts', function () {
return gulp.src('./elements/foundations/**/js/src/*.js', {base: './elements/foundations/'})
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('./elements/foundations/'))
;
});
And if I try to use the wildcard (**) in the destination, gulp ends up in an infinite loop (independently of the position of the wildcard).
gulp.task('scripts', function () {
return gulp.src('./elements/foundations/**/js/src/*.js', {base: './elements/foundations/'})
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('./elements/foundations/**/'))
;
});
I've also tried to use it without setting the base, but the results were similar.
You can pass a function to gulp-rename for more complex renaming operations. This allows you for example to use the path module of node.js to manipulate file paths:
var gulp = require('gulp');
var rename = require('gulp-rename');
var path = require('path');
gulp.task('scripts', function() {
return gulp.src('./elements/foundations/**/js/src/*.js')
.pipe(rename(function(file) {
file.dirname = path.dirname(file.dirname);
file.basename = file.basename + '.min';
return file;
}))
// .pipe(uglify()) and others ...
.pipe(gulp.dest('./elements/foundations/'))
});

How to have GULP bundel libraries installed by Bower, ASP.Net 5

I have installed both jQuery and jQuery-Validation in my ASP.Net 5 application using the new Bower system. This has crated a folder called lib which contains a folder for both packages. In the folder for the packages there are LOTS of files and subfolders and after some digging around it looks like I only need to use the .js files in the dist folder.
I am also using gulp for bundling and minification but I am not sure how to configure it so it will add the files form the dist folders along with my own custom JavaScript files.
I am very new to both Gulp and Bower but so far they look far more cumbersome, annoying, and complex then the old NuGet and ASP.Net 2.5 Bundling and Minification way.
My Gulp (generated by VS2015 for me):
///
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify");
var paths = {
webroot: "./wwwroot/"
};
paths.js = paths.webroot + "js/**/*.js";
paths.minJs = paths.webroot + "js/**/*.min.js";
paths.css = paths.webroot + "css/**/*.css";
paths.minCss = paths.webroot + "css/**/*.min.css";
paths.concatJsDest = paths.webroot + "js/site.min.js";
paths.concatCssDest = paths.webroot + "css/site.min.css";
gulp.task("clean:js", function (cb) {
rimraf(paths.concatJsDest, cb);
});
gulp.task("clean:css", function (cb) {
rimraf(paths.concatCssDest, cb);
});
gulp.task("clean", ["clean:js", "clean:css"]);
gulp.task("min:js", function () {
return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
.pipe(concat(paths.concatJsDest))
.pipe(uglify())
.pipe(gulp.dest("."));
});
gulp.task("min:css", function () {
return gulp.src([paths.css, "!" + paths.minCss])
.pipe(concat(paths.concatCssDest))
.pipe(cssmin())
.pipe(gulp.dest("."));
});
gulp.task("min", ["min:js", "min:css"]);
EDIT:
I just added jquery.validatie.unobtrusive and it does not have a dist folder just some json files and the core .js file at the package root so how do I make sure I am grabbing all the right stuff here?
Assuming your dist folder is under webroot:
paths.dist = paths.webroot + "dist/**/*.js";
..
gulp.task("min:js", function () {
return gulp.src([paths.js, paths.dist, "!" + paths.minJs], { base: "." })
The key is that you set the source folders that gulp pulls files from. Notice that I added my paths.dist to the array? That adds that folder and all js files under it to gulp. If you need another folder, add another property to paths and add it to the array.

gulp filters javascript files and not css files

I am a newbie to gulp. I am trying to create one single vendor.css file and vendor.js file with gulp.
The vendor.css should be
-bootstrap.css
The vendor.js should be
-jquery.js
-bootstrap.js
-angular.js
-angular-ui-router.js
gulpfile.js
// Include Gulp
var gulp = require('gulp');
// Include plugins
var plugins = require("gulp-load-plugins")({
pattern: ['gulp-*', 'gulp.*'],
replaceString: /\bgulp[\-.]/
});
// Define default destination folder
var dest = 'public';
gulp.task('vendorjs', function(){
var filterJS = plugins.filter('**/*.js');
return gulp.src('./bower.json')
.pipe(plugins.mainBowerFiles( ))
.pipe(filterJS)
.pipe(plugins.concat('vendor.js'))
.pipe(plugins.uglify())
.pipe(filterJS.restore())
.pipe(gulp.dest(dest+"/vendor/js/"));
});
gulp.task('vendorcss', function(){
var filterCSS = plugins.filter('**/*.css');
return gulp.src('./bower.json')
.pipe(plugins.mainBowerFiles( ))
.pipe(filterCSS)
.pipe(plugins.concat('vendor.css'))
.pipe(plugins.uglify())
.pipe(filterCSS.restore())
.pipe(gulp.dest(dest+"/vendor/css/"));
});
gulp.task('default', function() {
// place code for your default task here
});
gulp.task('serve', ['vendorcss','vendorjs'], function () {
});
When i run gulp serve, it executes without error. But I end up with
public/vendor/css/angular/angular.js
public/vendor/css/angular-ui-router/release/angular-ui-router.js
public/vendor/css/bootstrap/dist/js/bootstrap.js
public/vendor/css/bootstrap/less/bootstrap.less
public/vendor/css/jquery/dist/jquery.js
public/vendor/js/vendor.js
public/vendor/js/bootstrap/less/bootstrap.less
Why do my css files are missing. Why do i get less file.
My output should be
public/vendor/vendor.js
public/vendor/vendor.css
How do i map the vendor.js and vendor.css with my html