Gulp js src : get deepest files first - javascript

I use Gulp to build a small web application based on the React framework.
To compile the client scripts, my task starts like that :
gulp.task( 'buildClientScripts', function () {
// Get all the js and jsx scripts
// Starts with the app.js file
return gulp.src( [
'app/app.js',
'app/clientScripts/**/*.jsx',
'app/clientScripts/**/*.js',
] )
The order of the files is my problem. For this file structure :
- clientScripts
---- components
-------- subComponents
------------ mysubComponent.js
-------- myComponent.js
---- main.js
The load order will be : main.js, myComponent.js, mysubComponent.js. But obviously, my top files need the deeper files to work.
How do I ask gulp to load the deepest files first ?

You can use gulp-sort to order the files after gulp.src reads them.
Count slashes in path as crude way to determine depth.
var sort = require('gulp-sort');
var path = require('path');
gulp.task( 'buildClientScripts', function () {
// Get all the js and jsx scripts
// Starts with the app.js file
return gulp.src( [
'app/app.js',
'app/clientScripts/**/*.jsx',
'app/clientScripts/**/*.js',
] )
.pipe(sort(function(file1, file2) {
return countSlashes(file2) - countSlashes(file1);
function countSlashes(file) {
return file.path.split(path.sep).length - 1;
}
})

Related

How to use js-cookie in a standalone *.js script?

I am using gulp to concatenate and minify a number of standalone *.js scripts used on my web site. Basically this is just a catchall folder where I place little utility scripts that run on page load. For example, one of them starts a carousel slider, another adds a class to the header that shrinks it on scroll, etc. Each of these "features" has its own standalone *.js file.
Now, I would like to use the popular js-cookie library in one of those scripts. Unfortunately, since my project is not set up as an ES6 module, I am not able to able to import the js-cookie library the way it's specified in the docs, like this:
import Cookies from 'js-cookie'
When I do this, I get the error message Uncaught SyntaxError: Cannot use import statement outside a module.
I tried changing it to this:
window.Cookies = require('js-cookie')
but that gave me this error:
Uncaught ReferenceError: require is not defined
Here is my gulpfile, followed by the feature.js script in which I'm trying to use the js-cookie library:
gulpfile.js
// Initialize modules
const { src, dest, watch, series, parallel } = require('gulp');
const sourcemaps = require('gulp-sourcemaps');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const postcss = require('gulp-postcss');
const autoprefixer = require('autoprefixer');
const cssnano = require('cssnano');
var replace = require('gulp-replace');
var merge = require('merge-stream');
// File paths (note that src paths are arrays)
const files = {
scssSrcPath: [
'scss/*.scss',
'scss/_pageContentModules/*.scss'
],
jsSrcPath: [
'js/*.js',
'node_modules/slick-carousel/slick/slick.js'
],
scssDstPath: '../web/css',
jsDstPath: '../web/js'
}
// Sass task: compiles SCSS files into style.css
function scssTask(){
return merge(files.scssSrcPath.map(function (file) {
return src(file)
}))
.pipe(sourcemaps.init()) // initialize sourcemaps first
.pipe(sass()) // compile SCSS to CSS
.pipe(postcss([ autoprefixer(), cssnano() ])) // PostCSS plugins
.pipe(sourcemaps.write('.'))
.pipe(dest(files.scssDstPath));
}
// JS task: concatenates and uglifies JS files to script.js
function jsTask(){
return merge(files.jsSrcPath.map(function (file) {
return src(file)
}))
.pipe(concat('app.js'))
.pipe(uglify())
.pipe(dest(files.jsDstPath));
}
// Watch task: watch SCSS and JS files for changes
// If any change, run scss and js tasks simultaneously
function watchTask(){
watch(files.scssSrcPath, scssTask);
watch(files.jsSrcPath, jsTask);
}
// Export the default Gulp task so it can be run
// Runs the scss and js tasks simultaneously
// then watch task
exports.default = series(
parallel(scssTask, jsTask),
watchTask
);
js/feature.js
import Cookies from 'js-cookie';
const rs = cookies.get('referral_source');
if (typeof rs !== 'undefined') {
console.log('referral_source = ' + rs);
}
How can I get this working? Is there a way to do it using my simple Gulp setup, or do I need to go beyond and set up a full-on Webpack setup (with all the complexity that adds)?
Unfortunately, as far as I know, Gulp does not support the ability to use ES6 modules. If you want to use them, you will need to use Webpack.
But js-cookie does have a jsDelivr CDN: <script src="https://cdn.jsdelivr.net/npm/js-cookie#3.0.1/dist/js.cookie.min.js"></script>. By including this before your JS script, like this:
<script src="https://cdn.jsdelivr.net/npm/jscookie#3.0.1/dist/js.cookie.min.js"></script>
<script src="./js/feature.js"></script>

NodeJS require from unknown child folder

-- plugins
---- myplugin1
------ core
---- myplugin2
------ core
If this is my directory structure, is there any way for me to import all core folders from plugins without knowing the name myplugin1 etc?
require('/plugins/./core')
I know how to require from parent folders... but there seem to be nothing about child folders?
Node-Cheat available here, run node app followed by npm i glob.
Possible try:
const glob = require('glob');
const path = require('path');
glob.sync('./plugins/**/core/*.js').forEach(( file ) => {
require(path.resolve( file ) );
});
Expected output:
myplugin1 core loading
myplugin2 core loading
You can use require-dir to achieve this.
These will be the steps
npm install require-file-directory
var requireDir = require('require-dir');
var dir = requireDir('pathToyourCoreDirectory');
And inside the above handler function you can require all of the modules

How to locate the path of parent directory in gulp.dest()?

I'm new comer in Gulp, and i got stock when i try to output my files to their parent's path.
My directories like this:
app/page_a/less/a.less
app/page_a/css
My goal is:
app/page_a/less/a.less
app/page_a/css/a.css
Here's what i'm doing:
I use ** because i want to match all of my page_* module.
gulp.task('test', function () {
var files = ['./app/**/*.less'];
return gulp.src(files, {
base: '.' // Now the base url becomes where the *.less is.
})
.pipe(less())
.pipe(gulp.dest('.'));
});
My result:( which is obviously wrong :( )
app/page_a/less/a.less
app/page_a/less/a.css
app/page_a/css
So how can i output *.css into the corresponding app/page_*/css path?
The path you specify in the base option to gulp.src() isn't relative to each respective .less file, but rather the current working directory. This is usually the directory your Gulpfile.js resides in.
What you actually want to do is alter the path for each resulting .css file after your less() plugin has run, so when the .css files are written to the directory specified by gulp.dest() the /less/ part of the path has been replaced with /css/.
This is exactly what the gulp-rename plugin is for:
var gulp = require('gulp');
var less = require('gulp-less');
var rename = require('gulp-rename');
gulp.task('default', function () {
return gulp.src( './app/**/*.less')
.pipe(less())
.pipe(rename(function(file) {
file.dirname = file.dirname.replace(/less$/, "css");
}))
.pipe(gulp.dest('./app/'));
});
With gulp.dest('.') you say 'here'
Try with:
.pipe(gulp.dest('./app/page_a/css/'));
This should be work

Precompile handlebars templates into seperate JST (.js) files with Gulp

I have just recently moved from grunt to gulp and I am wanting to pre-compile my handlebars templates (with .handlebars extension) into separate .js files.
from:
www/templates/login.handlebars
www/templates/home.handlebars
to:
www/templates/login.js
www/templates/home.js
I am trying to use gulp but to no avail. A lot of the npm packages ask you to pass data to the compiler, but the data in my web app is collected mainly from ajax requests and then passed to the handlebars template.
My gulpfile.js:
// cache vars
var gulp = require('gulp'),
rename = require('gulp-rename'),
handlebars = require('gulp-compile-handlebars');
// start task
gulp.task('default', function(){
return gulp.src( 'www/templates/*.handlebars' )
.pipe( handlebars() )
.pipe( rename('*.js') )
.pipe( gulp.dest( 'www/templates' ) );
});
});
The main reason i moved from Grunt to Gulp was because grunt doesnt seem to support the newer handlebars version (link here).
There are lots of examples how to compile handlebars templates but not in the way I want too (Is my way possible?)
Also i don't want to wrap my handlebar js files into a namespace if possible.
When i run my gulp task none of the .js files are generated any ideas?
I have a not so clean solution that works for me. I'm using pump + gulp as it's a good idea to clean the source if something goes wrong while processing the pipe.
in the gulpfile.js:
const pump = require( 'pump' )
const handlebars = require( 'gulp-handlebars' )
gulp.task( 'default', ( done ) => {
const templates = [
'login',
'home'
] // <-- You may want to get the list of files programmatically ;)
let pipe = []
templates.forEach( ( template ) => {
pipe.push( gulp.src( 'www/templates/' + template + '.handlebars' ) )
pipe.push( handlebars() )
pipe.push( gulp.dest( 'www/templates/' ) )
} )
pump( pipe, done )
} )

How can I achieve this using gulp?

I am enumerating the subdirectories in a directory. For each sub directory I would like to apply a number of gulp activities like less compilation, and then create an output file specific to that subdirectory.
I would like the gulp process to continue, as further transformation steps need to be performed later.
Can someone help me understand how I can create these files half way through the "gulp pipeline"?
This seems quite interesting to achieve and gulp has no limitations at all.
I will give you detailed example how I have managed to accomplish such a task a while ago.
Let assume that you have directoryA. Subdirectories childA, childB and childC are contained into directoryA. So basically your tree structure looks like:
directoryA
--childA
--childB
--childC
I am always looking for a flexible solutions so I would suggest to include a JSON file in each subdirectory naming the tasks you would like to running. Using fs you can access these files. You can also use run-sequence to execute gulp tasks synchronously.
For demo purposes place a file named manifest.json inside childA subdirectory.
Manifest.json contains the following declarations:
{
"filesToProccess" : ["./childA/*.js", "./childB/*.js"],
"tasksToRun" :["taskA", "taskB"]
}
Finally gulpfile would like this:
'use strict';
//dependencies declared into package.json
//install them using npm
var gulp = require('gulp'),
fs = require('fs'),
runSequence = require('run-sequence'),
path = require('path');
//these two array will keep the actions you have included into manifest file.
var filesHolder = [], tasksHolder = [];
gulp.task('taskA', function () {
return gulp.src(filesHolder)
.pipe(whatever)
.pipe(gulp.dest('whatever')); //chailed actions
});
gulp.task('taskB', function () {
return gulp.src(filesHolder)
.pipe(whatever)
.pipe(gulp.dest('whatever'));
});
//a simple utility function to read all subdirectories of directoryA
function getDirectories(srcpath) {
return fs.readdirSync(srcpath).filter(function(file) {
return fs.statSync(path.join(srcpath, file)).isDirectory();
});
}
//finally insert the default gulp task
gulp.task('default', function(){
var manifest;
//map directory's A subdirectories
var availableDirs = getDirectories("./directoryA");
//finally loop the available subdirectories, load each manifest file and
availableDirs.forEach(function(subdir) {
manifest = require("./directoryA/"+subdir+"manifest.json");
filesHolder = manifest.filesToProccess;
tasksHolder = manifest.tasksToRun;
runSequence( tasksHolder , function () {
console.log( " Task ended :" + tasksHolder + " for subdirectory : " + subdir);
});
});
});

Categories

Resources