I encountered an issue trying to copy a set of files and when calling .dest('some folder') the entire folder structure was lost.
I searched and found an answer suggesting that I should provide {base:'.'} as an option on my call to gulp.src(...) to resolve this issue.
The documentation for gulp.src options only says that its options are:
Options to pass to node-glob through glob-stream.
Looking into node-glob documentation for its options base is not listed there at all.
And the glob-stream options documentation only states that
"the Default is everything before a glob starts (see glob-parent)"
So no much help here either.
So, what effect does the base option passed to gulp.src have on the viny6l files in the created stream and how does it effect the gulp.dest command ?
(You're not looking at the official gulp documentation. http://github.com/arvindr21/gulp is just some guy's fork of the gulpjs github repo. The official repo is http://github.com/gulpjs/gulp/ where the base option is indeed documented.)
To answer your question:
If you don't specify the base option yourself, then everything before the first glob in your gulp.src() paths is automatically used as the base option and ommitted when writing to the destination folder.
Say you have the following files:
some/path/example/app/js/app.js
some/path/example/vendor/js/vendor.js
some/path/example/vendor/lib/js/lib.js
And this is your Gulpfile.js:
gulp.src('some/path/**/js/*.js')
.pipe(gulp.dest('output'));
In this case everything before the ** is automatically used as your base option. So the above is essentially equivalent to this:
gulp.src('some/path/**/js/*.js', {base:'some/path/'})
.pipe(gulp.dest('output'));
What this means is that some/path/ is stripped from the path of every file that matches the pattern in gulp.src(). The resulting structure in the output folder looks like this:
output/example/app/js/app.js
output/example/vendor/js/vendor.js
output/example/vendor/lib/js/lib.js
So a certain part of the directory structure of your source files is indeed lost. How much of your directory structure you lose depends on where the first glob in your gulp.src() pattern is.
If you want to avoid this you have to explicitly specify the base option:
gulp.src('some/path/**/js/*.js', {base:'.'})
.pipe(gulp.dest('output'));
Now some/path/ will not be stripped from your file paths, resulting in the following folder structure in output:
output/some/path/example/app/js/app.js
output/some/path/example/vendor/js/vendor.js
output/some/path/example/vendor/lib/js/lib.js
EDIT: If you pass an array of patterns to gulp.src() there's no way to specify a different base option for each of the array elements. This for example won't work:
gulp.src(
['source1/examples/**/*.html',
'source2/examples/**/*.html'],
{ base: ['source1/', // Doesn't work.
'source2/']} // Needs to be a string.
).pipe(gulp.dest('dist'));
Instead you have to follow the "Using multiple sources in one task" recipe. This lets you merge two streams each of which can receive its own base option:
var merge = require('merge-stream');
gulp.task('default', function() {
merge(gulp.src('source1/examples/**/*.html', {base: 'source1/'}),
gulp.src('source2/examples/**/*.html', {base: 'source2/'}))
.pipe(gulp.dest('dist'));
});
Related
I recently installed gulp 4 [from 3.9.1] and I'm having an issue getting my globs to work as they used to.
I have a whole directory [less some other sub-directories and files] that I want to transfer.
Here's the relevant code:
var path_in_str = 'my_input_dir/';
var path_out_str = 'my_output_dir/';
return gulp.src([path_in_str+'**', path_in_str+'.*', '!'+path_in_str+'node_modules', '!'+path_in_str+'node_modules/**', '!'+path_in_str+'*.json'], {dot: true})
.pipe(gulp.dest(path_out_str));
Basically, I'm trying to prevent the node_modules folder from being transferred, and I also want to prevent all .json files in the home folder from being transferred as well.
What is happening is that the node_modules directory only [no content] is being transferred. Also, all the .json files are being transferred.
How can I tweak this to fix for Gulp 4's way of handling globs [as it appears to have changed slightly]?
I couldn't get this to work with native gulp, so I thought I'd try the node glob package, and this option seems to work best for the use-case.
First you would need to install it like so:
npm install glob --save-dev
Then reference it in your gulp gile:
var gp_glob = require('glob');
And finally, use it as the glob filter:
var input_list_arr = gp_glob.sync(path_in_str+'**', {ignore: [path_in_str+'node_modules/**', path_in_str+'*.json'], dot: true});
return gulp.src(input_list_arr, {base: path_in_str})
.pipe(gulp.dest(path_out_str));
Take note that we're using the ignore option instead of ! notation to filter the file/directory paths. Also note that the base option is specified when passing the filtered list into gulp.src.
This worked for me as intended. Hope it helps.
I am attempting to concat a few javascript files as part of my gulp build. I am following the "documentation" as much as possible, but there aren't many answers there. Here are the commands I am using.
gulp.task('concatMe', function ()
{
console.log('I am in the concat function.');
return gulp.src(['/app/core/threejs/*.js'])
.pipe(concat('new.js'))
.pipe(gulp.dest('./dist/'));
});
I would think that this takes all of the javascript files in the folder targeted and concatenates them in the new.js file at the desired directory.
While the console log works, nothing is actually done.
How do I know if it found the files I want?
How should the base URL be specified?
How should the destination URL be specified?
Does the destination file and folder need to already exist or will the code create it?
Thanks
In your gulp file, have you included the below line?
var plugin = require("gulp-load-plugins")();
Then you need to modify your code to:
return gulp.src(['/app/core/threejs/*.js'])
.pipe(plugin.concat('new.js'))
.pipe(gulp.dest('./dist/'));
Hope this helps
I'm trying to write a yeoman generator and at one point I need to copy the files/folders of a github repo to the current working directory, eg:
this.remote('owner', 'repo', function (err, remote) {
remote.directory('.', '.');
});
However I want to ignore some of the files in this repo, is it possible to do so? I found the function responsible for this but it doesn't seem to be a clear way to do it, there's a process function that you can pass but I'm not sure if you can "cancel" a file being copied if it matches a certain pattern.
From the mem-fs-editor docs:
For a globified from, you can optionally pass in an
options.globOptions object to change its pattern matching behavior.
See the options here:
Example:
this.fs.copy("<from path>/**", "<to path>",
{
globOptions: {
ignore: [
globs to ignore...
]
}
}
);
You should rely on the this.fs object rather than the old depreciated files methods.
Helper methods on this.fs support glob patterns, so ignoring some files become trivial.
You can learn more about Yeoman file system here: http://yeoman.io/authoring/file-system.html
I have lots of .jade, .styl and .coffee files resided in different subfolders.
I’d like to compile only changed files when they are changed.
I’m using gulp and I’ve come up to the following pattern:
var watch = require('gulp-watch'),
watch(['app/**/*.styl'], function (e) {
gulp.src(e.path)
.pipe(stylus({use: nib()}))
.pipe(gulp.dest('./app'))
However this pattern stores compiled file into the root of ./app folder, but not to the folder where the source file resides.
I’ve tried lots of stuff and all in vain.
The problem is that there is a lack of documentation and samples for gulp-watch and others.
Could anybody tell me how to store compiled file to the its source’s folder?
The problem is that you pass e.path (i.e. the full path of every changed file) as a glob pattern to gulp.src(). This means that your glob pattern does not actually contain a glob (like * or **), in which case the directory where the file is located is used as the default value for the base option to gulp.src(). When the files are then written with gulp.dest() that base option causes the entire directory structure to get stripped.
The solution is to use the streaming variant of gulp-watch instead of the callback variant ...
gulp.src('app/**/*.styl')
.pipe(watch('app/**/*.styl'))
.pipe(stylus({use: nib()}))
.pipe(gulp.dest('./app'));
... or provide an appropriate base option to the callback variant:
watch(['app/**/*.styl'], function (e) {
gulp.src(e.path, {base: 'app'})
.pipe(stylus({use: nib()}))
.pipe(gulp.dest('./app'));
});
I currently use gulp for most of my automation tasks. To keep the process optimised I check for file changes before processing the file. The problem is that when I rebuild my files and only a single file in the set has changed, the concat file only includes the changed file. Is there a way to pickup all the files in case of concat
gulp.task('myScripts', function() {
return gulp.src(['public/js/one.js','public/js/two.js'], {base: 'public/js'})
.pipe(changed('public/dist/original/js'))
.pipe(gulp.dest('public/dist/original/js'))
.pipe(uglify())
.pipe(concat('all.min.js'))
.pipe(gulp.dest('public/dist/js'));
});
I am using gulp-changed to check for file changes, Here are the scenarios:
When running it for the first time, it takes both the miles and minifies them.
When only one file is changed after that, the concatenated file 'all.min.js' only contains the minified version of the changed file.
Can anyone please help me with how I can concat all the files even if only one file changes?
You should require gulp-remember and call it before concat. Gulp-remember works with gulp-changed and restores the previous changed files into the stream.
Have a look to this official recipe: Incremental rebuilding, including operating on full file sets