Iterate through multiple folders to compile all SASS to CSS in Gulp - gulp

I currently have a file structure like this
projects
sites
site-example
css
scss
site-second-example
css
scss
site-third-example
css
scss
***
site-fifty-example
css
scss
I'm trying to write a gulp task that I can run from the projects folder that will look inside the sites folder, and then go through each folder separately, look for any scss files, and then compile them to css.
I tried to follow this recipe but I must be messing it up somehow:
https://github.com/gulpjs/gulp/blob/master/docs/recipes/running-task-steps-per-folder.md
gulpfile.js
var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var fs = require('fs');
var path = require('path');
var merge = require('merge-stream');
var postcss = require('gulp-postcss');
var autoprefixer = require('autoprefixer');
var output = './**/css';
var sassOptions = {
errLogToConsole: true,
outputStyle: 'expanded'
};
var scriptsPath = './sites';
function getFolders(dir) {
return fs.readdirSync(dir)
.filter(function(file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
gulp.task('sass', function() {
var processors = [
autoprefixer({
browsers: ['last 12 versions']
})
];
var folders = getFolders(scriptsPath);
var tasks = folders.map(function(folder) {
return gulp.src(path.join(scriptsPath, folder, '/**/*.scss'))
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(postcss(processors))
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest(output));
});
return merge(tasks);
});

You can't put a globstar ** in your destination directory like this:
var output = './**/css';
That won't work, because gulp.dest() can't magically guess from context which directory you want your files to end up in.
You have to explicitly construct a destination directory for each folder returned from getFolders(), just as you do for gulp.src():
var tasks = folders.map(function(folder) {
var src = path.join(scriptsPath, folder, 'scss');
var dst = path.join(scriptsPath, folder, 'css');
return gulp.src(path.join(src, '**/*.scss'))
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(postcss(processors))
.pipe(sourcemaps.write('./maps'))
.pipe(gulp.dest(dst));
});

Related

gulp not compiling scss in subfolders

I have the following folder structure:
theme
assets
build
css
style.css
src
theme
buttons.scss
style.scss
components
hero
hero.html
hero.scss
index.html
Any changes in src theme and any scss file for a component (i.e. hero.scss) should all compile into style.css.
My theme files compile correctly, but my component scss files don't appear in style.css.
Instead, when I run gulp css, a separate css file appears under the build folder, i.e.
build
css
style.css
hero.css
How can I get it to compile everything into style.css?
gulpfile.js
const assetsSRC = 'assets/src/',
assetsDST = 'assets/build/',
components = 'components/';
const gulp = require('gulp'),
sass = require('gulp-sass')(require('sass')),
sourcemaps = require('gulp-sourcemaps'),
fs = require('fs'),
path = require('path'),
merge = require('merge-stream'),
postcss = require('gulp-postcss'),
autoprefixer = require('gulp-autoprefixer'),
plumber = require('gulp-plumber'),
concat = require('gulp-concat'),
uglify = require('gulp-uglify'),
strip = require('gulp-strip-comments');
const componentCSS = components + '**/*.scss',
componentJS = components + '**/*.js',
globalCSS = assetsSRC + 'scss/style.scss';
configCSS = assetsSRC + 'scss/config/**.scss';
themeCSS = assetsSRC + 'scss/theme/**.scss';
globalJS = assetsSRC + 'js/*.js';
libJS = assetsSRC + 'js/lib/*.js';
var sassOptions = {
errLogToConsole: true,
outputStyle: 'compressed'
};
function getFolders(dir) {
return fs.readdirSync(dir).filter(function(file) {
return fs.statSync(path.join(dir, file)).isDirectory();
});
}
function css() {
var folders = getFolders(components);
var tasks = folders.map(function(folder) {
var src = path.join(components, folder);
var dst = path.join(assetsDST + 'css');
return gulp.src(path.join(src, '/**/*.scss'))
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(dst));
});
return merge(tasks);
}
function mainCSS() {
var dst = path.join(assetsDST + 'css/');
return gulp.src(globalCSS, { allowEmpty: true })
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(dst));
}
function libraryJS() {
var dst = path.join(assetsDST + 'JS/lib');
return gulp.src(libJS).pipe(gulp.dest(dst));
}
function watch() {
gulp.watch([globalCSS,configCSS,themeCSS, componentCSS],mainCSS);
}
exports.mainCSS = mainCSS;
exports.mainJS = mainJS;
exports.libraryJS = libraryJS;
exports.css = css;
exports.javascript = javascript;
exports.watch = watch;
const build = gulp.series(watch);
gulp.task('default', build);
Edit
Attempt using gulp-sass-glob:
function css() {
gulp.task('styles', function () {
var src = path(components);
return gulp
.src(src, '/**/*.scss')
.pipe(sassGlob())
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(sourcemaps.write('.'))
.pipe(sass())
.pipe(gulp.dest(assetsDST + 'css'));
});
}
Re-ran gulp watch (no errors). Made a change and saved hero.scss. Then went into style.css to find css that has been compiled from hero.scss - nothing shows. scss not compiled into style.css
Edit 2
I have the following:
function css() {
var folders = getFolders(components);
var tasks = folders.map(function(folder) {
var src = path.join(components, folder);
var dst = path.join(assetsDST + 'css/');
return gulp.src(path.join(src, '**/*.scss'))
.pipe(sourcemaps.init())
.pipe(sass(sassOptions).on('error', sass.logError))
.pipe(autoprefixer('last 2 versions'))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(dst));
});
return merge(tasks);
}
This is creating individual css files (rather than collating into style.css). I think this one is close, but unsure how to proceed.
Have you tried gulp-sass-glob?
https://www.npmjs.com/package/gulp-sass-glob

postcss/precss - convert .scss to .css

I'm usign postcss/precss with gulp to convert my scss markup to valid css. This is my gulpfile.js:
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var precss = require('precss');
var watch = require('gulp-watch');
gulp.task('stream', function () {
var processors = [
precss
];
return watch('src/*.css', { ignoreInitial: false })
.pipe(postcss(processors))
.pipe(gulp.dest('dest'));
});
gulp.task('default', gulp.parallel('stream'));
The problem is that it doesn't change file extensions, so I need to write scss in *.css files, and what I am trying to do is to set it to read scss from *.scss files and output css into *.css files. Can anybody tell me how to achieve that?
Not an expert on this, so I'll just share how we do sass compilation.
We use gulp-concat to concat the files together into one .css file. Your gulp snippet would be as follows:
var gulp = require('gulp');
var postcss = require('gulp-postcss');
var precss = require('precss');
var watch = require('gulp-watch');
var concat = require('gulp-concat');
gulp.task('stream', function () {
var processors = [
precss
];
return watch('src/*.css', { ignoreInitial: false })
.pipe(postcss(processors))
.pipe(concat('FILENAME.css'))
.pipe(gulp.dest('dest'));
});
gulp.task('default', gulp.parallel('stream'));
Don't forget to do npm install --save-dev gulp-concat first!

How to create glob pattern to access all sub folder and its own folder?

I got a main folder and under it, it has a sub folders generated dynamically with boilerplate of folders and files.
Folder structure: http://www.screencast.com/t/WLFrIeYfm60o
Below is my sample code for javascripts:
var gulp = require('gulp'),
runTaskSeq = require('gulp-sequence'),
uglifyjs = require('gulp-uglify'),
uglifycss = require('gulp-uglifycss'),
sourcemaps = require('gulp-sourcemaps'),
concatjs = require('gulp-concat'),
concatcss = require('gulp-concat-css'),
rename = require('gulp-rename'),
autoprefixer = require('gulp-autoprefixer'),
del = require('del'),
fs = require('fs');
// log errors
function errorLog(error) {
console.log(error.message);
this.emit('end');
}
// script task
gulp.task('scripts', function() {
return gulp.src('mainfolder/**/public/js/**/*/*.js')
.pipe(sourcemaps.init())
.pipe(concatjs('temp.js'))
.pipe(uglifyjs())
.on('error', errorLog)
.pipe(rename('build.min.js'))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('mainfolder/**/public/js'));
});

Gulp watch - not working

I have gulpfile.js from https://github.com/gulpjs/gulp.
I just change folders name for mine.
Task 'gulp' work normally, first 'gulp watch' too. But any another save any less file don't do anything. Just "Finished 'styles' after 1.34 s"
(JS works good)
Any advice?
main.less have less imports with all filles
Folders looks like:
/www
/js
/css
main.less
file.less
file2.less
/lib
file3.less
var gulp = require('gulp');
var less = require('gulp-less');
var babel = require('gulp-babel');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var cleanCSS = require('gulp-clean-css');
var del = require('del');
var paths = {
styles: {
src: 'www/css/main.less',
dest: 'www/css/'
},
scripts: {
src: 'www/js/js/**/*.js',
dest: 'www/js/'
}
};
function clean() {
return del([ 'assets' ]);
}
function styles() {
return gulp.src(paths.styles.src)
.pipe(less())
.pipe(cleanCSS())
// pass in options to the stream
.pipe(rename({
basename: 'main',
suffix: '.min'
}))
.pipe(gulp.dest(paths.styles.dest));
}
function scripts() {
return gulp.src(paths.scripts.src, { sourcemaps: true})
.pipe(babel())
.pipe(uglify())
.pipe(concat('all.min.js'))
.pipe(gulp.dest(paths.scripts.dest));
}
function watch() {
gulp.watch("www/js/js**/*.js", scripts);
gulp.watch("www/css/**/*.less", styles);
}
exports.clean = clean;
exports.styles = styles;
exports.scripts = scripts;
exports.watch = watch;
var build = gulp.series(clean, gulp.parallel(styles, scripts));
gulp.task('build', build);
gulp.task('default', build);
As #Jakub thought, you never actually call your watch task in the code you presented! You probably want something like this:
var build = gulp.series(clean, gulp.parallel(styles, scripts), watch);

Gulp to compile the scss files and move the css and css.map files to the parent folder relative to the scss file location

var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('sass', function () {
return gulp.src(['./project/**/*.scss', '!./project/**/_*/'])
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(function (file) {
return file.base;
}));
});
/project
--> Module1
--> scss
--> Test1.scss
--> Module2
--> scss
--> Test2.scss
Click here for folder structure
I have a project with multiple modules. I'm trying to write a gulp task that compiles the sass files and creates css files within each module. I have the following folder structure and gulpfile.
The task is currently designed to compile the scss files and create the css and css.map files in the same location as the scss files.
How can I move them both outside the scss folder, but still inside their respective modules?
You can add a config file to specify the build location for the files so that they can be generated in a folder of your choice, like so:
let gulp = require('gulp');
let sass = require('gulp-sass');
let sourcemaps = require('gulp-sourcemaps');
let rename = require('gulp-rename');
let gulpUtil = require('gulp-util');
let merge = require('merge-stream');
const CONFIGS = [require('./gulp.module1.config'), require('./gulp.module2.config')];
gulp.task('sass', function () {
let tasks = CONFIGS.map(config => {
return gulp.src(config.sass.src)
.pipe(sass())
.on('error', error => console.log(error))
.pipe(rename('app.min.css'))
.pipe(gulp.dest(config.buildLocations.css));
});
return merge(tasks);
});
Config 1:
module.exports = {
app: { baseName: 'module1' },
sass: {
src: ['./project/module1/scss/*.scss']
},
buildLocations: {
css: './project/module1/'
}
}
config 2
module.exports = {
app: { baseName: 'module1' },
sass: {
src: ['./project/module2/scss/*.scss']
},
buildLocations: {
css: './project/module2/'
}
}
Folder Structure
UPDATE: If you don't want to write an individual config file you can use the path library to rename it, leaves you with the files on the parent level.
gulp.task('sass', function () {
return gulp.src('./project/**/scss/*.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('.'))
.pipe(rename(function(file) {
file.dirname = path.dirname(file.dirname)
return file;
}))
.pipe(gulp.dest('./project'))
});
gulp-flatten is really handy for selecting which directories to include or exclude from the final structure.
var gulp = require('gulp');
var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var flatten = require("gulp-flatten");
gulp.task('sass', function () {
return gulp.src(['./project/**/*.scss', '!./project/**/_*/'])
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('.'))
// keep one parent directory: "Module1", "Module2"
// relative to your glob bae, so first after "project"
.pipe(flatten({ includeParents: 1}))
.pipe(gulp.dest('project'));
});