Using parent directory of file-directory as destination in gulp - 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/'))
});

Related

script files not loading in rev-manifest.json (gulp)

I have this gulpfile.js where I'm minifying my js files the problem is that when I'm doing gulp build this task is creating the minified js files but not entering the key-value pairs in the rev-manifest.json.
gulp.task('js', function (done) {
console.log('minifying js...');
gulp.src('./assets/**/*.js')
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest('./public/assets'))
.pipe(rev.manifest({
cwd: 'public',
merge: true
}))
.pipe(gulp.dest('./public/assets'));
done()
});
I have a similar task for my scss files which converts scss to CSS and then minifies it. this is working absolutely fine adding proper key-value pairs in the rev-manifest.json
gulp.task('css', function (done) {
console.log('minifying css...');
gulp.src('./assets/sass/**/*.scss')
.pipe(sass())
.pipe(cssnano())
.pipe(gulp.dest('./assets.css'));
gulp.src('./assets/**/*.css')
.pipe(rev())
.pipe(gulp.dest('./public/assets'))
.pipe(rev.manifest({
cwd: 'public',
merge: true
}))
.pipe(gulp.dest('./public/assets'));
done();
});
this is what rev-manifest.json looks like
See it's only adding the css files here but not js files.
my rev-manifest.json is present inside public/assets/
In my case, manifests were not merging, they were getting overwritten. gulp.dest() causes the file to be overwritten. We indeed have to pass the path of the manifest as parameter before the options if we want the merge to work, here is the working code :
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const cssnano = require('gulp-cssnano');
const rev = require('gulp-rev');
const uglify = require('gulp-uglify-es').default;
const imagemin = require('gulp-imagemin');
const del = require('del');
gulp.task('css', function(done){
console.log('minifying css...');
gulp.src('./assets/sass/**/*.scss')
.pipe(sass())
.pipe(cssnano())
.pipe(gulp.dest('./assets/'));
return gulp.src('./assets/**/*.css')
.pipe(rev())
.pipe(gulp.dest('./public/assets/'))
.pipe(rev.manifest('public/assets/rev-manifest.json', {
base: './public/assets',
merge: true // merge with the existing manifest (if one exists)
}))
.pipe(gulp.dest('./public/assets/'));
done();
});
gulp.task('js', function (done) {
console.log('minifying js...');
gulp.src('./assets/**/*.js')
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest('./public/assets/'))
.pipe(rev.manifest('public/assets/rev-manifest.json', {
base: './public/assets',
merge: true // merge with the existing manifest (if one exists)
}))
.pipe(gulp.dest('./public/assets/'));
done()
});
gulp.task('images', function(done){
console.log('compressing images...');
gulp.src('./assets/**/*.+(png|jpg|gif|svg|jpeg)')
.pipe(imagemin())
.pipe(rev())
.pipe(gulp.dest('./public/assets/'))
.pipe(rev.manifest('public/assets/rev-manifest.json', {
base: './public/assets',
merge: true // merge with the existing manifest (if one exists)
}))
.pipe(gulp.dest('./public/assets/'));
done();
});
// empty the public/assets directory
gulp.task('clean:assets', function(done){
del.sync('./public/assets');
done();
});
gulp.task('build', gulp.series('clean:assets', 'css', 'js', 'images'), function(done){
console.log('Building assets');
done();
});
I just deleted the rev-manifest.js file and build it again and it worked. Took me a day to do this.
Why God Why.

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 concatenate plugins and main scripts then minify

I'm hoping to combine everything into one minified JS file, with the contents of main.js right at the end. The below outputs a minified file int he correct destination, but it seems to ignore the order. Any help would be much appreciated.
// Filepaths
var themepath = 'wp/wp-content/themes/themename'
// optimise scripts
gulp.task('scripts', function() {
return gulp.src('build/scripts/**/*.js')
.pipe(order(['build/scripts/plugins/**/*.js','build/scripts/main.js']))
.pipe(concat('main-min.js'))
.pipe(uglify())
.pipe(plumber())
.on('error', errorLog)
.pipe(gulp.dest(themepath + '/assets/scripts/min/'))
.pipe(browserSync.stream());
});
Try run uglify before concat. I think uglify messes with the order. So try the following:
// Filepaths
var themepath = 'wp/wp-content/themes/themename'
// optimise scripts
gulp.task('scripts', function() {
return gulp.src('build/scripts/**/*.js')
.pipe(order(['build/scripts/plugins/**/*.js','build/scripts/main.js']))
.pipe(uglify())
.pipe(concat('main-min.js'))
.pipe(plumber())
.on('error', errorLog)
.pipe(gulp.dest(themepath + '/assets/scripts/min/'))
.pipe(browserSync.stream());
});
Alright I figured it out.
Because you're specifying the order within an already predefined stream from gulp.src. You need to specify the order relative to the original gulp.src path, I.E. removed build/scripts from the order paths:
.pipe(order(['plugins/**/*.js', 'main.js']))

How to use gulp-watch?

What is the proper way to use gulp-watch plugin?
...
var watch = require('gulp-watch');
function styles() {
return gulp.src('app/styles/*.less')
.pipe(watch('app/styles/*.less'))
.pipe(concat('main.css'))
.pipe(less())
.pipe(gulp.dest('build'));
}
gulp.task('styles', styles);
I don't see any results when run gulp styles.
In your shell (such as Apple's or Linux's Terminal or iTerm) navigate to the folder that your gulpfile.js. For example, if you're using it with a WordPress Theme your gulpfile.js should be in your Theme's root. So navigate there using cd /path/to/your/wordpress/theme.
Then type gulp watch and hit enter.
If your gulpfile.js is configured properly (see example below) than you will see output like this:
[15:45:50] Using gulpfile /path/to/gulpfile.js
[15:45:50] Starting 'watch'...
[15:45:50] Finished 'watch' after 11 ms
Every time you save your file you'll see new output here instantly.
Here is an example of a functional gulpfile.js:
var gulp = require('gulp'),
watch = require('gulp-watch'),
watchLess = require('gulp-watch-less'),
pug = require('gulp-pug'),
less = require('gulp-less'),
minifyCSS = require('gulp-csso'),
concat = require('gulp-concat'),
sourcemaps = require('gulp-sourcemaps');
gulp.task('watch', function () {
gulp.watch('source/less/*.less', ['css']);
});
gulp.task('html', function(){
return gulp.src('source/html/*.pug')
.pipe(pug())
.pipe(gulp.dest('build/html'))
});
gulp.task('css', function(){
return gulp.src('source/less/*.less')
.pipe(less())
.pipe(minifyCSS())
.pipe(gulp.dest('build/css'))
});
gulp.task('js', function(){
return gulp.src('source/js/*.js')
.pipe(sourcemaps.init())
.pipe(concat('app.min.js'))
.pipe(sourcemaps.write())
.pipe(gulp.dest('build/js'))
});
gulp.task('default', [ 'html', 'js', 'css', 'watch']);
Note: Anywhere you see source/whatever/ this is a path you'll either need to create or update to reflect the path you're using for the respective file.
gulp.task('less', function() {
gulp.src('app/styles/*.less')
.pipe(less())
.pipe(gulp.dest('build'));
});
gulp.task('watch', function() {
gulp.watch(['app/styles/*.less'], ['less'])
});
Name your task like I have my 'scripts' task named so you can add it to the series. You can add an array of tasks to the series and they will be started in the order they are listed. For those coming from prior versions note the return on the gulp.src.
This is working code I hope it helps the lurkers.
Then (for version 4+) you need to do something like this:
var concat = require('gulp-concat'); // we can use ES6 const or let her just the same
var uglify = require('gulp-uglify'); // and here as well
gulp.task('scripts', function(done) {
return gulp.src('./src/js/*.js')
.pipe(concat('all.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist/js/'));
});
gulp.task('watch', function() {
gulp.watch('./src/js/*.js',gulp.series(['scripts']))
});
** Note the line gulp.watch('./src/js/*.js',gulp.series(['scripts'],['task2'],['etc']))

How do I replace the filenames listed in index.html with the output of gulp-rev?

I'm using gulp-rev to build static files that I can set to never expire. I'd like to replace all references to the generated files in index.html to these renamed files, but I can't seem to find anything that does that like Grunt with usemin.
As far as I can tell right now, I have some options.
Use gulp-usemin2, which depends on gulp-rev. When I go to search Gulp plugins, it says that gulp-usemin2 does too much so I should use gulp-useref instead, but I can't configure gulp-ref to use gulp-rev's output.
Write my own plugin the replace the blocks (scripts & styles) in index.html (and in the CSS) with the generated files.
Any ideas? I don't see why this little use case should be the only thing in my way to replacing Grunt.
Rather than trying to solve this problem multiple gulp steps (which gulp-rev seems to want you to do), I've forked gulp-rev to gulp-rev-all to solve this usecase in one gulp plugin.
For my personal usecase I wanted to rev absolutely everything but as someone else raised an feature request, there should be the ability to exclude certain files like index.html. This will be implemented soon.
I've just written a gulp plugin to do this, it works especially well with gulp-rev and gulp-useref.
The usage will depend on how you've set things up, but it should look something like:
gulp.task("index", function() {
var jsFilter = filter("**/*.js");
var cssFilter = filter("**/*.css");
return gulp.src("src/index.html")
.pipe(useref.assets())
.pipe(jsFilter)
.pipe(uglify()) // Process your javascripts
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe(csso()) // Process your CSS
.pipe(cssFilter.restore())
.pipe(rev()) // Rename *only* the concatenated files
.pipe(useref.restore())
.pipe(useref())
.pipe(revReplace()) // Substitute in new filenames
.pipe(gulp.dest('public'));
});
I have confronted the same problem, I tried gulp-rev-all, but it has some path problem, not very free to use.
So I figure out an solution, use gulp-rev and gulp-replace:
At first I have a replace symbol in my html(js, css) files
<link rel="stylesheet" href="{{{css/common.css}}}" />
<script src="{{{js/lib/jquery.js}}}"></script>
in css files
background: url({{{img/logo.png}}})
Second after some compile task, use gulp-replace to replace all the static files reference:
take stylus compile in development as example:
gulp.task('dev-stylus', function() {
return gulp.src(['./fe/css/**/*.styl', '!./fe/css/**/_*.styl'])
.pipe(stylus({
use: nib()
}))
.pipe(replace(/\{\{\{(\S*)\}\}\}/g, '/static/build/$1'))
.pipe(gulp.dest('./static/build/css'))
.pipe(refresh());
});
In production environment, use gulp-rev to generate rev-manifest.json
gulp.task('release-build', ['release-stylus', 'release-js', 'release-img'], function() {
return gulp.src(['./static/build/**/*.css',
'./static/build/**/*.js',
'./static/build/**/*.png',
'./static/build/**/*.gif',
'./static/build/**/*.jpg'],
{base: './static/build'})
.pipe(gulp.dest('./static/tmp'))
.pipe(rev())
.pipe(gulp.dest('./static/tmp'))
.pipe(rev.manifest())
.pipe(gulp.dest('./static'));
});
Then use gulp-replace to replace the refs in static files with rev-manifest.json:
gulp.task('css-js-replace', ['img-replace'], function() {
return gulp.src(['./static/tmp/**/*.css', './static/tmp/**/*.js'])
.pipe(replace(/\{\{\{(\S*)\}\}\}/g, function(match, p1) {
var manifest = require('./static/rev-manifest.json');
return '/static/dist/'+manifest[p1]
}))
.pipe(gulp.dest('./static/dist'));
});
This helped me gulp-html-replace.
<!-- build:js -->
<script src="js/player.js"></script>
<script src="js/monster.js"></script>
<script src="js/world.js"></script>
<!-- endbuild -->
var gulp = require('gulp');
var htmlreplace = require('gulp-html-replace');
gulp.task('default', function() {
gulp.src('index.html')
.pipe(htmlreplace({
'css': 'styles.min.css',
'js': 'js/bundle.min.js'
}))
.pipe(gulp.dest('build/'));
});
You could do it with gulp-useref like this.
var gulp = require('gulp'),
useref = require('gulp-useref'),
filter = require('gulp-filter'),
uglify = require('gulp-uglify'),
minifyCss = require('gulp-minify-css'),
rev = require('gulp-rev');
gulp.task('html', function () {
var jsFilter = filter('**/*.js');
var cssFilter = filter('**/*.css');
return gulp.src('app/*.html')
.pipe(useref.assets())
.pipe(jsFilter)
.pipe(uglify())
.pipe(rev())
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe(minifyCss())
.pipe(rev())
.pipe(cssFilter.restore())
.pipe(useref.restore())
.pipe(useref())
.pipe(gulp.dest('dist'));
});
or you could even do it this way:
gulp.task('html', function () {
var jsFilter = filter('**/*.js');
var cssFilter = filter('**/*.css');
return gulp.src('app/*.html')
.pipe(useref.assets())
.pipe(rev())
.pipe(jsFilter)
.pipe(uglify())
.pipe(jsFilter.restore())
.pipe(cssFilter)
.pipe(minifyCss())
.pipe(cssFilter.restore())
.pipe(useref.restore())
.pipe(useref())
.pipe(gulp.dest('dist'));
});
The problem is updating the asset paths in the html with the new rev file paths. gulp-useref doesn't do that.