Define file order in gulpfile.js - gulp

I need to run bundling and minifying for some .js files, but I need to define a correct order for these files to be processed.
How can I do this?
my gulpfile.js file, path snippet:
...
var paths = {
js: webroot + "js/lib/**/*.js",
minJs: webroot + "js/lib/**/*.min.js",
css: webroot + "css/lib/**/*.css",
minCss: webroot + "css/lib/**/*.min.css",
...
I need to process in this order:
jquery.js
jquery-ui.custom.js
my-site.js
update
Entire gulpfile.js file (this is the default file for asp.net core bundling and minifying tasks):
/// <binding Clean='clean' />
"use strict";
var gulp = require("gulp"),
rimraf = require("rimraf"),
concat = require("gulp-concat"),
cssmin = require("gulp-cssmin"),
uglify = require("gulp-uglify");
var webroot = "./wwwroot/";
var paths = {
js: webroot + "js/lib/**/*.js",
minJs: webroot + "js/lib/**/*.min.js",
css: webroot + "css/lib/**/*.css",
minCss: webroot + "css/lib/**/*.min.css",
concatJsDest: webroot + "js/site.min.js",
concatCssDest: 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"]);

It's pretty simple, you need to specify array of paths to your files (paths can contain wildcards), i.e:
/* REMEMBER TO USE FULL PATHS */
var order = [
"jquery.js",
"jquery-ui.custom.js",
"my-site.js"
];
gulp.task("yourtask",function () {
var sources = order.concat([
webroot + "js/lib/**/*.js",
webroot + "js/lib/**/*.min.js",
]);
return gulp.src(sources)./* your operations goes here*/
});
Also, gulp is smart enough to not duplicate already used files, so you can include your libraries like this one:
webroot + "js/lib/**/*.js"

Related

Gulp - Watch multiple folders and output to relative dist folder

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

Gulp watch delete files

I'm new to Gulp, i did some research but not found solutions .. Here is my Gulpfile.
var gulp = require('gulp');
var watch = require('gulp-watch');
var imagemin = require('gulp-imagemin');
var browserSync = require('browser-sync').create();
var paths = {
src: 'src/',
dist: 'dist/',
html: '**/*.html',
php: '**/*.php',
images: {
src: 'assets/img/**/*.{png,jpg,jpeg,svg,gif}',
dist: 'assets/img'
},
misc: '**/*.{ico,htaccess,txt}'
}
/**
* Files
*/
gulp.task('files', function(){
return gulp.src([
paths.src + paths.php,
paths.src + paths.html,
paths.src + paths.misc
])
.pipe(gulp.dest(paths.dist))
.pipe(browserSync.stream());
});
/**
* Images
*/
gulp.task('images', function(){
return gulp.src(
paths.src + paths.images.src
)
.pipe(imagemin({
progressive: true
}))
.pipe(gulp.dest(paths.dist + paths.images.dist))
.pipe(browserSync.stream());
});
/**
* Serve
*/
gulp.task('serve', ['files', 'images'], function(){
browserSync.init({
server: {
baseDir: 'dist'
}
});
watch([
paths.src + paths.php,
paths.src + paths.html,
paths.src + paths.misc
], function(){ gulp.start('files') });
watch(
paths.src + paths.images.src
, function(){ gulp.start('images') });
});
All is ok but during watching files from my "src" folder (serve task), when i delete a file (image or html,php etc...) in "src", the file is not deleted in the "dist" folder.
When file changed or added, no problem.. I've found some similar topics but not the solution..
Thanks.
The reason files aren't deleted in your dist folder is because gulp.watch() simply reruns a task whenever a watched file changes. That task doesn't know that the reason it is running is because a file was deleted. It simply processes all files matching the glob in its gulp.src() statement.
Since the deleted file doesn't exist anymore, it is not picked up by gulp.src() and your task doesn't process it. It is simply left standing as it is in your dist folder, while the other files there are overwritten.
One way to fix this is to follow the Handling the Delete Event on Watch recipe:
var fileWatcher = watch([
paths.src + paths.php,
paths.src + paths.html,
paths.src + paths.misc
], function(){ gulp.start('files') });
fileWatcher.on('change', function (event) {
if (event.type === 'deleted') {
var filePathFromSrc = path.relative(path.resolve(paths.src), event.path);
var destFilePath = path.resolve(paths.dist, filePathFromSrc);
del.sync(destFilePath);
}
});
The handling for your images would be analogous.

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.

Merging two gulp streams

I am trying to merge two gulp sources as follows:
gulp.task("build", ["clean"], function () {
var sb = gulp.src([
paths.bower + "jquery/jquery.js",
paths.bower + "angular/angular.js"
])
.pipe(flatten())
.pipe(gulp.dest(paths.scripts.vnd));
var sm = gulp.src([
paths.scripts.vnd + "jquery.js",
paths.scripts.vnd + "angular.js"
])
.pipe(concat("app.js"))
.pipe(gulp.dest(paths.scripts.dst))
.pipe(rename("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest(paths.scripts.dst));
return merge(sb, sm);
});
Somehow only the first one is executed.
However, if I move the second one to another task with dependency on build then both are executed ...
Am I doing the merging the wrong way?
UPDATE 1
I updated my task to build both LESS files and JS files so I have:
var
gulp = require("gulp"),
fs = require("fs"),
merge = require("merge2"),
concat = require("gulp-concat"),
flatten = require("gulp-flatten"),
less = require('gulp-less'),
minify = require('gulp-minify-css'),
rename = require("gulp-rename"),
rimraf = require("gulp-rimraf"),
uglify = require("gulp-uglify");
var paths = {
bower: "./bower_components/",
scripts: {
app: "./" + "/scripts/app/",
dst: "./" + "/scripts/dst/",
vnd: "./" + "/scripts/vnd/"
},
styles: {
app: "./" + project.webroot + "/styles/app/",
dst: "./" + project.webroot + "/styles/dst/"
}
};
gulp.task("build", function () {
var sbm = gulp.src([
paths.styles.app + "*.less",
paths.styles.vnd + "*.less"
])
.pipe(less())
.pipe(minify())
.pipe(concat("app.css"))
.pipe(gulp.dest(paths.styles.dst))
.pipe(rename("app.min.css"))
.pipe(gulp.dest(paths.styles.dst));
var scb = gulp.src(
[
paths.bower + "jquery/jquery.js",
paths.bower + "angular/angular.js"
])
.pipe(flatten())
.pipe(gulp.dest(paths.scripts.vnd));
var scm = gulp.src(
[
paths.scripts.vnd + "jquery.js",
paths.scripts.vnd + "angular.js"
])
.pipe(concat("app.js"))
.pipe(gulp.dest(paths.scripts.dst))
return merge(sbm, scb, scm);
});
Somehow, this only executes sbm ... Does anyone knows why?
I also tried #topleft's suggestion but when including the LESS tasks at the end the app.min.js file get's the Less code in it ...
try this with merge2 plugin, that's how I do it
var merge = require('merge2');
gulp.task("build", ["clean"], function () {
var sb = gulp.src([
paths.bower + "jquery/jquery.js",
paths.bower + "angular/angular.js"
])
.pipe(flatten())
.pipe(gulp.dest(paths.scripts.vnd));
var sm = gulp.src([
paths.scripts.vnd + "jquery.js",
paths.scripts.vnd + "angular.js"
])
return merge(sb, sm)
.pipe(concat("app.js"))
.pipe(gulp.dest(paths.scripts.dst))
.pipe(rename("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest(paths.scripts.dst));
});
as an example, here is how I merge my two LESS streams : (one is unCSS'ed, the other is not)
/* ===== LESS START ===== */
gulp.task('less', function() {
// Get static styles
var streamMain = gulp.src([
srcAssets + '/less/**/*.less',
srcAssets + '!/less/**/interactive.less',])
// Convert to CSS
.pipe(less())
// Remove unused CSS rules
.pipe(uncss({
html: [dest + '/index.html']
}))
// Get dynamic styles
var streamEvents = gulp.src(srcAssets + '/less/global/interactive.less')
// Convert to CSS
.pipe(less())
// Merge dynamic and static styles
return merge(streamMain, streamEvents)
// Concatenate in a single file
.pipe(concat('main.css'))
// Remove all comments
.pipe(stripCssComments({
all: true
}))
// Autoprefixer for browser compatibility
.pipe(autoprefixer())
// Compression
.pipe(minifyCSS())
// Output file
.pipe(gulp.dest(dest + '/css'));
});
/* ===== LESS END ===== */

How to detect css theme and work only with this theme?

I have a project in which there are about 30 css themes. It means I have the next css files structure:
src/
themes/
default/
a.scss
b.scss
rockStar/
a.scss
b.scss
oneMoreTheme/
a.scss
b.scss
dist/
themes/
default/
styles.css
rockStar/
styles.css
oneMoreTheme/
styles.css
Here is just example of gulpfile:
var gulp = require('gulp'),
glob = require('glob'),
path = require('path'),
_ = require('underscore'),
$ = require('gulp-load-plugins')(),
options = {};
options.themes = [
'default',
'rockStar',
'oneMoreTheme'
];
gulp.task('styles', function () {
_.each(options.themes, function(themeName, themeKey) {
gulp.src('src/themes/' + themeName + '/**/*.scss')
.pipe($.concat('styles.scss'))
.pipe($.sass())
.pipe(gulp.dest('dist/themes/' + themeName + '/'));
});
});
gulp.task('watch', function () {
gulp.watch('src/**/*.*', ['styles']);
});
In my gulp file I have a task "styles", which compiles scss files from each theme and puts compiled files to dist folder.
And I have task "watch" which run "styles" task when any scss file form any source theme changes. It works, but it takes much time because of lots of themes!
How can my task "watch" detect from which theme files changes and run task "styles" only for this changed theme?
That is indeed a tough one, but here is a solution. Please refer to the comments in the code for an explanation.
version 1
var gulp = require('gulp');
var merge = require('merge2');
var $ = require('gulp-load-plugins')();
var path = require('path');
var options = {};
options.themes = [
'default',
'rockStar',
'oneMoreTheme'
];
// we extract the task itself to a new function
// this allows us to reuse it
var styleTask = function(themeName) {
return gulp.src('src/themes/' + themeName + '/**/*.scss')
.pipe($.concat('styles.scss'))
.pipe($.sass())
.pipe(gulp.dest('dist/themes/' + themeName + '/'));
}
// we adapt the style task to use that function
// please note that I switched _.each for merge
// this allows you to work with streams!
gulp.task('styles', function() {
var tasks = themes.map(styleTask);
return merge(tasks);
});
// here we set up a new watcher. Instead of running 'styles'
// we filter the theme directory from the file that has changed
// and run the styleTask function
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', function(e) {
var theme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
return styleTask('theme');
});
});
version 2
// same as above except the default task. we save the theme
// we want to build in a file
var singleTheme;
// and call the styleTask function should it be set
gulp.task('single-style', function(done) {
if(singleTheme) {
return styleTask(singleTheme);
} else {
done();
}
});
// here we have a watcher that calls single-style, but before calling
// it gets the right themename.
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', 'single-style');
watcher.on('change', function(e) {
singleTheme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
})
})
I hope this helped.
Update If you want to run more tasks and have a status call on if they ended, please go for version 2. Than you can add all the tasks you want to run in
gulp.task('default', function() {
var watcher = gulp.watch('src/themes/**/*.scss', ['single-style', 'another-task']);
watcher.on('change', function(e) {
singleTheme = path
.relative(__dirname, e.path)
.substr('src/themes/'.length)
.split('/')[0];
console.log('rebuilding ' + theme);
})
})
Instead of gulp.run you can use gulp.start.