Gulp not concatenating js file in correct order - javascript

I am concatenating and minifying js files using gulp. But files are not concatenating in the order it should be, like this is the order I want :
var scriptFiles = [
'assets/lib/js/angular.min.js',
'assets/lib/js/angular-sanitize.min.js',
'assets/lib/js/angular-route.min.js',
'assets/lib/js/angular-ui-router.min.js',
'assets/lib/js/angular-css.min.js',
'assets/lib/js/angular-select.min.js',
'assets/lib/js/duration.js',
'assets/lib/js/ui-codemirror.min.js',
];
The problem is, after concatenation ui-codemirror.min.js file goes to top of the compiled file, which breaks the javascript since angular.js is not initialized/loaded.
To solve this problem I tried to use "gulp-order" package and wrote this gulp task:
gulp.task('lib-js', function() {
return gulp.src(scriptFiles)
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(order(scriptFiles, { base: './' }))
.pipe(concat('vendor.js'))
.pipe(gulp.dest('assets/compiled/js'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('assets/compiled/js'))
});
I passed the same scriptFiles array to try to preserve the order. But it did not work.
Then I tried the streamqueue plugin, and change the task:
gulp.task('lib-js', function() {
return streamqueue({ objectMode: true },
gulp.src('assets/lib/js/angular.min.js'),
gulp.src('assets/lib/js/angular-sanitize.min.js'),
gulp.src('assets/lib/js/angular-route.min.js?v=20161018-1'),
gulp.src('assets/lib/js/angular-ui-router.min.js'),
gulp.src('assets/lib/js/angular-css.min.js'),
gulp.src('assets/lib/js/angular-select.min.js'),
gulp.src('assets/lib/js/jquery-2.1.1.min.js'),
gulp.src('assets/lib/js/material.min.js'),
gulp.src('assets/lib/js/ocLazyLoad.min.js'),
gulp.src('assets/lib/js/duration.js'),
gulp.src('assets/lib/js/ui-codemirror.min.js')
)
.pipe(concat('vendor.js'))
.pipe(gulp.dest('assets/compiled/js'))
.pipe(rename({ suffix: '.min' }))
.pipe(uglify())
.pipe(gulp.dest('assets/compiled/js'))
});
This did not work either. I am unable to debug why this is happening. "order" and "streamqueue" plugin had not effect on the output. Any idea/solution?

Related

Gulp multiple src

I am trying to inject a concatenated css file into my index.html using 'gulp-inject' and then version my files. I can get this working separately but what I am trying to do is compile everything in a single task so that I can run assetVersion() against certain files and the index.html. The problem I have is that my 'styles.min.css' is not written to disk and I'm not sure how to combine the streams to achieve my goal. Can anyone help?
gulp.task('compile',['clean'],function() {
// CSS - minify, concat to one file and copy
gulp.src(paths.css + '*', { base: paths.base })
.pipe(cleanCSS())
.pipe(concat('styles.min.css'))
.pipe(gulp.dest(paths.dist + paths.css));
// Images - minify and copy
gulp.src(paths.images + '*', { base: paths.base })
.pipe(imagemin())
.pipe(gulp.dest(paths.dist));
// Index.html - inject the concatenated css, asset version and copy to dist
gulp.src(paths.index)
.pipe(inject(gulp.src(paths.dist + paths.css + 'styles.min.css', {read: false})))
.pipe(debug())
.pipe(assetVersion())
.pipe(gulp.dest(paths.dist));
});
You can use run-sequence to force run each task synchronously.
var runSequence = require('run-sequence')
gulp.task('compile', ['clean'], function() {
return runSequence(['compile:css', 'compile:images'], 'compile:version');
});
gulp.task('compile:css', function() {
// CSS - minify, concat to one file and copy
return gulp.src(paths.css + '*', { base: paths.base })
.pipe(cleanCSS())
.pipe(concat('styles.min.css'))
.pipe(gulp.dest(paths.dist + paths.css));
});
gulp.task('compile:images', function() {
// Images - minify and copy
return gulp.src(paths.images + '*', { base: paths.base })
.pipe(imagemin())
.pipe(gulp.dest(paths.dist));
});
gulp.task('compile:version', function() {
// Index.html - inject the concatenated css, asset version and copy to dist
return gulp.src(paths.index)
.pipe(inject(gulp.src(paths.dist + paths.css + 'styles.min.css', { read: false })))
.pipe(debug())
.pipe(assetVersion())
.pipe(gulp.dest(paths.dist));
});

GulpUglifyError:Unable to minify JavaScript

I am trying to minify my script files for which i am using gulp task runner
And I am trying gulp-uglify plugin
Code:
gulp.task('concat', function() {
return gulp.src('app/**/*.js')
// .pipe(concat('script.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist/'))
});
but i am getting error as
when i try to run gulp task as gulp concat
Any help would be appreciated
The main error is generated when you're using ES6 format. Use the gulp-uglify-es module instead of 'gulp-uglify' to overcome this error.
var uglify = require('gulp-uglify-es').default;
Note: gulp-uglify-es is no longer being maintained. You may want to use terser/gulp-terser instead:
To see the error in console:
var gutil = require('gulp-util');
gulp.task('concat', function() {
return gulp.src('app/**/*.js')
// .pipe(concat('script.js'))
.pipe(uglify())
.on('error', function (err) { gutil.log(gutil.colors.red('[Error]'), err.toString()); })
.pipe(gulp.dest('./dist/'))
});
To find the exact file, with line number of error register and run this task:
var pump = require('pump');
gulp.task('uglify-error-debugging', function (cb) {
pump([
gulp.src('app/**/*.js'),
uglify(),
gulp.dest('./dist/')
], cb);
});
I think the top answers here are not explaining how to get the error. The docs have a section on error handling:
gulp-uglify emits an 'error' event if it is unable to minify a
specific file
So, just capture the error and do whatever you want with it (such as logging to console) to see the filename, line number, and additional info:
uglify().on('error', console.error)
or in a larger context:
gulp.task('foo', () => {
return gulp.src([
'asset/src/js/foo/*.js',
'asset/src/js/bar/*.js',
])
.pipe(uglify().on('error', console.error))
.pipe(concat('bundle.js'))
.pipe(gulp.dest('./'));
});
This gives you a super helpful error!
{ GulpUglifyError: unable to minify JavaScript
at [stack trace])
cause:
{ SyntaxError: Continue not inside a loop or switch
[stack trace]
message: 'Continue not inside a loop or switch',
filename: 'ProductForm.js',
line: 301,
col: 37,
pos: 10331 },
plugin: 'gulp-uglify',
fileName:
'/asset/src/js/foo/ProductForm.js',
showStack: false }
Have you used ES6 format in your script file?
If so try ES5 now because when you do gulp-uglify it doesnt understand ES6 format as of now
and after that try your code
gulp.task('concat', function() {
return gulp.src('app/**/*.js')
.pipe(concat('script.js'))
.pipe(uglify())
.pipe(gulp.dest('./dist/'))
});
and run the task gulp concat it will work
For me, it was a deprecated option "preserveComments" that generated the error (and completely crashed the script).
Found the issue using:
gulp.task('concat', function() {
return gulp.src('app/**/*.js')
.pipe(uglify())
.on('error', function (err) { console.log( err ) })
.pipe(gulp.dest('./dist/'))
});
Try using this
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
var minifyJS = require('gulp-minify');
gulp.task('concat', function() {
return gulp.src('app/**/*.js')
.pipe(minifyJS())
.pipe(concat('bundle.min.js'))
.pipe(uglify({ mangle: false }))
.pipe(gulp.dest('./dist/'));
});
you may have syntax error or used ES6 syntax. you can try https://skalman.github.io/UglifyJS-online/ firstly.
The main error to Unable to minifies JavaScript is the path not found. You can use the task usemin For this you need:
$ sudo npm install gulp-usemin --save-dev
$ sudo npm install gulp-livereload --save-dev
$ sudo npm install gulp-util --save-dev
and requires :
var usemin = require('gulp-usemin');
var livereload = require('gulp-livereload');
var gutil = require('gulp-util'); //gutil for error display
gulp.task('usemin',['jshint'], function(){
return gulp.src('./app/index.html')
.pipe(usemin({
css: [minifycss(),rev()],
scripts: [uglify().on('error', function(err) {gutil.log(gutil.colors.red('[Error]'), err.toString());this.emit('end');}),rev()]
}))
.pipe(gulp.dest('dist'))
.pipe(livereload());
});
Change the js: [uglify(), rev()] to scripts: [uglify(), rev()]

Gulp dest: warn if 2 tasks try to write to the same destination

I wonder if there is an easy way to detect if two tasks write to the same file.
In this example there is a /js directory alongside a /ts directory. The /ts will get transpiled to the same directory as the /js. There shouldn't be any collisions. The ask is that, if there are collisions, the ts will win; but, I would like to warn that there is a collision.
gulp.task('js', function() {
return es.concat(
gulp.src(config.src.path('js', '**', '*.js'))
.pipe(gulp.dest(config.build.path(app, 'js')))
//, ....
);
});
gulp.task('ts', ['js'], function() {
var tsResult = gulp.src(config.src.path('ts', '**', '*.ts'))
.pipe(ts({
declaration: true,
noExternalResolve: true
}));
return es.concat([
tsResult.dts.pipe(gulp.dest(
config.build.path(app, 'definitions'))),
tsResult.js.pipe(gulp.dest(
config.build.path(app, 'js'))) // <--- same dest as js task
]);
})
Can I detect that the ts task is overwriting a file that the js task just put in place?
Just an idea. You can pass a callback to gulp.dest like this:
gulp.src('lib/*.js')
.pipe(uglify())
.pipe(gulp.src('styles/*.css'))
.pipe(gulp.dest(function(file) {
if (fs.existsSync('something here')) { // it's a deprecated call, use a newer one
console.warn("File exists", file);
}
// I don't know, you can do something cool here
return 'build/whatever';
}));
The feature is available since Gulp 3.8: https://github.com/gulpjs/gulp/blob/master/CHANGELOG.md#380
Other resources:
https://stackoverflow.com/a/29437418/99256
https://stackoverflow.com/a/29817916/99256

Combine gulp tasks to avoid creating the unnecessary files

I'm using two separate gulp tasks to minify templates into js file (1) and concat all js file of the project to the only minified (2).
gulp.task('templates', function() { // RESULT of this task
return gulp.src('templates/**/*.html')
.pipe(dotify({
root : 'templates'
}))
.pipe(concat('templates.js'))
.pipe(gulp.dest('js'));
});
gulp.task('minifyJs', ['templates'], function() {
return gulp.src([
'js/templates.js',
'js/plugins/*.js',
'js/*.js'
])
.pipe(concat('scripts-all.js'))
});
The question is: am I able to avoid creating the templates.js file by processing the result from first task to the second one to concat it with the rest of js's?
Solution: addSrc should be used
return gulp.src('templates/**/*.html')
.pipe(dotify({
root : 'templates'
}))
.pipe(addSrc([
'js/plugins/*.js',
'js/common/*.js',
'js/ui/*.js',
'js/pages/*.js',
'js/*.js'
]))
.pipe(concat('scripts-all.js'))
.pipe(gulp.dest('js/'));

Gulp browser-sync only works once

I'm trying out Gulp on one of my projects and I wanted to run it like I used to with Grunt watch. Meaning, it has to watch less files and js files, lint, merge, compile and refresh the browser once all that is done.
I managed to make it work with gulp-browser-sync but for some reason it only works once. I do a change to my .less file and the browser reloads. Then, a second change, it does compile but no reload happens.
Here's the log:
[BS] Serving files from: ./
[09:47:26] Starting 'css-clean'...
[09:47:26] Finished 'css-clean' after 16 ms
[09:47:26] Starting 'styles'...
[BS] 1 file changed (styles.min.css)
[09:47:27] Finished 'styles' after 624 ms
[09:47:27] Starting 'styles-watch'...
[BS] Reloading Browsers...
And when I hit save a second time:
[09:47:31] Starting 'css-clean'...
[09:47:31] Finished 'css-clean' after 3.39 ms
[09:47:31] Starting 'styles'...
[BS] 1 file changed (styles.min.css)
[09:47:32] Finished 'styles' after 362 ms
As for the JS, it works all the time. No issues whatsoever, even after the styles task is done, the JS changes are still triggering the reload properly. Really is only the styles that has issues.
Here's the gulpfile.js
var gulp = require('gulp'),
autoprefixer = require('gulp-autoprefixer'),
less = require('gulp-less'),
minifycss = require('gulp-minify-css'),
concat = require('gulp-concat'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
rename = require('gulp-rename'),
notify = require('gulp-notify'),
path = require('path'),
streamqueue = require('streamqueue'),
clean = require('gulp-clean'),
browserSync = require('browser-sync').create(),
reload = browserSync.reload;
// Clean the CSS folder
gulp.task('css-clean', function () {
return gulp.src(['dist/css'], {read: false})
.pipe(clean());
});
// Clean the CSS folder
gulp.task('js-clean', function () {
return gulp.src(['dist/js'], {read: false})
.pipe(clean());
});
// Generate the CSS styles, clean before hand
gulp.task('styles', ['css-clean'], function() {
return streamqueue({ objectMode: true },
gulp.src(['./bower_components/uikit/less/uikit.less']),
gulp.src(['./src/less/main.less'])
)
.pipe(concat('styles.less'))
.pipe(less({
paths: [ path.join(__dirname, 'less', 'includes') ]
}))
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(gulp.dest('dist/css'))
.pipe(rename({suffix: '.min'}))
.pipe(minifycss())
.pipe(gulp.dest('dist/css'))
.pipe(browserSync.reload({stream:true}));
});
// create a task that ensures the `styles` task is complete before
// reloading browsers
gulp.task('styles-watch', ['styles'], browserSync.reload);
// Lint Task
gulp.task('lint', function() {
return gulp.src('src/js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'));
});
// Generate the scripts, clean before hand
gulp.task('scripts', ['js-clean', 'lint'], function() {
return streamqueue({ objectMode: true },
gulp.src(['./bower_components/jquery/dist/jquery.js']),
gulp.src(['./bower_components/modernizer/modernizr.js']),
gulp.src(['./bower_components/uikit/js/uikit.js']),
gulp.src(['./src/js/plugin.js']),
gulp.src(['./src/js/main.js'])
)
.pipe(concat('scripts.js'))
.pipe(gulp.dest('dist/js'))
.pipe(rename({suffix: '.min'}))
.pipe(uglify())
.pipe(gulp.dest('dist/js'))
.pipe(browserSync.reload({stream:true}));
});
// create a task that ensures the `scripts` task is complete before
// reloading browsers
gulp.task('scripts-watch', ['scripts'], browserSync.reload);
// Lint Task
gulp.task('alldone', ['scripts'], function() {
return gulp.src('src/js/*.js')
.pipe(notify({ message: 'Gulp tasks are completed!!' }));
});
// Static server
gulp.task('browsersync', function() {
browserSync.init({
server: {
baseDir: "./"
}
});
gulp.watch("src/less/*.less", ['styles-watch']);
gulp.watch('src/js/*.js', ['lint', 'scripts-watch']);
gulp.watch("*.html").on('change', reload);
});
// Default Task
gulp.task('default', ['css-clean', 'js-clean', 'styles', 'lint', 'scripts', 'alldone']);
// Build Task
gulp.task('build', ['css-clean', 'js-clean', 'styles', 'lint', 'scripts', 'alldone']);
Thanks for your help!
For me in Gulp 4, the anonymous function didn't solve the issue, What I did was wrap the browserSync.reload() in a function with a done callback:
function reload(done) {
browserSync.reload();
done();
}
gulp.watch(['scripts/**/*.js','!scripts/main.min.js'], gulp.series(buildScripts, reload));
How about directly use
.pipe(browserSync.stream())
I once had the same problem while changing '.jade' files which it only reloaded once. Then I wrapped browserSync.reload in an anonymous function like
gulp.task('templates-watch', ['templates'], function() {
browserSync.reload();
});
It works for me. I don't know if there is something special about browserSync.reload. How about have a try. :)
I know this is not the right way to do things, but after some trial and error I figured out that using an undefined function after browserSync.reload()
gulp.watch("./**/*.php", function () {
browserSync.reload();
done();
});
leads to a reference error in my log which triggers to reload the browser:
ReferenceError: done is not defined
at ...
at ...
at asyncRunner (...)
at processTicksAndRejections (...)
[Browsersync] Reloading Browsers...
Are you sure the CSS is not changed in the browser? New styles are loaded without requiring to reload the page. At least that is what my gulp setup is doing.
Try changing the .less file, and see if the change is actually visible in the browser.
My situation is a little different, but it might be similar enough to be helpful to you or someone else. I have gulp + browserSync set up like this:
.task('serve', ['clean', 'lint', 'sass', 'js', 'server'], function () {
return gulp.watch([paths.js, paths.html, paths.sass],
['lint', 'sass', 'js', browserSync.reload]);
})
This would start up and open the page once. If I made a change to the HTML page and save it, I could see lint, sass, js, and browserSync.reload run, but the browser didn't refresh. My HTML was very simple; this:
<!doctype html>
<html>
TEST
</html>
I changed the HTML to this finally and it started working:
<!doctype html>
<html>
<head>
<title>TEST</title>
</head>
<body>
HELLO-TEST
</body>
</html>
I am facing same issue.looks there is issue with 'asyncDone' function inside node_modules. here is file path: /node_modules/glob-watcher/index.js
following is only dirty hack for temp fix. you may have issues sometimes. but worked for me.
function onChange() {
console.log("onChange running: ", running);
/** existing code */
// keeping this function at it worked for me.
setTimeout(() => {
runComplete({msg: "test"});
}, 2000);
}

Categories

Resources