I'm having problems with my gulp-rev-all task. Everytime I change the code, it will generate a new revision file, but leave the old one there.
Here is my gulp task:
var gulp = require('gulp');
var RevAll = require('gulp-rev-all');
gulp.task('js', function() {
var revAll = new RevAll();
return gulp.src(opt.Src + 'scripts.js')
// Add a hash to the file
.pipe(revAll.revision())
// Save the hashed css file
.pipe(gulp.dest(path.js))
// Write the manifest file
.pipe(revAll.manifestFile())
.pipe(gulp.dest(path.js + 'rev'));
});
So, this works like a charm.
It will give me a file with a rev (like: scripts.0ad8ecf1.js) and a manifest.json file.
The challange is, whenever I change my code, it will generate a new scripts.js file with a different hash and not overwrite or remove the old one. So, my folder looks like this now:
scripts.0ad8ecf1.js
scripts.7e3fa506.js
scripts.056ddda0.js
I can't seem to replace the old file for the new one.
Can anybody help me or point me in the right direction to accomplish this?
You need to delete your files with another plugin, since gulp-rev-all doesn't do this for you.
You could for example use the 'del' package (https://www.npmjs.com/package/del)
And then create a "delete Task" something like this:
var del = require('del');
/**
* Deletes all files inside the /foo/scripts/ folder
*/
gulp.task('purge:foo', function() {
return del.sync(['foo/scripts/**'], function (err, deletedFiles) {
if (err) {
console.log(err);
}
if (deletedFiles) {
console.log('Elements deleted:', deletedFiles.join(', '));
}
});
});
Related
I've read Get the current file name in gulp.src(), and it seems like it's approaching what I am attempting to do, but I need help.
Consider the following function in a gulpfile.js:
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/app.css')))
.pipe(gulp.dest('dist'));
}
And inliner(), to be thorough (also in the gulpfile):
function inliner(css) {
var css = fs.readFileSync(css).toString();
var mqCss = siphon(css);
var pipe = lazypipe()
.pipe($.inlineCss, {
applyStyleTags: false,
removeStyleTags: false,
removeLinkTags: false
})
.pipe($.replace, '<!-- <style> -->', `<style>${mqCss}</style>`);
return pipe();
}
These functions take an external CSS file and inline them into the respective HTML for email.
I really want to know how to do something like this:
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, inliner('dist/css/' + file.name + '.css')))
.pipe(gulp.dest('dist'));
}
And you might ask yourself, "why?" Well, I don't have just one CSS file. If everything from app.css was to be inlined, there would be a lot more styles applied than were actually necessary.
So I want to inline:
email1.css ---- to -------> email1.html
email2.css ---- to -------> email2.html
email3.css ---- to -------> email3.html
And so on. Essentially, I want to get the name of the HTML file being processed at that moment in the Gulp Stream, save it as a variable, and then pass it into the inliner('dist/css/' + file.name + '.css') bit. I've exhausted every bit of Gulp Knowledge I have and have come up completely and utterly blank.
Basically what you need to do is send each .html file in your stream down its own little sub stream with its own inliner(). The gulp-foreach plugin let's you do just that.
Then it's just a matter of determining the simple name of your file from its absolute path. The node.js built-in path.parse() got you covered there.
Putting it all together:
var path = require('path');
function inline() {
return gulp.src('dist/**/*.html')
.pipe($.if(PRODUCTION, $.foreach(function(stream, file) {
var name = path.parse(file.path).name;
return stream.pipe(inliner('dist/css/' + name + '.css'));
})))
.pipe(gulp.dest('dist'));
}
I use gulp to configure complex local setup and need to auto-edit files.
The scenario is:
determine if certain file contains certain lines after certain other line (found using regular expression)
if line is not found, insert the line.
optionally, delete some lines found in the file.
I need this to amend system configuration files and compile scenarios.
What would be the best way to do it in gulp?
Gulp is plain javascript. So what I would do if I were you is to create a plugin to pipe to the original config file.
Gulp streams emit Vinyl files. So all you really got to do is to create a "pipe factory" that transforms the objects.
It would look something like this (using EventStream):
var es = require('event-stream');
// you could receive params in here if you're using the same
// plugin in different occasions.
function fixConfigFile() {
return es.map(function(file, cb) {
var fileContent = file.contents.toString();
// determine if certain file contains certain lines...
// if line is not found, insert the line.
// optionally, delete some lines found in the file.
// update the vinyl file
file.contents = new Buffer(fileContent);
// send the updated file down the pipe
cb(null, file);
});
}
gulp.task('fix-config', function() {
return gulp.src('path/to/original/*.config')
.pipe(fixConfigFile())
.pipe(gulp.dest('path/to/fixed/configs');
});
Or you can use vinyl-map:
const map = require('vinyl-map')
const gulp = require('gulp')
const modify = map((contents, filename) => {
contents = contents.toString()
// modify contents somehow
return contents
})
gulp.task('modify', () =>
gulp.src(['./index.js'])
.pipe(modify)
.pipe(gulp.dest('./dist'))
})
I am trying to pass a parameter to a task that is being invoked by gulp-watch. I need it because I am trying to build a modular framework.
So if a file changes in module 1, the other modules don't need to be rebuild.
And I want just one function to create the concatted & uglified files per module.
This is what I got so far:
//here I need the 'module' parameter
gulp.task('script', function(module) { ... }
gulp.task('watch', function() {
gulp.watch('files/in/module1/*.js', ['script']); //here I want to pass module1
gulp.watch('files/in/module2/*.js', ['script']); //here I want to pass module2
});
A lot of the documentation/examples seems to be outdated (gulp.run(), gulp.start()).
I hope someone can help me out here.
I had the very same issue, searched for a while, and the "cleanest" way I came up with, uses the .on() event handler of gulp.watch(), and the .env property of gulp-util:
var gulp = require('gulp');
$.util = require('gulp-util');
var modules = {
module1: {}, // awesome module1
module2: {} // awesome module2
};
gulp.task('script', function(){
var moduleName = $.util.env.module;
// Exit if the value is missing...
var module = modules[moduleName];
if (!module) {
$.util.log($.util.colors.red('Error'), "Wrong module value!");
return;
}
$.util.log("Executing task on module '" + moduleName + "'");
// Do your task on "module" here.
});
gulp.task('watch', function () {
gulp.watch(['files/in/module1/*.js'], ['script']).on('change', function () {
$.util.env.module = 'module1';
});
gulp.watch(['files/in/module2/*.js'], ['script']).on('change', function () {
$.util.env.module = 'module2';
});
});
gulp-util also comes in handy if you need to pass (global) parameters from the shell:
[emiliano#dev ~]# gulp script --module=module1 --minify
Hope this helps someone else out there!
Regards.
In that i will answer directly the question "How to pass a parameter to gulp-watch invoked task"
My way of doing, and one of the possibility i see, is to use a global variable to pass the value between the two blocks. you set it just before launching the task in the watcher. And in the task, just at the start you pass it to a local variable.
See this answer for more details: https://stackoverflow.com/a/49733123/7668448
In what you want to achieve, you can too use just one watcher over the directory that hold all modules. If so is the structure. Then when a change happen, you can recover the changed file path. From that you can deduce what module does belong to. By getting the Module folder. That way you will not need to add a new watcher for each new module. Which can be nice when there is multiple contributors to the project for example when working on open source. And you do it one time, and don't have to care about adding anything. Just like with the delegation principle, with DOM event handling when there is multiple elements. Even if the chosen structure, doesn't have all the modules in one directory. You can stay pass multiple globs to the one watcher.
gulp.watch(['glob1/**/*.js', 'glob2/**/*.js',...], function(evt) {/*.....*/});
And following the structure you have, you can work your way to deduce what module is.
For the watcher here how i suggest you do it:
watch('./your/allModulesFolder/**/*.js', function (evt) {
rebuildModulWatchEvt = evt; //here you update the global var
gulp.start('rebuildModul'); // you start the task
})
The evt here hold multiple info: cwd, base, state, _contents ...etc And what interest us is path. So evt.path will give you the path of the changed file.
In your task either you do that:
gulp.task('rebuildModul', function() {
let evt = rebuildModulWatchEvt; // at all start you pass it to a local var
let filePath = evt.path; // how you get the changed file path
// your code go here for the rest, following your structure, get the path for the module folder
});
or you use a function :
gulp.task('rebuildModul', function() {
rebuildModulTaskRun(rebuildModulWatchEvt);
});
function rebuilModulTaskRun(evt) {
let filePath = evt.path;
// your code go here for the rest, following your structure, get the path for the module folder
}
Just learning Gulp. Looks great, but I can't find any information on how to make a complete distribution with it.
Let's say I want to use Gulp to concatenate and minify my CSS and JS, and optimise my images.
In doing so I change the location of JS scripts in my build directory (eg. from bower_components/jquery/dist/jquery.js to js/jquery.js).
How do I automatically update my build HTML/PHP documents to reference the correct files? What is the standard way of doing this?
How do I copy over the rest of my project files?. These are files that need to be included as part of the distribution, such as HTML, PHP, various txt, JSON and all sorts of other files. Surely I don't have to copy and paste those from my development directory each time I do a clean build with Gulp?
Sorry for asking what are probably very n00bish questions. It's possible I should be using something else other than Gulp to manage these, but I'm not sure where to start.
Many thanks in advance.
Point #1
The way i used to achieve this:
var scripts = [];
function getScriptStream(dir) { // Find it as a gulp module or create it
var devT = new Stream.Transform({objectMode: true});
devT._transform = function(file, unused, done) {
scripts.push(path.relative(dir, file.path));
this.push(file);
done();
};
return devT;
}
// Bower
gulp.task('build_bower', function() {
var jsFilter = g.filter('**/*.js');
var ngFilter = g.filter(['!**/angular.js', '!**/angular-mocks.js']);
return g.bowerFiles({
paths: {
bowerDirectory: src.vendors
},
includeDev: !prod
})
.pipe(ngFilter)
.pipe(jsFilter)
.pipe(g.cond(prod, g.streamify(g.concat.bind(null, 'libs.js'))))
.pipe(getScriptStream(src.html))
.pipe(jsFilter.restore())
.pipe(ngFilter.restore())
.pipe(gulp.dest(build.vendors));
});
// JavaScript
gulp.task('build_js', function() {
return gulp.src(src.js + '/**/*.js', {buffer: buffer})
.pipe(g.streamify(g.jshint))
.pipe(g.streamify(g.jshint.reporter.bind(null, 'default')))
.pipe(g.cond(prod, g.streamify(g.concat.bind(null,'app.js'))))
.pipe(g.cond(
prod,
g.streamify.bind(null, g.uglify),
g.livereload.bind(null, server)
))
.pipe(gulp.dest(build.js))
.pipe(getScriptStream(build.html));
});
// HTML
gulp.task('build_html', ['build_bower', 'build_js', 'build_views',
'build_templates'], function() {
fs.writeFile('scripts.json', JSON.stringify(scripts));
return gulp.src(src.html + '/index.html' , {buffer: true})
.pipe(g.replace(/(^\s+)<!-- SCRIPTS -->\r?\n/m, function($, $1) {
return $ + scripts.map(function(script) {
return $1 + '<script type="text/javascript" src="'+script+'"></script>';
}).join('\n') + '\n';
}))
.pipe(gulp.dest(build.html));
});
It has the advantages of concatenating and minifying everything for production while include every files for testing purpose keeping error line numbers coherent.
Point 2
Copying files with gulp is just as simple as doing this:
gulp.src(path).pipe(gulp.dest(buildPath));
Bonus
I generally proceed to deployment by creating a "build" branch and just cloning her in the production server. I created buildbranch for that matter:
// Publish task
gulp.task('publish', function(cb) {
buildBranch({
branch: 'build',
ignore: ['.git', '.token', 'www', 'node_modules']
}, function(err) {
if(err) {
throw err;
}
cb();
});
});
To loosely answer my own question, several years later:
How do I automatically update my build HTML/PHP documents to reference the correct files? What is the standard way of doing this?
Always link to dist version, but ensure sourcemaps are created, so the source is easy to debug. Of course, the watch task is a must.
How do I copy over the rest of my project files?. These are files that need to be included as part of the distribution, such as HTML, PHP, various txt, JSON and all sorts of other files. Surely I don't have to copy and paste those from my development directory each time I do a clean build with Gulp?
This usually isn't a problem as there aren't offer too many files. Large files and configuration are often kept out if the repo, besides.
In my gulp.js file I'm streaming all HTML files from the examples folder into the build folder.
To create the gulp task is not difficult:
var gulp = require('gulp');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(gulp.dest('./build'));
});
But I can't figure out how retrieve the file names found (and processed) in the task, or I can't find the right plugin.
I'm not sure how you want to use the file names, but one of these should help:
If you just want to see the names, you can use something like gulp-debug, which lists the details of the vinyl file. Insert this anywhere you want a list, like so:
var gulp = require('gulp'),
debug = require('gulp-debug');
gulp.task('examples', function() {
return gulp.src('./examples/*.html')
.pipe(debug())
.pipe(gulp.dest('./build'));
});
Another option is gulp-filelog, which I haven't used, but sounds similar (it might be a bit cleaner).
Another options is gulp-filesize, which outputs both the file and it's size.
If you want more control, you can use something like gulp-tap, which lets you provide your own function and look at the files in the pipe.
I found this plugin to be doing what I was expecting: gulp-using
Simple usage example: Search all files in project with .jsx extension
gulp.task('reactify', function(){
gulp.src(['../**/*.jsx'])
.pipe(using({}));
....
});
Output:
[gulp] Using gulpfile /app/build/gulpfile.js
[gulp] Starting 'reactify'...
[gulp] Finished 'reactify' after 2.92 ms
[gulp] Using file /app/staging/web/content/view/logon.jsx
[gulp] Using file /app/staging/web/content/view/components/rauth.jsx
Here is another simple way.
var es, log, logFile;
es = require('event-stream');
log = require('gulp-util').log;
logFile = function(es) {
return es.map(function(file, cb) {
log(file.path);
return cb(null, file);
});
};
gulp.task("do", function() {
return gulp.src('./examples/*.html')
.pipe(logFile(es))
.pipe(gulp.dest('./build'));
});
You can use the gulp-filenames module to get the array of paths.
You can even group them by namespaces:
var filenames = require("gulp-filenames");
gulp.src("./src/*.coffee")
.pipe(filenames("coffeescript"))
.pipe(gulp.dest("./dist"));
gulp.src("./src/*.js")
.pipe(filenames("javascript"))
.pipe(gulp.dest("./dist"));
filenames.get("coffeescript") // ["a.coffee","b.coffee"]
// Do Something With it
For my case gulp-ignore was perfect.
As option you may pass a function there:
function condition(file) {
// do whatever with file.path
// return boolean true if needed to exclude file
}
And the task would look like this:
var gulpIgnore = require('gulp-ignore');
gulp.task('task', function() {
gulp.src('./**/*.js')
.pipe(gulpIgnore.exclude(condition))
.pipe(gulp.dest('./dist/'));
});
If you want to use #OverZealous' answer (https://stackoverflow.com/a/21806974/1019307) in Typescript, you need to import instead of require:
import * as debug from 'gulp-debug';
...
return gulp.src('./examples/*.html')
.pipe(debug({title: 'example src:'}))
.pipe(gulp.dest('./build'));
(I also added a title).