Consider the following two files:
config.json
{
"vendorFiles": [
"vendor/angular/angular.js",
"vendor/angular-ui-router/release/angular-ui-router.js",
"vendor/angular-ui-utils/modules/utils.js"
]
}
gulpfile.js
var gulp = require("gulp"),
concat = require("gulp-concat"),
config = require("./config");
gulp.task("build-vendor", function() {
gulp.src(config.vendorFiles)
.pipe(concat("vendor.js"))
.pipe(gulp.dest("build"));
});
How can I eliminate the need to specify vendor/ for each file in config.json? That file is one that is manually edited by other developers by hand, so I want to make it as hassle-free on them as possible.
Ideally I'd like my gulpfile.js to take care of adding that prefix (somehow), and for my config.json to look like this:
{
"vendorFiles": [
"angular/angular.js",
"angular-ui-router/release/angular-ui-router.js",
"angular-ui-utils/modules/utils.js"
]
}
There may be a better way with a Gulp specific solution, but this should work.
var gulp = require("gulp"),
concat = require("gulp-concat"),
config = require("./config");
gulp.task("build-vendor", function() {
gulp.src(config.vendorFiles.map(function(a) {return 'vendor/' + a}))
.pipe(concat("vendor.js"))
.pipe(gulp.dest("build"));
});
Demo:
http://jsfiddle.net/AK4tP/
Can't you just do
var gulp = require("gulp"),
concat = require("gulp-concat"),
config = require("./config");
gulp.task("build-vendor", function() {
gulp.src(config.vendorFiles, {root: 'vendor/'})
.pipe(concat("vendor.js"))
.pipe(gulp.dest("build"));
});
Gulp should accept root option in src() although it's not documented.
Related
I have been working on modifying this relatively simple gulpfile/project: https://github.com/ispykenny/sass-to-inline-css
The first issue I had was to update to gulp v4, but I've also tried to store variables for my src and destination folders which is a bit easier to control. So now my gulpfile looks like this:
const gulp = require('gulp');
const inlineCss = require('gulp-inline-css');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
const plumber = require('gulp-plumber');
const del = require('del');
const srcFolder = './src'; // TODO tidy this up once working
const buildFolder = srcFolder + '/build/'; // Tidy this up once working
const src = {
scss: 'src/scss/**/*.scss',
templates: 'src/templates/**/*.html'
}
const dest = {
build: 'build/',
css: 'build/css'
};
function processClean() {
return del(`${buildFolder}**`, { force: true });
}
function processSass() {
return gulp
.src(src.scss)
.pipe(plumber())
.pipe(sass())
.pipe(gulp.dest(dest.css))
.pipe(browserSync.stream())
}
function processInline() {
return gulp
.src('./*.html')
.pipe(inlineCss({
removeHtmlSelectors: true
}))
.pipe(gulp.dest('build/'))
}
function processWatch() {
gulp.watch(['./src/scss/**/*.scss'], processSass);
gulp.watch(srcFolder).on('change', browserSync.reload);
gulp.watch(distFolder).on('change', browserSync.reload);
}
const buildStyles = gulp.series(processSass, processInline);
const build = gulp.parallel(processClean, buildStyles);
gulp.task('clean', processClean);
gulp.task('styles', buildStyles);
gulp.task('sass', processSass);
gulp.task('inline', processInline);
gulp.task('build', build);
gulp.task('watch', processWatch);
But I am now wanting to create lots of template files, store them in a subfolder and have gulp spit out each file into the destination folder. if I have index.html, test1.html etc in the root it works fine.
I tried modifying this:
function processInline() { return gulp.src('./*.html')
To this:
function processInline() { return gulp.src(src.templates) // should equate to 'src/templates/**/*html'
Now I'm seeing this error in the console:
ENOENT: no such file or directory, open 'C:\Users\myuser\pathToApp\emailTemplates\src\templates\build\css\style.css'
In the head of index.html in the root is this:
<link rel="stylesheet" href="build/css/style.css">
I actually don't really care about the css file as the final output should be inline (for email templates). But I cannot get my head around why this is happening.
Does gulp create the css file and then read the class names from there? EDIT, Ah I guess it must because it has to convert the sass to readable css first before stripping out the class names and injecting the inline styles.
Years ago I worked with grunt a fair bit, and webpack, but haven't done much with gulp.
I hope it is obvious, but if you need more information just let me know.
I have this gulpfile:
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify');
gulp.task('minifyJS', function() {
return gulp.src(['src/*.js'])
.pipe(uglify())
.pipe(gulp.dest('min'));
});
gulp.task('watch', function() {
gulp.watch(['src/*.js'], ['minifyJS']);
});
I want to know what file trigger the watcher and his absolute path.
For example: if my project is placed in /myCode and I change the file src/main.js, I want to see /myCode/src/main.js inside minifyJS task. Is there a way to do it?
Thank you for your time.
You can do it by using gulp-ng-annotate and gulp-changed:
var gulp = require('gulp');
var changed = require('gulp-changed');
var rename = require('gulp-rename');
var ngAnnotate = require('gulp-ng-annotate'); // just as an example
var SRC = 'src/*.js';
var DEST = 'src/';
//Function to get the path from the file name
function createPath(file) {
var stringArray = file.split('/');
var path = '';
var name = stringArray[1].split('.');
stringArray = name[0].split(/(?=[A-Z])/);
if (stringArray.length>1) {stringArray.pop()};
return {folder: stringArray[0], name: name[0]}
}
gulp.task('default', function () {
return gulp.src(SRC)
.pipe(changed(DEST))
// ngAnnotate will only get the files that
// changed since the last time it was run
.pipe(ngAnnotate())
.pipe(rename(function (path) {
var createdPath = createPath(path);
path.dirname = createdPath.folder;
path.basename: createdPath.name,
path.prefix: "",
path.suffix: "",
path.extname: ".min.js"
}))
.pipe(gulp.dest(DEST));
});
Result:
Use gulp-changed npm package.
$ npm install --save-dev gulp-changed
Try the below in gulp file, (I haven't tried)
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
changed = require('gulp-changed');
gulp.task('minifyJS', function() {
return gulp.src(['src/*.js'])
.pipe(changed('min'))
.pipe(uglify())
.pipe(gulp.dest('min'));
});
gulp.task('watch', function() {
gulp.watch(['src/*.js'], ['minifyJS']);
});
see the documentation of this package https://www.npmjs.com/package/gulp-changed
Based on your comment to Julien's answer this should be fairly close to what you want, or at least get you going in the right direction:
var gulp = require('gulp'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
cache = require('gulp-cached'),
rename = require('gulp-rename'),
path = require('path');
function fileName(file) {
return file.dirname + path.sep + file.basename + file.extname;
}
gulp.task('minifyJS', function() {
return gulp.src(['src/*.js'])
.pipe(cache('minifyJS'))
.pipe(rename(function(file) {
var nameOfChangedFile = fileName(file);
if (nameOfChangedFile == './main.js') {
file.basename = 'main.min'
}
if (nameOfChangedFile == './userView.js') {
file.basename = 'user/userView.min'
}
console.log(nameOfChangedFile + ' -> ' + fileName(file));
}))
.pipe(uglify())
.pipe(gulp.dest('min'));
});
gulp.task('watch', function() {
gulp.watch(['src/*.js'], ['minifyJS']);
});
This uses gulp-cached to keep an in-memory cache of all the files in your src/ folder that have passed through the stream. Only files that have changed since the last invocation of minifyJS are passed down to the gulp-rename plugin.
The gulp-rename plugin itself is then used to alter the destination path of the changed files.
Note: the cache is empty on first run, since no files have passed through the gulp-cached plugin yet. This means that the first time you change a file all files in src/ will be written to the destination folder. On subsequent changes only the changed files will be written.
I'm using Gulp in a VS2015 project to run jscs on JavaScript files with the fix option set. The intention is to modify the same file that is read (viz., source and destination are the same).
var gulp = require('gulp');
var jscs = require('gulp-jscs');
var chmod = require('gulp-chmod');
var exec = require('gulp-exec');
var ourJsFiles = // an array of files and globbed paths
gulp.task('jscs', function (callback) {
ourJsFiles.forEach(function (fn) {
gulp.src(fn, { base: './' })
.pipe(jscs({
"preset": "google",
"maximumLineLength": 160,
"validateIndentation": 3,
"fix": true
}))
.pipe(gulp.dest('./'));
});
callback();
});
But I do not want to process any files that are read-only. Is there already a way to detect this in Gulp on Windows?
There is a plugin which allows you to work with subset of files: gulp-filter.
One of options is to pass filter function which will receive vinyl file object, so for e.g. you could use stat.mode property of that object which holds permissions and do something like:
var filter = require('gulp-filter');
...
var writableFiles = filter(function (file) {
//https://github.com/nodejs/node-v0.x-archive/issues/3045
var numericPermission = '0'+(e.stat.mode & parseInt('777', 8)).toString(8);
return numericPermission[1]==='6'
});
...
gulp.src(....)
.pipe(writableFiles)
Is there a way to set the working directory for Gulp within a gulpfile, so that I can run a gulp command from a subdirectory without running into any issues? I ran a search for this and didn't find what I was looking for.
To clarify, I'm aware of adding a prefix to the files I'm using. However, instead of this -
var gulp = require('gulp');
var jshint = require('gulp-jshint');
...
var paths = {
js: [__dirname + 'app/*/*.js', __dirname + '!app/lib/**'],
css: __dirname + 'app/*/*.styl',
img: __dirname + 'app/img/*',
index: __dirname + '*.html',
dist: __dirname + 'dist'
};
I'd like to do something like this:
var gulp = require('gulp');
var jshint = require('gulp-jshint');
...
gulp.cwd(__dirname); // This would be much easier to understand, and would make future edits a bit safer.
var paths = {
js: ['app/*/*.js', '!app/lib/**'],
css: 'app/*/*.styl',
img: 'app/img/*',
index: '*.html',
dist: 'dist'
};
I'm wondering if Gulp exposes this functionality. Perhaps node itself allows this.
(I realize that there is likely a way to do command line itself when I run the command, but I would like to include it in the gulp file, especially for distribution purposes. I want the working directory for gulp to match the directory in which the gulpfile resides.)
Thanks!
Besides option.cwd, you can also use process.chdir(yourDir)
it could be used anywhere in a gulpfile. e.g.
process.chdir(yourDir);
var gulp = require('gulp');
Make sure your gulp is up-to-date( > 3.8.10), this may not work in older gulp.
Instead of concatenating strings by yourself, you should be using path.join since it will take care of the proper slash, and following that path you can add a shorcut:
var path = require('path'),
p = function () {
Array
.prototype
.unshift
.call(arguments, __dirname);
return path.join.apply(path, arguments);
};
console.log(p('a', 'b', 'c'));
Or, well, you can just:
gulp.src(..., {cwd: __dirname})
gulp.dest(..., {cwd: __dirname})
Something like:
var src = function (globs, options) {
options = options || {};
options.cwd = __dirname;
return gulp.src(globs, options);
};
var dest = function (folder, options) {
options = options || {};
options.cwd = __dirname;
return gulp.dest(folder, options);
};
Look here and here.
I am trying to get any variation of hbsfy or browserify-handlebars to compile correctly using browserify. Compiling results in the handlebars.js(hbsfy) code outputting to my browser. I've tried just using the browserify command browserify -t hbsfy app.js > bundle.js but it doesn't change anything
I haven't the reputation to post images but basically this is the output:
var templater = require("handlebars/runtime").default.template;module.exports = templater(function (Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; var buffer = "", stack1, helper, functionType="function", escapeExpression=this.escapeExpression; buffer += "
Hello "; if (helper = helpers.name) { stack1 = helper.call(depth0, {hash:{},data:data}); } else { helper = (depth0 && depth0.name); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; } buffer += escapeExpression(stack1) + "
"; return buffer; });
My template (template.hbs) is simply <h1>Hello {{name}}</h1>
My gulpfile setup:
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var browserify = require('gulp-browserify');
var hbsfy = require('browserify-handlebars');
//var hbsfy = require('hbsfy'); //this one shows up the same way
gulp.task('scripts', function() {
return gulp.src('./app/app.js')
.pipe(browserify({
transform: [hbsfy]
}))
.pipe(rename('bundle.js'))
.pipe(gulp.dest('./build/js'))
.pipe(connect.reload());
});
and my js file:
var Handlebars = require('hbsfy/runtime');
var $ = require('jquery'),
router = require('./router/routerDefault'),
template = require('./template.hbs');
$(document).ready(function(){
document.body.innerHTML = template({name: 'browserify'});
})
Does anyone have any experience on how to handle this? Any suggestions would be heplful!
The cause of this issue is redundant compiling. Listing a transform in both the packages.json and the gulpfile.js will perform it twice, I believe. In my packages.json, I now just use this 'node':
"browserify": {
"transform": [
"hbsfy"
]
},
This will compile your templates for you. Your gulpfile.js DOES NOT require this section:
.pipe(browserify({
transform: [hbsfy]
}))
You can use either one. My scripts gulp task now looks like this:
gulp.task('scripts', function() {
return browserify('./app/app.js')
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./build/js'))
.pipe(connect.reload());
});
I am experiencing something similar.
Just curious, what OS are you using? Seems to affect Mac but Windows seems OK.
I'm not entirely sure what's causing this but I stopped using gulp-browserify as it is now blacklisted.
I followed the suggestions from this blog post and it seems to solve the issue: http://viget.com/extend/gulp-browserify-starter-faq
The last bit is most relevant.
EDIT:
While using gulp-browserify, I would also check if you've listed your transforms in package.json. I think you may only need to specify transforms in one place (either in gulpfile as you have now or in package.json).