gulp-concat twice the content - javascript

That's a weird thing for me, i have a task to concat my .js files and then uglify them with a watcher, but the concat task just twice the content in every call...
Here is my gulpfile:
'use strict';
let gulp = require('gulp');
let stylus = require('gulp-stylus');
let sourcemaps = require('gulp-sourcemaps');
let concat = require('gulp-concat');
let uglify = require('gulp-uglify');
let plumber = require('gulp-plumber');
let bootstrap = require('bootstrap-styl');
let rupture = require('rupture');
let copy = require('gulp-copy2');
/*
Prepare the paths
*/
let base = './theme';
let themeName = 'own-theme';
let paths = {
stylus : `${base}/${themeName}/css`,
js : `${base}/${themeName}/js`,
vendor : `${base}/${themeName}/js/vendor`
}
/*
Stylus compile
*/
gulp.task('stylus-compile', () => {
return gulp.src([`${paths.stylus}/dev/*.styl`, `${paths.stylus}/!**/_*.styl`])
.pipe(plumber())
.pipe(stylus({
use: [bootstrap(), rupture()],
compress: true
}))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(`${paths.stylus}`));
});
/*
Get the bootstrap-styl js files and concat/uglify them
*/
gulp.task('bootstrap-build', () => {
return gulp.src([
'node_modules/bootstrap-styl/js/transition.js',
'node_modules/bootstrap-styl/js/alert.js',
'node_modules/bootstrap-styl/js/button.js',
'node_modules/bootstrap-styl/js/carousel.js',
'node_modules/bootstrap-styl/js/collapse.js',
'node_modules/bootstrap-styl/js/dropdown.js',
'node_modules/bootstrap-styl/js/modal.js',
'node_modules/bootstrap-styl/js/tooltip.js',
'node_modules/bootstrap-styl/js/popover.js',
'node_modules/bootstrap-styl/js/scrollspy.js',
'node_modules/bootstrap-styl/js/tab.js',
'node_modules/bootstrap-styl/js/affix.js'
])
.pipe(sourcemaps.init())
.pipe(concat('bootstrap.min.js'))
.pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(`${paths.vendor}`));
});
/*
Get the js assets from NPM
*/
gulp.task('js-copy', () => {
let dirs = [
{ src: 'node_modules/jquery/dist/jquery.min.js', dest: `${paths.vendor}/jquery.min.js` },
{ src: 'node_modules/sweet-scroll/sweet-scroll.min.js', dest: `${paths.vendor}/sweet-scroll.min.js` }
]
return copy(dirs);
});
/*
Concat/Uglify the JS files
*/
gulp.task('js-build', () => {
return gulp.src(`${paths.js}/*.js`)
.pipe(sourcemaps.init())
.pipe(concat('site.min.js'))
// .pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(`${paths.js}`));
})
/*
Watch
*/
gulp.task('watch', () => {
gulp.watch(`${paths.js}/*.js`, ['js-build']);
gulp.watch(`${paths.stylus}/dev/*.styl`, ['stylus-compile']);
});
gulp.task('default', ['bootstrap-build', 'js-copy', 'watch']);
The bootstrap-build task don't twice the content no matter how many times you call the task, but the js-build does.
Here are the test separated scripts to concat and the results:
File 1:
(function() {
console.log("oh!")
console.log("uh!")
}).call(this);
File 2:
(function() {
console.log("hey")
}).call(this);
Concated file(uh, oh file re-saved after the watcher was fired):
(function() {
console.log("oh!")
console.log("uh!")
}).call(this);
(function() {
console.log("oh!")
console.log("uh!")
}).call(this);
(function() {
console.log("hey")
}).call(this);
//# sourceMappingURL=site.min.js.map
(function() {
console.log("hey")
}).call(this);
//# sourceMappingURL=site.min.js.map
In every re-save, the concat twice the content... i really don't get the problem. Any idea?
Thanks in adnvance.

The reason your bootstrap-build works is because it places the resulting bootstrap.min.js in a different folder than the source files.
Your js-build task however concatenates all .js files in your path.js folder and places the resulting site.min.js in that same folder.
That means when first running js-build the files file1.js and file2.js are concatenated into site.min.js. On a second run the files file1.js, file2.js and site.min.js are concatenated into site.min.js. Every time you run your js-build task your site.min.js grows.
What you need to do is exclude site.min.js from being concatenated with the other files:
gulp.task('js-build', () => {
return gulp.src([
`${paths.js}/*.js`,
`!${paths.js}/site.min.js`
])
.pipe(sourcemaps.init())
.pipe(concat('site.min.js'))
// .pipe(uglify())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest(`${paths.js}`));
})

Related

Processing arrays within Gulp to create bundles in each directory with ordered files

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

Why is my gulpfile.js is not compiling to scripts.js when I run gulp scripts from the terminal?

Below is a copy of my gulpfile.js. For some reason /util.js, /alert.js & push.js are not being compiled into my scripts.js file when I run "gulp scripts" from the terminal in VSCode. I would appreciate an advice to help me sort out this problem. I'm new to gulpfile format, so I wouldn't be surprised if I've
made a mistake somewhere
const gulp = require('gulp');
const sass = require('gulp-sass');
const browserSync = require('browser-sync').create();
const concat = require('gulp-concat');
const rename = require('gulp-rename');
const uglify = require('gulp-uglify');
function scripts() {
return gulp.src(
'node_modules/jquery/dist/jquery.js',
'node_modules/bootstrap/js/dist/util.js',
'node_modules/bootstrap/js/dist/alert.js',
'node_modules/var/push.js',
'js/main.js',
'js/other.js'
)
.pipe(concat('scripts.js'))
.pipe(gulp.dest('js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('./js'));
}
// compile scss into css
function style() {
// 1 where is scss file
return gulp.src('scss/**/*.scss')
// 2 pass that file through sass compiler
.pipe(sass().on('error', sass.logError))
// 3 where do iI have the compiled css?
.pipe(gulp.dest('./css'))
// 4 stream changes to all browsers
.pipe(browserSync.stream());
}
function watch() {
browserSync.init({
server: {
baseDir: './'
}
});
gulp.watch('scss/**/*.scss', style);
gulp.watch('*.html').on('change', browserSync.reload);
gulp.watch('js/**/*.js').on('change', browserSync.reload);
}
exports.style = style;
exports.watch = watch;
exports.scripts = scripts;
When passing several globs or paths to gulp.src, you should wrap them in an array:
return gulp.src([
'node_modules/jquery/dist/jquery.js',
'node_modules/bootstrap/js/dist/util.js',
'node_modules/bootstrap/js/dist/alert.js',
'node_modules/var/push.js',
'js/main.js',
'js/other.js'
])

Css stylesheet has the wrong path when using gulp

I have been struggling for a while now and it is fairly frustrating to be honest.
The problem:
I created a gulpfile for my static website, and all i want to do is use browserSync, to compile sass into css and to minify the script and css files. Everything works fine, excluding one thing:
When I run "gulp" everything loads, besides de css file, which is located in "CSS/". Apparently the server thinks that the css file is ("CSS/style.css/") a folder actually.
Screenshot with the console error:
image
the css file is located in "css/style.css"
"use strict";
let paths = {
script: "js/*.js",
minifiedScript: 'script.min.js',
cssPath: "css/*.css",
productionFolder: "production",
sassPath: "scss/*.scss",
htmlFiles: "*.html"
};
const gulp = require('gulp');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');
const del = require('del');
const browserSync = require('browser-sync').create();
const cssMin = require('gulp-css');
const sass = require('gulp-sass');
const inject = require('gulp-inject');
const rename = require("gulp-rename");
gulp.task('browserSync', function() {
browserSync.init({
server: {
baseDir: "./"
}
});
});
gulp.task('sass', function () {
return gulp.src(paths.sassPath)
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./css'))
.pipe(browserSync.stream());
});
gulp.task('index', function () {
var target = gulp.src('index.html');
// It's not necessary to read the files (will speed up things), we're only after their paths:
var sources = gulp.src([paths.script,paths.cssPath], {read: false});
return target.pipe(inject(sources))
.pipe(gulp.dest(''));
});
gulp.task('cssMinify', function(){
return gulp.src(paths.cssPath)
.pipe(cssMin())
.pipe(gulp.dest(paths.productionFolder + "/minified css"))
.pipe(browserSync.stream());
});
gulp.task('clean', function() {
// You can use multiple globbing patterns as you would with `gulp.src`
return del(['build']);
});
gulp.task('scripts', ['clean'], function() {
// Minify and copy the JS file
return gulp.src(paths.script)
.pipe(sourcemaps.init())
.pipe(uglify())
.pipe(concat(paths.minifiedScript))
.pipe(sourcemaps.write())
.pipe(gulp.dest(paths.productionFolder + "/minified JS"));
});
gulp.task('jsMinify:watch', function() { gulp.watch(paths.script, ['scripts']) });
gulp.task('sass:watch', function() { gulp.watch(paths.sassPath, ['sass']) });
gulp.task('cssMinify:watch', function() { gulp.watch(paths.cssPath, ['cssMinify']) });
gulp.task('html:watch', function() { gulp.watch(paths.htmlFiles).on('change', browserSync.reload) });
gulp.task('default', ['sass', 'index', 'cssMinify', 'clean', 'html:watch', 'jsMinify:watch', 'sass:watch', 'cssMinify:watch','browserSync', 'scripts']); // DEVELOPMENT

Gulp browserify order/sort files

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', ...);

How to process *.js and *.min.js bower files in gulp

In my gulp file to inject bower components I have this bad style code duplication. But I do not have any ideas how to get rid of it.
Generally speaking we cannot say just bower_components/**/*.js because we don't want to import all files, plus for production we want to import just .min files. Again. I cannot guaranty that every package I use have .js and .min.js files. So just *.js and *.min.js may not work.
gulp.task('inject', () => {
let sources = gulp.src([
// jquery
'public/bower_components/jquery/dist/jquery.js',
// bootstrap
'public/bower_components/bootstrap/dist/js/bootstrap.js',
'public/bower_components/bootstrap/dist/css/bootstrap.css',
// angular
'public/bower_components/angular/angular.js',
'public/bower_components/angular/angular-csp.css',
// angular route
'public/bower_components/angular-route/angular-route.js',
],{read: false});
let min_sources = gulp.src([
// jquery
'public/bower_components/jquery/dist/jquery.min.js',
// bootstrap
'public/bower_components/bootstrap/dist/js/bootstrap.min.js',
'public/bower_components/bootstrap/dist/css/bootstrap.min.css',
// angular
'public/bower_components/angular/angular.min.js',
'public/bower_components/angular/angular-csp.css',
// angular route
'public/bower_components/angular-route/angular-route.min.js',
],{read: false});
return gulp.src('public/build/index.html')
.pipe(gulpif(!argv.production, inject(sources, {relative: true})))
.pipe(gulpif(argv.production, inject(min_sources, {relative: true})))
.pipe(gulp.dest('public/build/'));
});
But this code duplication isn't solution. I think. How can I improve this part, besides to move this two array in bower.js file ?
Maybe you can use config.js. Use var config = require('../config'); to read the variables in config.js so you can separate file paths and task.
If you want to separate .js and .min.js , you can use
'src' : [
'src/**/*.js',
'!src/**/*.min.js',
]
For example below I concat .min.js / .js files and uglify it, and also concate .css files and use cssnano() to compress it. In the end vendor task will output vendor.bundle.js and vendor.bundle.css
config.js:
'use strict';
module.exports = {
'vendor': {
'scripts': {
'src': [
'bower_components/jquery/dist/jquery.min.js',
'bower_components/lodash/dist/lodash.min.js',
// Moment
'bower_components/moment/min/moment.min.js',
'bower_components/moment/locale/zh-tw.js',
// Ionic & Angular
'bower_components/ionic/js/ionic.bundle.min.js',
'bower_components/ngCordova/dist/ng-cordova.min.js'
// ...
],
'dest': 'www/js',
'output': 'vendor.bundle.js'
},
'styles': {
'src': [
// Mobiscroll
'bower_external/mobiscroll/css/mobiscroll.custom-2.17.0.min.css',
],
'dest': 'www/css',
'output': 'vendor.bundle.css'
}
}
}
}
vendor.js
'use strict';
var config = require('../config');
var gulp = require('gulp');
var gulpif = require('gulp-if');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var postcss = require('gulp-postcss');
var cssnano = require('cssnano');
var handleErrors = require('../util/handleErrors');
var browserSync = require('browser-sync');
var pkg = require('../../package.json');
gulp.task('vendorScripts', function () {
return gulp.src(config.vendor.scripts.src)
.pipe(concat(config.vendor.scripts.output))
.pipe(uglify())
.pipe(gulp.dest(config.vendor.scripts.dest));
});
gulp.task('vendorStyles', function () {
return gulp.src(config.vendor.styles.src)
.pipe(concat(config.vendor.styles.output))
.pipe(postcss([ cssnano() ]))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(config.vendor.styles.dest));
});
gulp.task('vendor', ['vendorScripts', 'vendorStyles']);

Categories