Piping concat through gulp.src changes gulp.src glob - javascript

I'm still fairly new to gulp, so this might be a misunderstanding on my part.
I have gulp pipeline I'm trying to create that does something like this:
gulp.src('src/**/*.html')
.pipe(html2js({some:options}))
.pipe(concat('templates.js'))
.pipe(gulp.src('src/**/*.js'))
.pipe(uglify())
.pipe(gulp.dest('build/'))
When I run this however, the second glob does not catch all the .js files. If I run two separate piplines as:
gulp.src('src/**/*.html')
.pipe(html2js({some:options}))
.pipe(concat('template.js'))
.pipe(gulp.dest('build/'));
gulp.src(['src/**/*.js', 'build/template.js'])
.pipe(uglify())
.pipe(gulp.dest('build/'));
It works as expected. No errors appear to be thrown and in the first case, the template.js is added to the end of the file list as I would expect.
Any suggestions would be greatly appreciated.

You should check out gulp-merge. It's designed to combine gulp pipelines:
var gulpMerge = require('gulp-merge');
gulp.task('build', function() {
return gulpMerge(
gulp.src('src/**/*.html')
.pipe(html2js({some:options}))
.pipe(concat('template.js')),
gulp.src('src/**/*.js')
)
.pipe(uglify())
.pipe(gulp.dest('build/'));
});

Gulp.src accepts a glob and options so it can't handle the stream that's piped into it in your first sample script.
You may use an approach similar to your first one using gulp-filter:
var filter = gulpFilter('**/*.html');
gulp.src(['src/**/*.html', 'src/**/*.js'])
.pipe(filter)
.pipe(html2js({some:options}))
.pipe(concat('templates.js'))
.pipe(filter.restore())
.pipe(uglify())
.pipe(gulp.dest('build/'))
Otherwise, following the lines of your second sample, you can use merge-stream for merging the streams before uglifying:
var merge = require('merge-stream');
var htmlStream = gulp.src('src/**/*.html')
.pipe(html2js({some:options}))
.pipe(concat('template.js'));
return merge(htmlStream, gulp.src('src/**/*.js'))
.pipe(uglify())
.pipe(gulp.dest('build/'));

Related

Why isn't my gulp task running?

I'm using the following code because grabbing the whole js folder won't honor file sequence. So I select file by file, but it won't produce the site.min.js file even though no error is given.
gulp.task("minjs", function () {
gulp.src([
'js/site.js',
'js/directives/navbar.js',
'js/directives/Select.Lang.js'
])
.pipe(concat('site.min.js'))
.pipe(uglify())
.pipe(gulp.dest("wwwroot/js/"));
});
Updated:
No, it's not the return. I tried that too. I also searched trough my PC if a file was generated, but there's no file and the weirdest thing is that the gulp task shows no error.
Notice the return statement:
gulp.task("minjs", function () {
return gulp.src([
'js/site.js',
'js/directives/navbar.js',
'js/directives/Select.Lang.js'
])
.pipe(concat('site.min.js'))
.pipe(uglify())
.pipe(gulp.dest("wwwroot/js/"));
});

gulp.src pattern only matches last file

I am trying to browserify all my 'spec' files in my tests folder,
gulp.task('browserifyTests',function(){
return gulp.src(['./tests/**/spec*.js'])
.pipe($$.browserify()
)
.pipe($$.rename('specs.bundle.js'))
.pipe(gulp.dest('tests'));
});
I have 2 files specA.js and specB.js under tests/specs folder. When I browserify, I only see specB.js in the specs.bundle.js. Its really baffling why such a thing should happen when the pattern should clearly match here right? Or am I doing something silly..
Actually, I did a gulp-print and I see both file names printed too.
AFAIK, you can't use Browserify in Gulp like that (because it's not a Gulp plugin).
Try this:
const source = require('vinyl-source-stream');
const glob = require('glob').sync;
gulp.task('js', () => {
return $$.browserify(glob('./tests/**/spec*.js'), {...})
.bundle()
.pipe(source('specs.bundle.js'))
.pipe(gulp.dest('./tests/'));
});
More info here (in particular, "Using them together: Gulp + Browserify").

How to make Gulp complete one task, and only then start the next one

I've set up some simple Gulp tasks to process my CSS files.
The tasks are put together in one 'master' task:
gulp.task('process-css', ['concatCSS', 'minifyCSS', 'renameCSS']);
Just for reference, the definition of the concrete tasks follows:
gulp.task('minifyCSS', function() {
return gulp.src('themes/my_theme/css/dist/*.css')
.pipe(sourcemaps.init())
.pipe(minifyCSS())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('themes/my_theme/css/dist/'));
});
gulp.task('concatCSS', function() {
var files = [
'themes/rubbish_taxi/css/bootstrap.css',
'themes/rubbish_taxi/css/custom.css',
'themes/rubbish_taxi/css/responsive.css',
'themes/rubbish_taxi/css/jquery.fancybox.css'
];
return gulp.src(files)
.pipe(concat("bundle.css"))
.pipe(gulp.dest('themes/my_theme/css/dist/'));
});
gulp.task('renameCSS', function() {
gulp.src('themes/my_theme/css/dist/bundle.css')
.pipe(rename(function(path) {
path.basename += ".min";
}))
.pipe(gulp.dest("themes/my_theme/css/"));
});
The tasks complete without an error, but the problem is that minifyCSS does not minify the source file. An unminified version of the files is saved as bundle.min.css. I believe that the reason is that minifyCSS runs before concatCSS completed.
How can I make the tasks be executed synchronously?
Is my only option to specify which tasks should be executed before a give task like this:
gulp.task('minifyCSS', ['concatCSS'], function() {..} ?
It worked when I set it this way, but I wanted to avoid this to make code more readable.
gulp.task('minifyCSS', ['concatCSS'], function() {..} ?
It worked when I set it this way, but I wanted to avoid this to make code more readable.
More readable how? You're stating that minifyCSS is dependent on concatCSS. The line of code I quoted above is how you explain this dependency to gulp.
The alternative is to use something like run-sequence, but I think avoiding functionality built into the tool to solve the exact problem you're facing isn't justified by the desire for a subjective improvement in readability.

Is there a way to use gulp to remove all instances of require.js define([...]) wrappers?

I would like to test my app without require.js to see what the performance and file size would be like as a single concatenated file.
I'm thinking of using gulp to grab all app *.js files, perform a gulp-replace to remove all instances of the the define([...], function (...) { }); wrapper in the script, and the concatenate into a single *.js file.
Any idea if gulp-replace could handle that, and if so, what would the regex look like? Here's an example of a *.js file:
'use strict';
define(['file1', 'file2', 'file3'], function (param1, param2, param3) {
//...
//code that should remain after gulp-replace
//...
});
Solution for anyone else attempting to try the same:
var gulp = require('gulp'),
concat = require('gulp-concat'),
replace = require('gulp-replace'),
uglify = require('gulp-uglify');
gulp.src(['src/**/*.js', '!src/main.conf.js', '!src/**/*_test.js'])
.pipe(replace(/'use strict';/g, ''))
.pipe(replace(/define\s?\(\[.*\],\s?function\s?\(.*\)\s?\{/g, ''))
.pipe(replace(/\}\)\;\s?$/g, ''))
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(gulp.dest('dist'));
Assumption is that you are only targeting require.js files. If you have compile errors, try using gulp-debug to figure out which file is throwing the errors.
Assumption is that it doesn't matter which order these files load in, which is the case with an AngularJS app. But if order is important, you can set the desired order in the array you pass into gulp.src.

Pipe vendor js files from Bower and own js files into unique stream in Gulp

I'd like to grab my vendor js files from bower dependencies, and, along with my own js files, pipe through some other tasks and concat them into one .js file. And then do the same for Sass files.
How could I achieve that? I tried this, but it doesn't work:
gulp.task('scripts', function () {
return gulp.src([
mainBowerFiles(gulpFilter('*.js')),
'app/js/*.js'
])
.pipe(uglify())
.pipe(concat('app.js'))
.pipe(gulp.dest('./dist/js'));
});
It throws this error:
TypeError: Arguments to path.resolve must be strings
But it works if I have this, for example:
gulp.src([
'app/js/etc.js',
'app/js/main.js'
])
..and in the following case, it throws a different error (but no error without uglify()):
gulp.src(mainBowerFiles(gulpFilter('*.js')))
error:
events.js:72
throw er; // Unhandled 'error' event
How do I better debug this? Should I separate vendor / own js files in different streams?
update
I'm working now with two streams, and merging them later on with event-stream, like this:
gulp.task('scripts', function () {
var jsFilter = gulpFilter('*.js');
var vendorFiles = gulp.src(mainBowerFiles()) // don't read
.pipe(jsFilter)
.pipe(concat('vendor.js'));
var appFiles = gulp.src('app/js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(concat('app.js'));
return es.concat(vendorFiles, appFiles)
.pipe(uglify())
.pipe(concat('app.js'))
.pipe(gulp.dest('./dist/js'));
});
It works great, but I'm not able to handle the order of the files. Obviously I'd like that the vendor code come before my code at the destination's app.js, but that's doesn't happen. I created a thread about that here.
Solved it with gulp-event-stream and gulp-order. Intrigues me a little that gulp-order is trending downward at https://www.npmjs.org, though.
gulp.task('scripts', function () {
var jsFilter = gulpFilter('*.js');
var vendorFiles = gulp.src(mainBowerFiles())
.pipe(jsFilter)
.pipe(concat('vendor.js'));
var appFiles = gulp.src('app/js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(concat('app.js'));
return eventStream.concat(vendorFiles, appFiles)
.pipe(order([
"vendor.js",
"app.js"
]))
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist/js'));
});
mainBowerFiles() returns an array. gulp.src is expecting an array of strings, not nested arrays, which is likely the cause of the first problem. You could try the following instead:
gulp.src(mainBowerFiles(gulpFilter('*.js')).push('app/js/*.js'))
I'm not sure what's causing the unhandled error event, but you could try using gulp-debug to get more information.

Categories