Just attempting to move from grunt to gulp and learning as I go. One item which has had me scratching my head is the error "Did you forget to signal async completion?" when trying to run requirejs (js:rjs in the gulpfile below). My very basic gulpfile.js is:
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var rjs = require('gulp-requirejs');
gulp.task('sass', function()
{
return gulp.src('./*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./'));
});
gulp.task('sass:watch', function()
{
gulp.watch('./*.scss', gulp.series('sass'));
});
gulp.task('js:rjs', function()
{
return rjs({
baseUrl: "./script.js",
out: "./script.rjs.js",
})
.pipe(gulp.dest('./'));
});
The answer at https://stackoverflow.com/a/36899424/1424591 seems pretty exhaustive but I want to know how I can identify which of these solutions is required here and why. I have tried the callback method
gulp.task('js:rjs', function(done)
{
return rjs({
baseUrl: "./script.js",
out: "./script.rjs.js",
})
.pipe(gulp.dest('./'));
done();
});
which results in the same issue.
Related
I'm having trouble with browserSync I can't get reload do trigger after trying several different methods. BrowserSync itself is up and running although when I manually reload nothing happens I have to open a new tab to see any changes. I'm not really understanding gulp 4 and all the sources I have watched seem to be using completely different methods to me. Any help would be greatly appreciated feel free to ask any questions.
var gulp = require('gulp');
var sass = require('gulp-sass');
var concatcss = require('gulp-concat');
var concatjs = require('gulp-concat');
var uglifycss = require('gulp-uglifycss');
var reload = require('browser-sync').reload();
var nunjucks = require('gulp-nunjucks-render');
var browserSync = require('browser-sync').create();
sass.compiler = require('node-sass');
gulp.task('sass', function () {
return gulp.src('./Edit/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./Edit/css'));
});
gulp.task('concatcss', function() {
return gulp.src('./Edit/css/*.css')
.pipe(concatcss('style.css'))
.pipe(gulp.dest('./Edit/css/concated/'));
});
gulp.task('concatjs', function() {
return gulp.src('./Edit/java-script/*.js')
.pipe(concatjs('scripts.js'))
.pipe(gulp.dest('./Upload/js/'));
});
gulp.task('css', function () {
return gulp.src('./Edit/css/concated/*.css')
.pipe(uglifycss({
"maxLineLen": 80,
"uglyComments": true
}))
.pipe(gulp.dest('./upload/css'));
});
gulp.task('browserSync', function() {
browserSync.init({
server: {
baseDir: "./Upload/"
}
});
});
gulp.task('run',gulp.parallel('browserSync', gulp.series('sass','concatcss','concatjs','css')));
gulp.task('watch', function(){
gulp.watch('./Edit/sass/*.scss',gulp.series('sass'));
gulp.watch('./Edit/css/*.css',gulp.series('concatcss'));
gulp.watch('./Edit/java-script/*.js',gulp.series('concatjs')); // maybe put extra task in all gulp series for browser sync
gulp.watch('./Edit/css/concated/*.css', gulp.series('css'));
});
gulp.task('default', gulp.parallel('watch', 'run'));
For anyone else having trouble here is my solution, simply add this .on('change', browserSync.relod) to the end of the desired watch.
gulp.task('watch', function(){
gulp.watch('./Edit/sass/*.scss',gulp.series('sass'));
gulp.watch('./Edit/css/*.css',gulp.series('concatcss'));
gulp.watch('./Edit/java-script/*.js',gulp.series('concatjs')); // maybe put extra task in all gulp series for browser sync
gulp.watch('./Edit/css/concated/*.css', gulp.series('css'));
gulp.watch('./Upload/css/*.css').on('change', browserSync.reload);
gulp.watch('./Upload/js/*.js').on('change', browserSync.reload);
});
Problems I'm facing:
The browser doesn't reflect live changes in .scss or .js
I don't understand whether we have to return the stream from the gulp.task() or not, I visited some websites and watched lectures some of which used return and some didn't.
Cannot understand the flow of execution of gulpfile (which statement runs first, then which and so on)
This is my current code of gulpfile.js.
"use strict";
var gulp = require('gulp');
var sass = require('gulp-sass');
var nodemon = require('gulp-nodemon');
var browserSync = require('browser-sync').create();
var uglify = require('gulp-uglify');
gulp.task('default', ['nodemon'], function(){
gulp.watch("src/sass/*.scss", ['sass']);
gulp.watch("src/js/*.js", ['js']);
gulp.watch("views/*.ejs").on('change',browserSync.reload); //Manual Reloading
})
// Process JS files and return the stream.
gulp.task('js', function () {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('public/javascripts'));
});
// Compile SASS to CSS.
gulp.task('sass', function(){
// gulp.src('src/sass/*.scss') //without return or with return? why?
return gulp.src('src/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('public/stylesheets'))
.pipe(browserSync.stream());
});
// Setup proxy for local server.
gulp.task('browser-sync', ['js','sass'], function() {
browserSync.init(null, {
proxy: "http://localhost:3000",
port: 7000,
});
});
gulp.task('nodemon', ['browser-sync'], function(cb){
var running = false;
return nodemon({script: 'bin/www'}).on('start', function(){
if(!running)
{
running = true;
cb();
}
});
})
You may look at project structure at https://github.com/DivyanshBatham/GulpWorkflow
Try this:
"use strict";
var gulp = require('gulp');
var sass = require('gulp-sass');
var nodemon = require('gulp-nodemon');
var browserSync = require('browser-sync').create();
var uglify = require('gulp-uglify');
// First, run all your tasks
gulp.task('default', ['nodemon', 'sass', 'js'], function(){
// Then watch for changes
gulp.watch("src/sass/*.scss", ['sass']);
gulp.watch("views/*.ejs").on('change',browserSync.reload); //Manual Reloading
// JS changes need to tell browsersync that they're done
gulp.watch("src/js/*.js", ['js-watch']);
})
// create a task that ensures the `js` task is complete before
// reloading browsers
gulp.task('js-watch', ['js'], function (done) {
browserSync.reload();
done();
});
// Process JS files and return the stream.
gulp.task('js', function () {
return gulp.src('src/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('public/javascripts'));
});
// Compile SASS to CSS.
gulp.task('sass', function(){
return gulp.src('src/sass/*.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('public/stylesheets'))
.pipe(browserSync.stream());
});
// Setup proxy for local server.
gulp.task('browser-sync', ['js','sass'], function() {
browserSync.init(null, {
proxy: "http://localhost:3000",
port: 7000,
});
});
gulp.task('nodemon', ['browser-sync'], function(cb){
var running = false;
return nodemon({script: 'bin/www'}).on('start', function(){
if(!running)
{
running = true;
cb();
}
});
})
Also, you should consider adding the JS file to your index.ejs
Eg: <script src='/javascripts/main.js'></script>
More help: https://browsersync.io/docs/gulp
I'll answer what I can.
You don't always have to return the stream in a gulp task but you should since you have some tasks, like 'browser-sync' that are dependent on other tasks, ['js','sass'], finishing. The purpose of returning the stream is to signal task completion. It is not the only way to signal task completion but one easy way.
You are already doing this in your ['js','sass'] tasks with the return statements.
Your 'js' task needs a .pipe(browserSync.stream()); statement at the end of it like your 'sass' task. Or try .pipe(browserSync.reload({stream:true})); sometimes that variant works better.
You have both browser-sync and nodemon running - that I believe is unusual and may cause problems - they do much the same thing and do not typically see them running together. I would eliminate nodemon from your file.
Flow of execution:
(a) default calls ['nodemon', 'sass', 'js'] : these run in parallel.
(b) nodemon call 'browser-sync'. 'browserSync' must finish setting up before 'nodemon' gets into its function.
(c) 'browser-sync', ['js','sass'], Here browser-sync is dependent upon 'js' and 'sass' which run in parallel and must finish and signal that they have finished by returning the stream for example before browser-sync continues.
(d) After 'js', 'sass', 'browser-sync' and 'nodemon' have completed, your watch statements are set up and begin to watch.
When I use partials on the scss structure, I have to deal with frequent browser sync error (like reloading forever). Notice that it is an intermittent error so it is not a common compiling problem (although it might be somewhat related) and it doesn't happen when I don't use partials. Also, I don't think it is project related or a gulpfile issue either, since it occurs with any project and I have tried more than one gulpfile structure. Anyway, you can check it out below:
var gulp = require('gulp');
var sass = require('gulp-sass');
var clean = require('gulp-clean');
var browserSync = require('browser-sync').create();
var autoprefixer = require('gulp-autoprefixer');
gulp.task('styles', function () {
gulp.src('src/scss/app.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(gulp.dest('src/css'))
.pipe(browserSync.reload({stream: true}));
});
gulp.task('copy', ['clean'], function () {
return gulp.src('src/**/*')
.pipe(gulp.dest('dist'));
});
gulp.task('clean', function () {
return gulp.src('dist')
.pipe(clean());
});
gulp.task('serve',function () {
browserSync.init({
server: {
baseDir: 'src/'
}
});
gulp.watch('src/scss/*.scss', ['styles']);
gulp.watch('src/**/*').on('change', browserSync.reload)
});
gulp.task('default', ['styles', 'serve']);
A couple of things that might help: (1) add a return statement in your 'styles' task and (2) remove the second watch because it calls browserSync.reload which is already called at the end of the 'styles' task and you don't need to call it twice. So make these changes:
gulp.task('styles', function () {
// added return below
return gulp.src('src/scss/app.scss')
.pipe(sass().on('error', sass.logError))
.pipe(autoprefixer())
.pipe(gulp.dest('src/css'))
.pipe(browserSync.reload({stream: true}));
});
and the second watch is unnecessary and possibly a problem:
gulp.task('serve',function () {
browserSync.init({
server: {
baseDir: 'src/'
}
});
gulp.watch('src/scss/*.scss', ['styles']);
// remove below watch
// gulp.watch('src/**/*').on('change', browserSync.reload)
gulp.watch("./*.html").on("change", browserSync.reload);
});
OK. I am having trouble with this code. I've used gulp-ruby-sass before, but I have not encountered this kind of error until now. I am using gulp-ruby-sass 1.0.0. I am simply trying to use gulp-ruby-sass to run my sass files in css. However, this is obviously not working. Any suggestions would be appreciated.
Here's the error:
TypeError: string is not a function
at Gulp.<anonymous> (/Users/xxxxxxxxxxx/xxxx/xxxxxxx/gulpfile.js:22:15)
at module.exports (/Users/xxxxxxxxxxx/xxxx/xxxxxxxx/node_modules/gulp/node_modules/orchestrator/lib/runTask.js:34:7)
at Gulp.Orchestrator._runTask (/Users/xxxxxxxxxxx/xxxx/xxxxxxx/node_modules/gulp/node_modules/orchestrator/index.js:273:3)
at Gulp.Orchestrator._runStep (/Users/xxxxxxxxxxx/xxxx/xxxxxxx/node_modules/gulp/node_modules/orchestrator/index.js:214:10)
at Gulp.Orchestrator.start (/Users/xxxxxxxxxxx/xxxx/xxxxxxx/node_modules/gulp/node_modules/orchestrator/index.js:134:8)
at /usr/local/lib/node_modules/gulp/bin/gulp.js:129:20
at process._tickCallback (node.js:442:13)
at Function.Module.runMain (module.js:499:11)
at startup (node.js:119:16)
at node.js:929:3
The Gulp code I am using for my project is the following:
var gulp = require('gulp'),
sass = ('gulp-ruby-sass'),
uglify = require('gulp-uglify'),
livereload = require('gulp-livereload'),
plumber = require('gulp-plumber'),
jshint = require('gulp-jshint');
var paths = {
sass: 'stylesheets/scss/',
css: 'stylesheets/css'
};
gulp.task('lint', function() {
return gulp.src('angular/app.js')
.pipe(jshint())
.pipe(jshint.reporter());
});
gulp.task('sass', function() {
return gulp.src(paths.sass + '*.scss')
.pipe(plumber())
.pipe(sass({style: 'expanded'})) // HERE IS WHERE THE ERROR OCCURS
.pipe(gulp.dest(paths.css + '*.css'))
.pipe(livereload());
});
gulp.task('scripts', function() {
return gulp.src('angular/app.js')
.pipe(plumber())
.pipe(uglify())
.pipe(gulp.dest('angular/minjs'))
.pipe(livereload());
});
gulp.task('watch', function() {
livereload.listen();
gulp.watch(paths.sass + '*.scss', ['sass']);
gulp.watch('angular/app.js', ['scripts']);
});
gulp.task('default', ['lint', 'sass', 'scripts', 'watch']);
Thanks to #Aperçu for spotting the error of not putting require at the beginning of ('gulp-ruby-sass). Stupid mistake.
So here is the answer that is working which I got from the new documentation for Gulp-Ruby-Sass 1.0.0-alpha. The new documentation notes that you have to get rid of gulp src. Here's the code I used to make everything work.
Old Code
gulp.task('sass', function() {
return gulp.src(paths.sass + '*.scss')
.pipe(plumber())
.pipe(sass({style: 'expanded'})) // HERE IS WHERE THE ERROR OCCURS
.pipe(gulp.dest(paths.css + '*.css'))
.pipe(livereload());
});
New Code
gulp.task('sass', function() {
return sass(paths.sass, {style: 'expanded'})
.pipe(plumber())
.pipe(gulp.dest(paths.css))
.pipe(livereload());
});
Note: the new documentation does not support globs.
what's wrong with this code:
var gulp = require('gulp');
var watch = require('gulp-watch');
var connect = require('gulp-connect');
var jshint = require('gulp-jshint');
var stylish = require('jshint-stylish');
//lint
module.exports = gulp.task('lint', function () {
return gulp.src([config.paths.src.scripts,config.paths.exclude.bower])
.pipe(jshint())
.pipe(jshint.reporter(stylish));
});
//watch
module.exports = gulp.task('watch', function () {
watch(config.paths.src.scripts, ['lint'])
.pipe(connect.reload());
watch(config.paths.src.templates, ['templates'])
.pipe(connect.reload());
watch(config.paths.src.index)
.pipe(connect.reload());
});
when ie I edit a js file doing an error
jshint show me nothing.
This works:
watch(config.paths.src.scripts)
.pipe(jshint())
.pipe(jshint.reporter(stylish))
.pipe(connect.reload());
but it's quite the same or not ?
gulp-watch does not support an array of task names like the internal gulp.watch. See documentation at https://www.npmjs.org/package/gulp-watch
You have to provide gulp-watch a function, something like
watch(config.paths.src.scripts, function(events, done) {
gulp.start(['lint'], done);
}
Note: It seems that gulp.start will be deprecated in Gulp 4.x, it will be replaced by a task runner called bach: https://github.com/floatdrop/gulp-watch/issues/92