I am having a difficult time getting gulp.dest to output anything anywhere. I specifically want to just output to the root of the project (I'm hijacking an ASP.NET Core project for TypeScript development only). I'd really appreciate some help on how I can get dest to do what I want. Here's my current gulpfile.js:
/// <binding AfterBuild="build" Clean="clean" ProjectOpened="watch" />
"use strict";
const del = require("del"),
gulp = require("gulp"),
gulpConcat = require("gulp-concat"),
gulpRename = require("gulp-rename"),
gulpTerser = require("gulp-terser");
gulp.task("concatenate", () => {
return gulp.src([
"*.js",
"!gulpfile.js"
])
.pipe(gulpConcat("concatenated.js"))
.pipe(gulp.dest("/"));
});
gulp.task("minify", () => {
return gulp.src("concatenated.js")
.pipe(gulpTerser())
.pipe(gulpRename("min.js"))
.pipe(gulp.dest("/"));
});
gulp.task("clean", () => del([
"*.js",
"!gulpfile.js"
]));
gulp.task("build", gulp.series(
"concatenate",
"minify"
));
gulp.task("watch", () => {
gulp.watch([
"*.ts"
], gulp.series(
"build"
));
});
I think
.pipe(gulp.dest('.'))
is all you want.
Related
I'm writing a gulp file to build and concatenate JS files. The main purpose is to build ES6 code with Babel in a main.build.js, then concatenate additional libraries/dependencies in a main.deps.jsfile, and concatenate both files in a final main.bundle.js file. This is done for frontend and admin, so the output must be two files (main.bundle.js and admin.bundle.js).
To do that, I've created 3 tasks, and one to trigger all with one command. Here is my gulpfile.js code:
task("js:build", (done) => {
browserify({entries: path.resolve(srcPath, "js/main.js")})
.transform(babelify.configure({
presets: ["#babel/preset-env"]
}))
.bundle()
.on("error", (e) => {
console.error(e.message);
})
.pipe(source("main.build.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
browserify({entries: path.resolve(srcPath, "js/admin.js")})
.transform(babelify.configure({
presets: ["#babel/preset-env"]
}))
.bundle()
.on("error", (e) => {
console.error(e.message);
})
.pipe(source("admin.build.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
done();
});
task("js:deps", (done) => {
let mainDeps = jsDeps.main.map((asset) => {
return asset.indexOf("node_modules") > -1 ? asset : path.resolve(srcPath, "js/plugins", asset);
});
let adminDeps = jsDeps.admin.map((asset) => {
return asset.indexOf("node_modules") > -1 ? asset : path.resolve(srcPath, "js/plugins", asset);
});
if(mainDeps.length > 0){
src(mainDeps)
.pipe(plumber())
.pipe(concat("main.deps.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
}
if(adminDeps.length > 0){
src(adminDeps)
.pipe(plumber())
.pipe(concat("admin.deps.js"))
.pipe(dest(path.resolve(distPath, "js/standalone")));
}
done();
});
task("js:concat", (done) => {
let mainDeps = path.resolve(distPath, "js/standalone/main.deps.js");
let mainBuild = path.resolve(distPath, "js/standalone/main.build.js");
let adminDeps = path.resolve(distPath, "js/standalone/admin.deps.js");
let adminBuild = path.resolve(distPath, "js/standalone/admin.build.js");
let main = fs.existsSync(mainDeps) ? [mainDeps, mainBuild] : [mainBuild];
let admin = fs.existsSync(adminDeps) ? [adminDeps, adminBuild] : [adminBuild];
src(main)
.pipe(plumber())
.pipe(concat("main.bundle.js"))
.pipe(dest(path.resolve(distPath, "js")));
src(admin)
.pipe(plumber())
.pipe(concat("admin.bundle.js"))
.pipe(dest(path.resolve(distPath, "js")));
done();
});
task("js", series("js:deps", "js:build", "js:concat"));
The problem is: when I run gulp js in my terminal, it throws an error that main.build.jsfile was not found, as if the js:build task hasn't executed. And, obviously, main.build.js isn't generated at desired folder.
But, for my surprise, if I run each task separately in my terminal (gulp js:deps, then gulp js:build, then gulp js:concat), it works like a charm, just like as expected. All .build and .deps file are generated and concatenated in .bundle files.
Looks like the gulp js:build isn't running when calling inside a series, or the series isn't running tasks in series (it's running like a parallel).
Can someone help me fixing that? Thanks!
I don't even know how to explain my problem shortly in title. I want to create task which will follow these steps:
Take Sass File as a source (Ex. src/scss/main.scss)
Sort css properties with 'postcss-sorting'
Overwrite source file to same path (Ex. src/scss/main.scss)
Take sorted scss file and compile to css
Write to css folder (Ex. dist/css)
I try to write this task but when i start to watch scss file changes, task having infinite loop. I tried with 2 different tasks too (one for sort css properties and write file, other one for compile and write) it still looping. I don't want to sort only css properties in css file, i want to sort my scss file too. That is my example code:
// Load plugins
const {gulp, watch, src, dest, series} = require( 'gulp' ),
browserSync = require('browser-sync').create(),
postcss = require( 'gulp-postcss' ),
sortProperties = require( 'postcss-sorting' ),
sassParser = require( 'postcss-scss' ),
sass = require( 'gulp-sass' );
// Load CSS property orders for 'postcss-sorting'
const propertySortOrder = require('./propertySortOrder');
// Style
const style = () => {
return src('src/scss/**/*.scss')
.pipe(
postcss([sortProperties(propertySortOrder)], {
syntax: sassParser,
})
)
.pipe(dest('src/scss'))
.pipe(sass().on('error', sass.logError))
.pipe(dest('src/css'))
.pipe(browserSync.stream());
}
// Start Server
const startServer = (done) => {
browserSync.init({
server: { baseDir: './' },
injectChanges: true
});
done();
}
// Watch File Changes
const watchFileChanges = (done) => {
watch('src/scss/**/*.scss', style);
done();
}
exports.start = series(startServer, watchFileChanges);
Can anyone help me to fix this? Thanks
P.S. Sorry for my all grammatical mistakes, English is not my native language.
You can use gulp-changed, it will override the file only if there is a change, preventing the infinite loop:
const changed = require('gulp-changed');
const clone = require( 'gulp-clone' );
const merge = require('merge-stream');
// Style
const style = () => {
const sortedCssPipe = src('src/scss/**/*.scss')
.pipe(
postcss([sortProperties(propertySortOrder)], {
syntax: sassParser,
})
);
const scssPipe = sortedCssPipe
.pipe(clone())
.pipe(changed('src/scss', {hasChanged: changed.compareContents}))
.pipe(dest('src/scss'));
const cssPipe = sortedCssPipe
.pipe(sass().on('error', sass.logError))
.pipe(dest('src/css'))
.pipe(browserSync.stream());
return merge(scssPipe, cssPipe);
}
Like most I have been concatenating my JS/CSS files into one big file within Gulp, however, with HTTP2 becoming the norm nowadays I thought I would change my gulp file instead to make related "bundles" instead, however am wondering how to manage this in a clean fashion within Gulp.
My prior gulpfile.js:
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var sass = require('gulp-sass');
var postcss = require('gulp-postcss');
var cleanCSS = require('gulp-clean-css');
var uglify = require('gulp-uglify');
var gulpif = require('gulp-if');
var sourcemaps = require('gulp-sourcemaps');
var autoprefixer = require('autoprefixer');
var site_url = 'xxxxxxxxxxxxx.local';
// Set some paths
var js_scripts = [
'js/dev/lib/**/*.js',
'js/dev/plugins/**/*.js',
// We have to set the bootstrap lines separately as some need to go before others
'js/dev/bootstrap/alert.js',
'js/dev/bootstrap/collapse.js',
'js/dev/bootstrap/tooltip.js',
'js/dev/bootstrap/popover.js',
'js/dev/bootstrap/tab.js',
'js/dev/bootstrap/transition.js',
'js/dev/custom.js'
];
gulp.task('scripts', function() {
return gulp.src(js_scripts)
.pipe(sourcemaps.init())
.pipe(concat('scripts.js'))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./js'));
});
gulp.task('uglify', gulp.series('scripts', function() {
return gulp.src(js_scripts)
.pipe(gulpif('!**/*.min.js', uglify({mangle: false})))
.pipe(concat('scripts.min.js'))
.pipe(gulp.dest('./js'));
}));
// create a task that ensures the `uglify` task is complete before
// reloading browsers
gulp.task('js-watch', gulp.series('uglify', function (done) {
browserSync.reload();
done();
}));
/* Creates the standard version */
gulp.task('styles', function() {
return gulp.src('scss/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./css/'))
.pipe(browserSync.stream());
});
/* Creates the minified version */
gulp.task('css-minify', gulp.series('styles', function() {
return gulp.src('scss/**/*.scss')
.pipe(sourcemaps.init())
.pipe(sass({
outputStyle: 'compact' // Options: nested, expanded, compact, compressed
}).on('error', sass.logError))
.pipe(postcss([
autoprefixer({
cascade: false
}),
]))
.pipe(cleanCSS({
advanced: false,
aggressiveMerging: false
}))
.pipe(rename({suffix: '.min'}))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./css/'));
}));
gulp.task('browser-sync', function(done) {
browserSync.init({
open: 'external',
proxy: site_url,
host: site_url,
// port: 5000,
browser: "chrome",
});
done();
});
gulp.task('watch', gulp.series('browser-sync', function() {
gulp.watch('scss/**/*.scss', gulp.series('css-minify'));
gulp.watch('js/dev/**/*.js', gulp.series('js-watch'));
}));
gulp.task('default', gulp.series('js-watch', 'css-minify'));
Now, to help turn the JS files into bundles I have made a change to the js_scripts array, to:
var js_scripts = [
[
'lib',
[
'js/dev/lib/**/*.js'
],
['lib.js', 'lib.min.js']
],
[
'plugins',
[
'js/dev/plugins/**/*.js'
],
['plugins.js', 'plugins.min.js']
],
[
'bootstrap',
[
// We have to set the bootstrap lines separately as some need to go before others
'js/dev/bootstrap/alert.js',
'js/dev/bootstrap/collapse.js',
'js/dev/bootstrap/tooltip.js',
'js/dev/bootstrap/popover.js',
'js/dev/bootstrap/tab.js',
'js/dev/bootstrap/transition.js',
],
['bootstrap.js', 'bootstrap.min.js']
],
[
'custom',
[
'js/dev/custom.js'
],
['custom.js', 'custom.min.js']
],
];
With the idea being that we will loop through this array and create a separate JS + min.js file for each.
Now, the problem is I'm not sure how to achieve this in Gulp in a clean way.
Take this for example:
gulp.task('scripts', function() {
return gulp.src(js_scripts)
.pipe(sourcemaps.init())
.pipe(concat('scripts.js'))
.pipe(sourcemaps.write('../maps'))
.pipe(gulp.dest('./js'));
});
Ideally it would be good to loop through the array in here; but I'm not sure how to handle doing this multiple times, because once you return the first result then obviously the loop is going to end.
Does Gulp need to return each time? ...if not, then what do you return once you have finished processing the loop?
I tried using gulp-order to force ordering of the bootstrap files but it was unreliable. Here I use merge2 instead - it seems to work much better. Assumes you now have a custom folder.
[I didn't incorporate your sourcemaps pipes and browserSync reloads for brevity.]
const gulp = require('gulp');
const concat = require('gulp-concat');
// const rename = require('gulp-rename'); // not needed
// var gulpif = require('gulp-if'); // not needed
var terser = require('gulp-terser'); // better than uglify, works with es6
const merge2 = require('merge2') // does the ordering of source files
const glob = require('glob');
const path = require('path');
// glob.sync will build your array for you, so you don't need your 'js_scripts' array
const bundleFolders = glob.sync('js/dev/*/'); // returns an array of folders
console.log(bundleFolders);
gulp.task('scripts', () => {
let stream;
for (const bundle of bundleFolders) {
// get just the last directory of 'js/dev/bootstrap', 'js/dev/lib`, etc.
let thisBundle = path.basename(bundle);
console.log('thisBundle = ' + thisBundle);
if (thisBundle === 'bootstrap') {
stream = merge2(
gulp.src([
'js/dev/bootstrap/alert.js',
'js/dev/bootstrap/collapse.js',
'js/dev/bootstrap/tooltip.js',
'js/dev/bootstrap/popover.js',
'js/dev/bootstrap/tab.js',
'js/dev/bootstrap/transition.js',
])
// your other stuff - sourcemaps, etc.
.pipe(concat(thisBundle + '.js'))
// your other stuff - sourcemaps, etc.
.pipe(gulp.dest('./js')));
}
else { // not 'bootstrap' directory
stream = gulp.src(bundle + "**/*.js")
// your other stuff - sourcemaps, etc.
.pipe(concat(thisBundle + '.js'))
// your other stuff - sourcemaps, etc.
.pipe(gulp.dest('./js'));
}
}
return stream;
});
// gulp.task('uglify', gulp.series('scripts', function () { // not needed
gulp.task('terser', () => {
let bundles= [];
for (const bundle of bundleFolders) {
// get `js/dev/custom/custom.js`,'js/dev/bootstrap/bootstrap.js' etc.
bundles.push(bundle + path.basename(bundle) + '.js');
}
console.log(bundles);
return gulp.src(bundles)
// .pipe(gulpif('!**/*.min.js', uglify({mangle: false})))
// assumes what you want to uglify and concat are the 'lib.js', bootstrap.js', etc. files
.pipe(terser({ mangle: false }))
.pipe(concat('scripts.min.js'))
.pipe(gulp.dest('./js'));
});
// create a task that ensures the `terser` task is complete before
// reloading browsers
// gulp.task('js-watch', gulp.series('terser', function (done) {
// browserSync.reload();
// done();
// }));
gulp.task('watch', gulp.series('browser-sync', function () {
gulp.watch('scss/**/*.scss', gulp.series('css-minify'));
// gulp.watch('js/dev/**/*.js', gulp.series('js-watch')); // replaced by below
gulp.watch('js/dev/**/*.js', gulp.series('scripts', 'terser', browserSync.reload));
}));
exports.terser = gulp.series('terser'); // useful for testing
exports.scripts = gulp.series('scripts'); // useful for testing
exports.default = gulp.series('scripts'); // just for testing
I have the following two tasks:
gulp.task('compress', () => {
return gulp.src('app/static/angular/**/*.js')
.pipe(concat('build.js'))
.pipe(gulp.dest('./app/static'));
});
gulp.task('templates', () => {
return gulp.src('app/static/angular/**/*.html')
.pipe(htmlmin())
.pipe(angularTemplateCache('templates.js', {
module: 'myApp',
root: '/static/angular'
}))
.pipe(gulp.dest('./app/static'))
});
And it works fine, but I want them both concatenated into build.js -- how can I combine these two?
In the end I used merge-stream to merge the two streams into one output file:
var gulp = require('gulp');
var concat = require('gulp-concat');
var htmlmin = require('gulp-htmlmin');
var angularTemplateCache = require('gulp-angular-templatecache');
var merge = require('merge-stream');
gulp.task('build', () => {
var code = gulp.src('app/static/angular/**/*.js');
var templates = gulp.src('app/static/angular/**/*.html')
.pipe(htmlmin())
.pipe(angularTemplateCache({
module: 'myApp',
root: '/static/angular'
}));
return merge(code, templates)
.pipe(concat('build.js'))
.pipe(gulp.dest('./app/static'));
});
gulp.task('default', ['build']);
I assume the above task mentioned is in separate file say compress.js inside tasks folder
In gulpfile.js you can use below code :
//Include require-dir to include files available in tasks directory
var requireDir = require('require-dir');
// And Take the tasks directory
requireDir('./tasks');
Then you can create a build task as below in gulpfile.js:
gulp.task('build', ['compress', 'templates']);
I've got a Gulp task using browserify and watchify. As you can see I've got four files. modules.js uses the class from overlay-model.js.
But browserify doens't keep the order I'm passing. Instead of that browserify puts the files in alphabetical order so it first uses modules.js.
I'll tried looking for a solution gulp sort doens't seem to work and I can't find a browserify-ish solution.
Anyone knows something about this?
var gulp = require('gulp');
var gutil = require('gulp-util');
var c = gutil.colors;
var sort = require('gulp-sort');
var sourcemaps = require('gulp-sourcemaps');
var source = require('vinyl-source-stream');
var buffer = require('vinyl-buffer');
var browserify = require('browserify');
var watchify = require('watchify');
var babel = require('babelify');
function compile(watch) {
var bundler = watchify(browserify([
'./assets/js/overlay-model.js',
'./assets/js/slider.js',
'./assets/js/words.js',
'./assets/js/modules.js'
], {
debug: true
})
.transform(babel.configure({
presets: ['es2015']
})));
function rebundle() {
bundler.bundle()
.on('error', function(err) { console.error(err); this.emit('end'); })
.pipe(source('build.js'))
.pipe(buffer())
.pipe(sourcemaps.init({ loadMaps: true }))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('./public'));
}
if (watch) {
gutil.log(`${c.cyan('scripts')}: watching`);
bundler.on('update', function() {
gutil.log(`${c.cyan('scripts')}: processing`);
rebundle();
});
}
rebundle();
}
function watch() {
return compile(true);
};
gulp.task('build', function() { return compile(); });
gulp.task('watch', function() { return watch(); });
gulp.task('scripts', ['watch']);
I think typically you'll have just one entry point (modules.js in your case) that'll use require(...) to load other modules in order you want.
// modules.js
require('./overlay-model');
require('./slider');
require('./modules');
Then use browserify like:
browserify('./assets/js/modules.js', ...);