I am totally new to gulp and I wanted to add a task to minify and eventually clean any duplicates or unused css. My gulpfile is below, and for the moment I'm still in the process of learning.
I know I will be using post-css and the modules that can go with it, later on. Right now I get an error: "Cannot read property 'on' of undefined at DestroyableTransform.Readable.pipe". It comes from the cleancss task, when I take it out, there's no errors. Any help and suggestions would be appreciated.
//JS
var gulp = require('gulp');
var sass = require('gulp-sass');
var browserSync = require('browser-sync');
var cleancss = require('clean-css');
var autoPrefixer = require('gulp-autoprefixer');
gulp.task('autoPrefixer', function() {
return gulp.src('../css/*.css')
.pipe(autoPrefixer ({
browsers: ['last 2 versions'],
}))
.pipe(gulp.dest('../css'))
});
gulp.task('cleancss', function() {
return gulp.src('../css/*.css')
.pipe(cleancss({compatibility: 'ie8'}))
.pipe(gulp.dest('../css/min'));
});
gulp.task('sass', function(){
return gulp.src('../scss/*.scss')
.pipe(sass().on('error', function(err) {
console.error('\x07'); // so it doesn't just fail (literally) silently!
sass.logError.bind(this)(err);
})) // Converts Sass to CSS with gulp-sass
.pipe(gulp.dest('../css'))
.pipe(autoPrefixer())
.pipe(browserSync.reload({
stream: true
}))
});
gulp.task('watch', ['browserSync','sass','autoPrefixer','cleancss'], function() {
gulp.watch('../scss/*.scss', ['sass']);
gulp.watch('../*.php', browserSync.reload);
gulp.watch('../js/*.js', browserSync.reload);
});
gulp.task('browserSync', function() {
browserSync.init ({
open: 'external',
host: 'testsite.local',
proxy: 'testsite.local',
port: 3000
})
browserSync ({
server: {
baseDir: 'app'
},
})
});
You should use the gulp plugin for cleancss, rather than cleancss directly.
var cleancss = require('gulp-clean-css');
instead of
var cleancss = require('clean-css');
Remember to install it if you haven't done that already:
npm install gulp-clean-css --save-dev
I actually managed to make it work by using "vynil-map" as discussed on here : https://github.com/jakubpawlowicz/clean-css/issues/342. Hope this link could help anybody else having the same problem.
Related
Browser console doesn't watch errors but when I try to run the command in git console I have got a error.
let gulp = require('gulp');
let sass = require('gulp-sass');
let watch = require('gulp-watch');
let browserSync = require('browser-sync');
gulp.task('sass', function() {
return gulp.src('src/scss/index.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('src/css/index.css'))
});
gulp.task('sass:watch', function() {
gulp.watch('src/scss/index.scss', ['sass']);
});
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: 'src'
},
notify: false
});
});
Link to my repository https://github.com/dzhulay/Step-Ham
The gulp.watch function requires a list of files and a function as second parameter.
You have to generate the function either with gulp.parallel or gulp.series, such as in your case:
gulp.task('watch', function() {
gulp.watch('src/scss/index.scss', gulp.series('sass'));
});
Also, in order to avoid the "file exists" error as specified in your comment, please implement "gulp-chmod" in your sass task, such as:
var chmod = require('gulp-chmod');
gulp.task('sass', function() {
return gulp.src('src/scss/index.scss')
.pipe(chmod(0o755))
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('src/css/index.css'))
});
I have my gulpfile:
var gulp = require('gulp');
var sass = require('gulp-sass');
var watch = require('gulp-watch');
var sourcemaps = require('gulp-sourcemaps');
var fileinclude = require('gulp-file-include');
var browserify = require('browserify');
var rename = require('gulp-rename');
var streamify = require('gulp-streamify'); // required for uglify
var uglify = require('gulp-uglify'); // minify JS
var source = require('vinyl-source-stream'); // required to dest() for browserify
var browserSync = require('browser-sync').create();
var localSettings = require('./gulp/localConfig.js');
gulp.task('sass', function () {
return gulp.src('./assets/sass/main.scss')
.pipe(sourcemaps.init())
.pipe(sass().on('error', sass.logError)) // .on('error', sass.logError) prevents gulp from crashing when saving a typo or syntax error
.pipe(sourcemaps.write())
.pipe(gulp.dest('./assets/sass'))
.pipe(browserSync.stream()); // causes injection of styles on save
});
gulp.task('compileHTML', function() {
return gulp.src(['static/src/*.html'])
.pipe(fileinclude({
prefix: '##',
basepath: '#root'
}))
.pipe(gulp.dest('./static/compiled'))
.pipe(browserSync.stream()); // causes injection of html changes on save
});
// Static Server for browsersync
gulp.task('sync', ['sass'], function() {
browserSync.init({
startPath: "static/compiled/index.html",
open: localSettings.openBrowserSyncServerOnBuild,
server: {
baseDir: "./",
}
});
});
gulp.task('watch', function() {
gulp.watch('./assets/sass/**/*.scss', ['sass']);
gulp.watch(['./static/src/**/*.html', '!partials', '!components'], ['compileHTML']);
gulp.watch('./assets/js/**/*.js', ['javascript']);
});
gulp.task('javascript', function() {
var bundleStream = browserify('./assets/js/main.js').bundle();
bundleStream
.pipe(source('main.js'))
.pipe(rename('bundle.js'))
.pipe(gulp.dest('./assets/js/'))
.pipe(browserSync.stream());
})
// Default Task
gulp.task('default', ['compileHTML', 'javascript', 'sass', 'watch', 'sync']);
Mostly everything with my build works great, however I am having one issue with my compileHTML task. When any modifications are made to my html, it is compiled and injected into the page with BrowserSync. The problem is that BrowserSync is injecting the markup into the page AFTER it reloads, so that I have to manually refresh or save the file again.
Although I am doing the exact same thing with my SASS task, I have no problems with that task. Why do my styles inject into the page before the reload, but the HTML does not?
Just for testing, I tried adding a setTimout surrounding the BrowserSync injection, but it did not affect the timing of the injection other than adding a delay.
I would try to follow the example at gulp-reload docs. Their example is:
// create a task that ensures the `js` task is complete before
// reloading browsers
gulp.task('js-watch', ['js'], function (done) {
browserSync.reload();
done();
});
So you try :
gulp.watch(['./static/src/**/*.html', '!partials', '!components'], ['compileHTML'],
function (done) {
browserSync.reload();
done();
});
And remove the pipe browserSync.stream() in your 'complieHTML' task.
[I might first try as a very simple attempt changing from stream() to reload() in that task before the changes above.]
I have a gulpfile running to compile Sass, CoffeeScript, and live reload both through Browsersync:
var gulp = require('gulp');
var plumber = require('gulp-plumber');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var cssmin = require('gulp-cssmin');
var coffee = require('gulp-coffee');
var uglify = require('gulp-uglify');
var browserSync = require('browser-sync');
gulp.task('sass', function() {
return gulp.src('./src/scss/**/*.scss')
.pipe(plumber())
.pipe(sass({
style: 'expanded',
precision: 10
}))
.pipe(autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
.pipe(cssmin())
.pipe(gulp.dest('./dist'))
.pipe(browserSync.stream());
});
gulp.task('coffee', function() {
return gulp.src('./src/coffee/**/*.coffee')
.pipe(plumber())
.pipe(coffee())
.pipe(uglify())
.pipe(gulp.dest('./dist'))
.pipe(browserSync.stream());
});
gulp.task('serve', function() {
browserSync.init({
proxy: 'http://mamp-site.dev'
});
gulp.watch('./src/scss/**/*.scss', ['sass']);
gulp.watch('./src/coffee/**/*.coffee', ['coffee']);
});
Browsersync successfully reloads my compiled JS every time I make a change, but won't reload my compiled CSS. I know placing browserSync.stream() after gulp.dest() is correct, because Browsersync says it only cares about your CSS when it's finished compiling. I also verified that my Sass is compiling.
Why would Browsersync work for my 'coffee' task but not my 'sass' task? This is my first go at gulp, so I'm hoping it's something simple.
EDIT: watching 'sass' only within the 'serve' task works, but not with both 'sass' and 'coffee'
I don't know why your sass is not reloading, but you should not be using browserSync.stream for your javascript. Perhaps the streams are getting mixed up. Your watch should be
gulp.watch('./src/coffee/**/*.coffee', ['coffee-watch']);
and there should be
gulp.task('coffee-watch', ['coffee'], function (done) {
browserSync.reload();
done();
});
Remove .pipe(browserSync.stream()); from your coffee task.
I'm attempting to use browser-sync with Gulp 4, but bs is not preserving state, and instead does a full refresh. This is not very useful. It seems bs no longer supports true injection. I filed an issue on GH if you want to contribute.
Here is the pertinent code:
// styles:dev task
gulp.task('styles:dev', function() {
return gulp.src(config.src)
.pipe(sourcemaps.init())
.pipe(postcss(config.postcss.dev))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(config.dest.dev))
.pipe(browserSync.stream());
});
// browserSync task
gulp.task('browserSync', function(cb) {
browserSync.init(config, cb);
});
// Watch task:
gulp.task('watch:styles', function() {
return gulp.watch(config.paths.css,
gulp.series('styles:dev'));
});
gulp.task('watch', gulp.parallel('watch:styles'));
// default task
gulp.task('default',
gulp.series('clean:dev',
gulp.parallel('copy:dev', 'styles:dev'), 'browserSync', 'watch')
);
Thanks in advance.
Fixed. Here's where I went wrong:
The browser-sync constructor takes an options object, which can include a files array. Most of the tutorials I've read, including the gulpfile for Google's very own Web Starter Kit, do not include this. As it turns out, this is required for style injection to preserve state.
Furthermore, do not pass .stream() or .reload() as the final pipe in your styles task. It is not needed, and will short circuit style injection, forcing a full refresh.
Finally, the browserSync process must not be terminated, and watch and browserSync tasks must execute in parallel in order for live style injection to take place.
Hope this helps anybody facing this issue.
I also closed the corresponding github issue, and posted my gulpfile
Almost 3 years later Gulp 4 now looks a little bit different, see https://gulpjs.com/docs/en/getting-started/creating-tasks
To have a complete Gulp 4 kickstart example, see https://gist.github.com/leymannx/8f6a75e8ad5055276a71d2901813726e
// Requires Gulp v4.
// $ npm uninstall --global gulp gulp-cli
// $ rm /usr/local/share/man/man1/gulp.1
// $ npm install --global gulp-cli
// $ npm install
const { src, dest, watch, series, parallel } = require('gulp');
const browsersync = require('browser-sync').create();
const sass = require('gulp-sass');
const autoprefixer = require('gulp-autoprefixer');
const sourcemaps = require('gulp-sourcemaps');
const plumber = require('gulp-plumber');
const sasslint = require('gulp-sass-lint');
const cache = require('gulp-cached');
// Compile CSS from Sass.
function buildStyles() {
return src('scss/ix_experience.scss')
.pipe(plumber()) // Global error listener.
.pipe(sourcemaps.init())
.pipe(sass({ outputStyle: 'compressed' }))
.pipe(autoprefixer(['last 15 versions', '> 1%', 'ie 8', 'ie 7']))
.pipe(sourcemaps.write())
.pipe(dest('css/'))
.pipe(browsersync.reload({ stream: true }));
}
// Watch changes on all *.scss files, lint them and
// trigger buildStyles() at the end.
function watchFiles() {
watch(
['scss/*.scss', 'scss/**/*.scss'],
{ events: 'all', ignoreInitial: false },
series(sassLint, buildStyles)
);
}
// Init BrowserSync.
function browserSync(done) {
browsersync.init({
proxy: 'blog.localhost', // Change this value to match your local URL.
socket: {
domain: 'localhost:3000'
}
});
done();
}
// Init Sass linter.
function sassLint() {
return src(['scss/*.scss', 'scss/**/*.scss'])
.pipe(cache('sasslint'))
.pipe(sasslint({
configFile: '.sass-lint.yml'
}))
.pipe(sasslint.format())
.pipe(sasslint.failOnError());
}
// Export commands.
exports.default = parallel(browserSync, watchFiles); // $ gulp
exports.sass = buildStyles; // $ gulp sass
exports.watch = watchFiles; // $ gulp watch
exports.build = series(buildStyles); // $ gulp build
Goal
I'm updating my old gulpfile.js, which used to be mainly for compiling my Sass into CSS, but now I'm trying to get Gulp to do the following:
Sync browser, whip up localhost server - DONE
Compile Sass => CSS - DONE
Show any JavaScript errors with JSHint - DONE
Compile ES6 => ES6 with Babel (WORKING ON)
Minify all assets (WORKING ON)
Show project file size - DONE
Deploy index.html, style.css and images to S3 (WORKING ON)
Watch files, reload browser when .scss or .html changes - DONE
Problem
Trying to minify my Javascript and also create a scripts.min.js
file, it keeps adding the suffix min to every new minified JavaScript
file.
Folder structure
index.html
gulpfile.js
package.json
.aws.json
.csscomb.json
.gitignore
assets
- css
style.css
style.scss
--partials
---base
---components
---modules
- img
- js
scripts.js
- dist
gulpfile.js
// Include Gulp
var gulp = require('gulp');
var postcss = require("gulp-postcss");
// All of your plugins
var autoprefixer = require('autoprefixer');
var browserSync = require('browser-sync');
var cache = require('gulp-cache');
var concat = require('gulp-concat');
var csswring = require("csswring");
var imagemin = require('gulp-imagemin');
var jshint = require('gulp-jshint');
var lost = require("lost");
var plumber = require('gulp-plumber');
var rename = require('gulp-rename');
var rucksack = require("rucksack-css");
var sass = require('gulp-sass');
var uglify = require('gulp-uglify');
// Sync browser, whip up server
gulp.task('browser-sync', function() {
browserSync({
server: {
baseDir: "./"
}
});
});
// Reload page automagically
gulp.task('bs-reload', function () {
browserSync.reload();
});
// Compile Sass into CSS, apply postprocessors
gulp.task('styles', function(){
var processors = [
autoprefixer({browsers: ['last 2 version']}),
csswring,
lost,
rucksack
];
gulp.src(['assets/css/**/*.scss'])
.pipe(plumber({
errorHandler: function (error) {
console.log(error.message);
this.emit('end');
}}))
.pipe(sass())
.pipe(postcss(processors))
// .pipe(gulp.dest('assets/css/'))
// .pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('assets/css/'))
.pipe(browserSync.reload({stream:true}))
});
// Show any JavaScript errors
gulp.task('scripts', function(){
return gulp.src('assets/js/**/*.js')
.pipe(plumber({
errorHandler: function (error) {
console.log(error.message);
this.emit('end');
}}))
.pipe(jshint())
.pipe(jshint.reporter('default'))
// .pipe(concat('main.js'))
// .pipe(babel())
.pipe(gulp.dest('assets/js/'))
.pipe(uglify())
.pipe(gulp.dest('assets/js/'))
.pipe(rename({suffix: '.min'}))
.pipe(browserSync.reload({stream:true}))
});
// Minify assets, create build folder
gulp.task('images', function(){
gulp.src('assets/img/**/*')
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest('assets/img'));
});
// Minify HTML
// Default task
gulp.task('default', ['browser-sync'], function(){
gulp.watch("assets/css/**/*.scss", ['styles']);
gulp.watch("assets/js/**/*.js", ['scripts']);
gulp.watch("*.html", ['bs-reload']);
gulp.start("images", "styles", "scripts")
});
// var babel = require('gulp-babel');
// var minifyhtml = require("gulp-minify-html");
// var size = require("gulp-size");
// var upload = require("gulp-s3");
Hi i can't solve all your problems but I had also a similar issue with the babel and ES6 fat arrow functions (using babelify and browserify). To solve the problem try to pass:
stage: 0
to your babel.js gulp plugin. If error will still occurs then try to pass also:
experimental: true
For more information please have a look "experimental" section on babel.js site.