I was learning gulp. I had come thru following code.
wrench.readdirSyncRecursive('./gulp').filter(function(file) {
return (/\.(js|coffee)$/i).test(file);
}).map(function(file) {
require('./gulp/' + file);
});
Can somebody help me to understand what above code is useful for?
This will load all js or coffee files in the gulp directory in order to load all gulp tasks, so you dont have to manually import new gulp tasks, just create whatevergulptask.js inside '/gulp' directory and you can use it from the command line.
Another advange of doing it like this is that you dont have a huge gulpfile.js with millions of tasks and lines of code, as instead you have a whatevergulptask.js per TASK, just a good practice cos the gulpfile grows pretty fast
Example gulpfile.js
/**
* Welcome to your gulpfile!
* The gulp tasks are splitted in several files in the gulp directory
* because putting all here was really too long
*/
'use strict';
var gulp = require('gulp');
var wrench = require('wrench');
/**
* This will load all js or coffee files in the gulp directory
* in order to load all gulp tasks
*/
wrench.readdirSyncRecursive('./gulp').filter(function (file) {
return (/\.(js|coffee)$/i).test(file);
}).map(function (file) {
require('./gulp/' + file);
});
/**
* Default task clean temporaries directories and launch the
* main optimization build task
*/
gulp.task('default', ['clean'], function () {
gulp.start('build');
});
YOUR FOLDER STRUCTURE
gulp/
build.js
whatevergulptask.js
...
Related
Project structure:
📁 development
📁 public
📁 pug
📁 1sass
📁 2css
📁 admin
📁 pug
📁 3sass
📁 4css
I add digits to folder names to imitate the situations when gulp can not guess somehow which output folder is respects to input ones.
Now, I want to compile .sass files in public/1sass and admin/3sass to .css and put it in public/2css and admin/4css respectively:
📁 public/1sass → 📁 public/2css
📁 admin/3sass → 📁 admin/4css
How I need to setup the sass task in gulpfile? Even if we put the paths array to gulp.src, how gulp will understand which output path respects to input ones?
Maybe gulp.parallel() becomes available in gulp 4.x will do?
Update
Two things that I did not understand yet:
How I should to setup the multiple output paths in gulp.dest()?
I learned that file.dirname = path.dirname(file.dirname); removes the last parent directory of the relative file path.But how I should to setup it for each of 1sass ans 3sass? Via array?
const gulp = require('gulp'),
sass = require('gulp-sass'),
path = require('path'),
rename = require('gulp-rename');
gulp.task('sass', function(){
return gulp.src([
`development/public/1sass/*.sass`,
`development/public/3sass/*.sass`])
.pipe(sass())
// As I can suppose, here we must to setup output paths for each input one
.pipe(rename(function(file){
file.dirname = path.dirname(file.dirname);
}))
.pipe(/* ??? */);
});
Simply in case of dynamic src and you want respective same dest (as received in src) then you can use following
Example Suppose we have array of scss file:
var gulp = require('gulp');
var sass = require('gulp-sass');
var scssArr = [
'src/asdf/test2.scss',
'src/qwerty/test1.scss'
];
function runSASS(cb) {
scssArr.forEach(function(p){
gulp.src(p, {base:'.'})
.pipe(sass({outputStyle: 'compressed'}))//outputStyle is optional or simply sass()
.pipe(gulp.dest('.')); //if othe folder including src path then use '/folder-name' instead of '.', so output path '/folder-name/{src-received-path}'
})
cb();
}
exports.runSASS = runSASS; // gulp runSASS
Run command gulp runSASS This will create following files:
src/asdf/test2.css
src/qwerty/test1.css
Happy Coding..
See my answer to a similar question: Gulp.dest for compiled sass. You should be able to modify that easily for your purposes. If you have trouble edit your question with your code and you will get help.
Even if we put the paths array to gulp.src, how gulp will understand which output path respects to input ones?
Gulp will retain the relative paths for each file that it processes. So, in your case, the files in public/1sass will all have their relative path info after sass processing still intact. And the files in admin/3sass will all have their relative path info as well. Thus you only need to find a way to modify that path info (parent directory structure) to redirect the files to a desired destination.
In your case, that would involve removing the immediate parent directory and replacing it with the 'css' directory. Gulp-rename is one way, not the only way, to do that. In gulp-rename you can examine and modify the parent directory structure - it is just string manipulation.
Maybe gulp.parallel() becomes available in gulp 4.x will do?
No, gulp.parallel() will not be of any help here. It will just order the execution and finishing of different tasks. It would not be necessary or of any real help in your case.
[EDIT]
var gulp = require("gulp");
var rename = require("gulp-rename");
var path = require("path");
var sass = require("gulp-sass");
gulp.task('modules-sass', function () {
// using .scss extensions for sass files
return gulp.src(`development/**/*.scss`)
.pipe(sass())
.pipe(rename(function (file) {
// file.dirname before any changes
console.log("file.dirname 1 = " + file.dirname);
// this removes the last directory
var temp = path.dirname(file.dirname);
console.log(" temp = " + temp);
// now add 'Css' to the end of the directory path
file.dirname = path.join(temp, 'Css');
console.log(" after = " + file.dirname);
}))
.pipe(gulp.dest('development'));
});
// this is the directory structure I assumed
// gulpfile.js is just above the 'development' directory
// development / Admin / Sass1 / file1.scss
// development / Admin / Sass1 / file2.scss
// development / Admin / Sass2 / file3.scss
// development / Admin / Sass2 / file4.scss
// development / Admin / Css
// development / Public / Sass1 / file5.scss
// development / Public / Sass1 / file6.scss
// development / Public / Sass2 / file7.scss
// development / Public / Sass1 / file8.scss
// development / Public / Css
I want to put inside gulpfile something like:
require('web-component-tester').gulp.init(gulp);
gulp.task('default', function() {
gulp.watch(['elements/**', 'test/**'], ['test:local']);
});
The purpose is to watch test folders or elements folders (with Polymer components). If some of them will change, run test with each build.
my wct.conf.js:
module.exports = {
root: '.tmp/elements/',
suites: ['**/test/'],
plugins: {
local: {browsers: ['chrome']},
}
};
I found the code above on some page but after I add some tests and then type gulp in my terminal I found error, because .tmp folder is not updated and strange errors like Polymer is not definedor ajax.generateRequest is not a function. I got also right errors when I intentionally made a mistake in a test to fail it, so it looks like something is ok, but not at all.
I add the tests to the existing project with lots of files. When I tried to do the same thing on empty project I also got the same error until I type bower install.
Is there any chance that this is the problem with bower dependencies?
Or have you any idea what is wrong? Is this part of code in gulpfile right to perform the desired effect?
Thanks a lot.
I am not answering your question directly, because its been a while since I've done it that way. But the following defines a sub task from among others to define a task called 'client' which then runs the tests in a frame buffer (so I don't have disturbing windows popping up all over the place when the tests run - they just run and output in a console window. Its effectively spawning a command line version of wct and I don't have a wct.conf file at all.
(function() {
'use strict';
const spawn = require('child_process').spawn;
module.exports = function(gulp) {
gulp.task('test:client',['lint:client'], () => {
var child = spawn('xvfb-run', ['-a', 'wct', '--color'], {cwd: process.cwd()});
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
process.stdout.write(data);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
process.stderr.write(data);
});
});
gulp.task('client',function() {
gulp.watch([
'app/index.html',
'app/src/*.html',
'app/test/*.html',
'aoo/mocks/*.html',
'gulpfile.js',
'tasks/*.js'
],['test:client']);
});
};
})();
This file is one file within the tasks directory (which as you can see I am watching)
My gulpfile loads this, and other tasks like so (I copied this from the angular.js team who used it to load some of there tasks supporting angular)
(function() {
'use strict';
require('dotenv').config(); //load our environment
var gulp = require('gulp');
var includeAll = require('include-all');
/**
* Loads task modules from a relative path.
*/
function loadTasks(relPath) {
return includeAll({
dirname: require('path').resolve(__dirname, relPath),
filter: /(.+)\.js$/
}) || {};
}
// *
// * Invokes the function from a Gulp configuration module with
// * a single argument - the `gulp` object.
function addTasks(tasks) {
for (var taskName in tasks) {
if (tasks.hasOwnProperty(taskName)) {
tasks[taskName](gulp);
}
}
}
/**
* Add all Gulp tasks to the gulpfile.
* Tasks are in `tasks/`
*/
addTasks(loadTasks('tasks/'));
// require('gulp-load-tasks')(__dirname + '/tasks');
gulp.task('default', ['lint:gulp','client','server']);
})();
I have a gulp task to move fonts:
gulp.task('move', function(cb) {
return gulp.src('./packages/my-package#1.0.17-alpha.3/fonts/*')
.pipe(gulp.dest('./build/fonts/'));
});
This working however the my-package number will change. Im trying to alter the gulp task so that it will still work when the package number changes:
gulp.task('move', function(cb) {
return gulp.src('./packages/my-package#*/fonts/*')
.pipe(gulp.dest('./build/fonts/'));
});
This does move the fonts but it also adds some folders.
This is what it does:
./build/fonts/my-package#1.0.17-alpha.3/fonts/ (fonts here)
What I need is this:
./build/fonts/ (fonts here)
Ive fixed this with gulp-flatten:
var flatten = require('gulp-flatten');
gulp.task('move', function(cb) {
return gulp.src('./packages/my-package#1.0.17-alpha.3/fonts/*')
.pipe(flatten())
.pipe(gulp.dest('./build/fonts/'));
});
https://www.npmjs.com/package/gulp-flatten
I'm trying to use these two gulp plugins together:
gulp-html-minifier
gulp-inject-stringified-html
Or put differently, I'm trying to inject the contents of files containing html fragments into my javascript files after they're minified.
When I'm trying to run a straight up gulp build I get this:
Error: ENOENT: no such file or directory, open 'C:\path\to\.temp\template.html'
Here's a repro of my situation. My folder structure:
/src/app.js
/src/template.html
/gulpfile.js
/package.json
My gulpfile.js:
var gulp = require('gulp');
var injectHtml = require('gulp-inject-stringified-html');
var htmlmin = require('gulp-html-minifier');
gulp.task('minify', [], function() {
gulp.src('src/*.html')
.pipe(htmlmin())
.pipe(gulp.dest('.temp'));
});
gulp.task('default', ['minify'], function() {
gulp.src('src/*.js')
.pipe(injectHtml())
.pipe(gulp.dest('.build'));
});
The template.html file:
<div>My Template</div>
The app.js file:
var html = { gulp_inject: "../.temp/template.html" };
Now, if I run minify manually first, things will work as expected. From this I speculate I'm not using Gulp correctly. I reckon I'd need to pipe the result of htmlmin into the injectHtml method. But I fail to see how.
How can I get these two plugins to play together nicely?
You are missing a return in the minify task. It should look like that:
gulp.task('minify', [], function() {
return gulp.src('src/*.html')
.pipe(htmlmin())
.pipe(gulp.dest('.temp'));
});
Without return, the default task doesn't have any way to know that minify finished, so it may start before the minified html file was created.
I am using yii2 to build a web service. And to help me to put together all the things I use gulp. I have a file structure similar to this
gulpfile.js
index.php
basics/
-composer.json
-vendor/
after you get all the dependencies using composer they save into vendor folder. The problem is that for some reason yii2 saves bower asset in a folder called bower-asset, but it will only work if the folder is called bower. So I wrote these two tasks to help me with this. task one copies the content of bower-asset folder into bower folder in the same directory and the second task deletes bower-asset folder. My problem occurs when task two is ran from default task. Then it returns an error like this
[15:11:20] Starting 'bower-del'...
events.js:85
throw er; // Unhandled 'error' event
^
Error: ENOENT, lstat '/Users/Me/Documents/mamp/dumb/game/basic/vendor/bower-asset/jquery/dist'
at Error (native)
It also appears if I try to tell task to to wait for task one to be finished before task two starts like
gulp.task('bower-del', ['bower-copy'], function () {
The thing that surprises me the most is that if I run task two by itself ie gulp bower-del it deletes the folder no problem.
I have taken other tasks from my gulp file for simplicity purposes.
This is what my gulp tasks look like:
// Copies bower-asset into bower folder
gulp.task('bower-copy', function(){
gulp.src('./basic/vendor/bower-asset/**/*')
.pipe(gulp.dest('basic/vendor/bower/'));
});
// Deletes old bower-asset folder
gulp.task('bower-del', function () {
return gulp.src('./basic/vendor/bower-asset/', {read: false})
.pipe(clean());
});
gulp.task('default', ['bower-copy', 'bower-del']);
You should run de bower-del in sequence. In my SkeletonSpa I have the same issue with cleaning before a build. Here I have 2 tasks clean and build, where the build task should only run when the clean task is finished, eg. they should not run in parallel.
My implementation is as follows:
gulp.task('build', (cb) => {
let runSequence = require('run-sequence');
runSequence('clean', ['info', 'styles', 'scripts', 'images', 'copy'], 'todo', cb);
});
gulp.task('clean', ['clear-cache'], () => {
let del = require('del');
let vinylPaths = require('vinyl-paths');
return gulp.src([settings.dist, settings.reports])
.pipe(vinylPaths(del));
});
This will do the trick. Just take a look at the run-sequence plugin and implement it ;-)