SASS + CSS Injecting with Gulp and BrowserSync - javascript

Just getting started with BrowserSync and I have a question regarding the common use-cases on configuration for SASS + CSS injecting.
What I'm a little confused about is weather I can give the server property its own name.
In the docs here they use "./app". Can I use another name like "./site" or am I only allowed to use "./app"?
Here's the code
// task
gulp.task('serve',['sass'], function (){
// static server
browserSync.init({
server: "./app"
});
// watching html and scss files for changes then reloading browser
gulp.watch("app/scss/*.scss", ['sass']);
gulp.watch("app/*.html").on('change', browserSync.reload);
});

UPDATED
If you're looking to set up browserSync as a static server with live reloading you're pretty much right with your approach. You can point browsersync to any folder in your repository using the baseDir option. You can also use multiple directories. For further info check out the options documentation.
First. I would look to split up the tasks you have.
Personally, I would opt to have my server task something like;
gulp.task('serve', ['build'], function(event) {
var server = browsersync.create();
server.init({
baseDir: 'app/'
});
return server.watch('app/**', function(evt, file) {
server.reload();
});
});
Note how build is a dependency. This ensures that all of our served files are in place when we initiate BrowserSync.
Keeping it generic we can then split the SCSS related tasks into their own tasks such as scss:compile and scss:watch.
gulp.task('scss:compile', function(){
return gulp.src('src/scss/**/*.scss')
.pipe(plumber())
.pipe(scss())
.pipe(gulp.dest('app/css/');
});
and
gulp.task('scss:watch', function() {
gulp.watch('src/scss/**/*.scss', ['scss:compile']);
});
For CSS injection. There are two options for doing this
Remember injection differs from reload. Whereas reload will reset the page state, injection won't affect the current page state and justs injects the styles.
Option one is to invoke browsersync.stream() with the piped content of your SASS compilation like follows;
gulp.task('scss:compile', function() {
return gulp.src('src/scss/**/*.scss')
.pipe(plumber())
.pipe(scss())
.pipe(gulp.dest('app/css')
.pipe(browsersync.stream());
});
Note that the last pipe injects the changes. This also requires to check the file type in the BrowserSync watch to only reload when a non CSS file changes.
This option is OK. However, I think it's not clear to have it just bundled on the end there and separate from BrowserSync setup code.
The second option(personally preferred) is to watch for changes with BrowserSync and if a CSS file changes, use vinyl to stream those changes to BrowserSync.
Something like the following tends to work;
var gulp = require('gulp'),
browsersync = require('browser-sync'),
vss = require('vinyl-source-stream'),
vb = require('vinyl-buffer'),
vf = require('vinyl-file');
gulp.task('serve', ['build'], function() {
var server = browsersync.create();
server.init({ baseDir: 'app/' });
return server.watch('app/**', function(evt, file) {
if (evt === 'change' && file.indexOf('.css') === -1)
server.reload();
if (evt === 'change' && file.indexOf('.css') !== -1)
vf.readSync(file)
.pipe(vss(file))
.pipe(vb())
.pipe(server.stream());
});
});
Hope that helps you out!

Related

How do I make a min file in the same path or dest on gulp-rename and gulp-uglify?

Hi everyone I hope you having a great day, I'm trying to find a way on how do I make a min file in the same path or gulp.dest() on gulp(gulp-uglify and gulp-rename). In my code below when I run my gulp it keeps on creating *.min.js , *.min.min.js , *.min.min.min.js so on and so forth unless I stop the terminal. How do I make my gulp create only one *.min.js at the same time it uglify's. I hope everyone can help me with this one. Thank You.
const gulp = require('gulp');
const browserSync = require('browser-sync').create();
const rename = require('gulp-rename');
const uglify = require('gulp-uglify');
gulp.task('scripts', function() {
return gulp.src('./src/js/*.js')
.pipe(uglify())
.pipe(rename( {suffix: '.min'} ))
.pipe(gulp.dest('./src/js/'))
.pipe(browserSync.stream());
});
gulp.task('browserSync', function(){
browserSync.init({
server : {
baseDir : './'
}
});
gulp.watch('./src/js/**.js', gulp.series('scripts'));
});
gulp.task('default', gulp.series('scripts', 'browserSync'));
This is happening because your scripts task is outputting the files to the same directory as you are watching:
.pipe(gulp.dest('./src/js/'))
and
gulp.watch('./src/js/**.js', gulp.series('scripts'));
So every time scripts runs and saves to that directory it triggers your watch again which fires scripts, etc., etc.
So either save your .min's to a directory you are not watching or don't watch .min files.
BTW, change to gulp.watch('./src/js/*.js', gulp.series('scripts')); // removed one asterisk
gulp.watch(['./src/js/*.js', '!./src/js/*.min.js'], gulp.series('scripts')); //
might work - untested though.

gulp.src from a separate file doesnt work

I am trying to write a gulpfile as follows :
var gulp = require('gulp');
// other dependencies go here ....
// source of files
var inputs = require('./asset_source.js');
// a simple task
gulp.task('css', function () {
gulp.src(inputs.css)
.pipe(debug())
.pipe(plumber())
.pipe(maps.init())
.pipe(concatCss('libs.css'))
.pipe(maps.write('../srcmaps'))
.pipe(plumber.stop())
.pipe(gulp.dest('assets/css'));
});
// the watcher
gulp.task('watch', function () {
gulp.watch('./asset_source.js', ['css']);
});
// default task
gulp.task('default', ['browser-sync', 'watch']);
And the source of assets (asset_source.js) file is something like this :
module.exports = {
css: [
'path/to/a/file.css',
'path/to/another/file.css',
.......
.......
],
js: [
'path/to/a/file.js',
'path/to/another/file.js',
.......
.......
]
};
Now I run the app with by just typing gulp in the console and it starts in a browser thanks to browsersync. I have all the css,scss,js assets listed in the asset_source.js file which is in the same directory as the gulpfile.js. What I want to achieve is if I append or remove a value to/from either of the arrays in asset_source.js, the concerned task should run while the gulp is already running. In this case css should be running on any change to asset_source.js with its updated content.
But instead it doesnt do so. Even if there is a change in the asset_source file, gulp uses the initial content and runs the task. However if run gulp css in a separate terminal, it works.
Please help me where I am going wrong or if it is even possible. Thanks.

Browsersnyc not auto reloading on changes made to css

Got Browsersync to work with my Gulp file but I've really been struggling with getting browsersync to auto reload my static site when I make changes to the main.scss file. I've followed all the documentation on there webpage thoroughly and I still cant get page to auto refresh.
I know parts of my integration with gulp are working because when I run my default gulp task which is linked to the browser-sync task a browser window fires up with the server but when I make s simple change to my main.scss file nothing auto reloads. I have to manually refresh to see changes.
Here's my gulpfile..What am I missing in here?
// refferance gulp
var gulp = require('gulp');
// browser-sync
var browserSync = require('browser-sync');
var reload = browserSync.reload;
// other packages installed
var concat = require('gulp-concat');
var cssmin = require('gulp-minify-css');
var rename = require('gulp-rename');
var scss = require('gulp-sass');
var uglify = require('gulp-uglify');
// browser-sync task
gulp.task('browser-sync',['styles'] , function(){
browserSync.init({
server:'./'
});
gulp.watch('.//src/scss/*.scss',['styles']);
gulp.watch('.//*.html').on('change',browserSync.reload);
});
// scripts task
gulp.task('scripts', function(){
// fetch all files in the .js extension in the /src/js directory
return gulp.src('./src/js/*.js')
// concatenate files and save as app.js
.pipe(concat('app.js'))
// save app.js in dest directory
.pipe(gulp.dest('./dest/js/'))
.pipe(uglify())
// minfiy file and rename to app.min.js
.pipe(rename({
suffix: '.min'
}))
// save in dest directory
.pipe(gulp.dest('./dest/js'));
});
// styles task
gulp.task('styles', function(){
// fetch all files with scss extension in /src/scss directory
return gulp.src('./src/scss/*.scss')
// compile scss
.pipe(scss())
// output css in css dest directory
.pipe(gulp.dest('./dest/css/'))
// minify css
.pipe(cssmin())
// rename as styles.min.css
.pipe(rename({
suffix: '.min'
}))
// save in same directory
.pipe(gulp.dest('./dest/css'))
// reload browser by injecting css into browser via browsersync
// .pipe(reload({stream:true}));
.pipe(browserSync.stream());
});
gulp.watch('./src/js/*.js', ['scripts']);
// we use the watch task in the default task bellow
gulp.task('watch',function(){
// watch js
gulp.watch('./src/js/*.js',['scripts']);
// watch scss
gulp.watch('./src/scss/*.scss',['styles']);
});
// default task allows us to run all tasks at once by just running `gulp` in command line
gulp.task('default', ['scripts', 'styles', 'browser-sync', 'watch']);
If you take out
gulp.watch('.//src/scss/*.scss',['styles']);
gulp.watch('.//*.html').on('change',browserSync.reload);
and replace with
gulp.watch('dest/**/*.html').on('change', browserSync.reload);
you should see changes providing that you are looking at a HTML file located under the dest directory.
I would also check that your styles and scripts tasks are firing. You should see this in the terminal/cli. If they are firing, any reload will also be logged too.
Hope that helps you out!

Very slow BrowserSync server startup with Gulp

I'm using BrowserSync in server mode (using its built-in static server) with GulpJS on a local project, and everything seems to be working correctly except that the BrowserSync server is very slow to startup. BrowserSync itself seems to initialize right away when I run Gulp, but it takes about 4 to 5 minutes (and occasionally more) for the server to start and for it to return the access URLs. During this period, everything continues to run and BrowserSync responds to reload() calls and such, but access is not available via the usual URLs (in this case, localhost:3000 and localhost:3001). Once the access URLs are returned, the server has seemingly started and BrowserSync's page refreshes work fine and are actually very speedy.
I have tried several different configurations of my gulpfile.js, trying different ways to initialize BrowserSync, different approaches to calling the stream() and reload() methods (including trying BrowserSync's basic Gulp/SASS "recipe"), and different port numbers, but all configurations had the same problem. I even tried disabling my firewall and AV software (Avast), but nothing.
I'm running Windows 8.1, if that's relevant. BrowserSync is freshly installed locally to the project via NPM, and fresh local installs to other directories have the same problem. NPM, Ruby, Gulp, and all modules seem to be up-to-date. For what it's worth, all of my other experience with Ruby, Gulp, and Node.js have been very smooth and problem-free.
I can't find any other posts mentioning this problem and am beginning to think this is normal behavior. Is this normal, and, if not, does anyone have any ideas of things to try? This delay is not the end of the world since the BrowserSync server does always start (eventually), but it's still a kink in my workflow that I'd rather fix than just deal with.
Finally, here is my gulpfile.js:
/* File: gulpfile.js */
var gulp = require('gulp'),
gutil = require('gulp-util');
jshint = require('gulp-jshint');
sass = require('gulp-sass');
concat = require('gulp-concat');
uglify = require('gulp-uglify');
sourcemaps = require('gulp-sourcemaps');
imagemin = require('gulp-imagemin');
browserSync = require('browser-sync').create();
gulp.task('default', ['watch'], browserSync.reload);
// JSHint
gulp.task('jshint', function() {
return gulp.src('src/js/**/*.js')
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'));
});
// Build JS
gulp.task('build-js', function() {
return gulp.src('src/js/**/*.js')
.pipe(sourcemaps.init())
.pipe(concat('main.js'))
//only uglify if gulp is ran with '--type production'
.pipe(gutil.env.type === 'production' ? uglify() : gutil.noop())
.pipe(sourcemaps.write())
.pipe(gulp.dest('public/www/js/core'));
});
// Build CSS
gulp.task('build-css', function() {
return gulp.src('src/sass/**/*.{sass,scss}')
.pipe(sourcemaps.init())
.pipe(sass()).on('error', handleError)
.pipe(sourcemaps.write()) // Add the map to modified source.
.pipe(gulp.dest('public/www/css/core'))
.pipe(browserSync.stream({match: '**/*.css'}));
});
// ImageMin
gulp.task('imagemin', function () {
return gulp.src('src/img/*')
.pipe(imagemin({
progressive: true,
svgoPlugins: [{removeViewBox: false}]
}))
.pipe(gulp.dest('public/www/img'));
});
// Handle errors
function handleError(err) {
console.log(err.toString());
this.emit('end');
}
// Watch function
gulp.task('watch', function() {
browserSync.init({
server: "./public/www",
//port: 3002
});
gulp.watch('src/js/**/*.js', ['jshint']);
gulp.watch('src/sass/**/*.{sass,scss}', ['build-css']);
gulp.watch('src/js/**/*.js', ['build-js']);
gulp.watch('src/img/*', ['imagemin']);
gulp.watch("public/www/css/**/*.css").on('change', browserSync.reload);
})
The BrowserSync Twitter account suggested that I set the "online" option to true, and...it seems to have worked!
I set it in BrowserSync's init like so:
browserSync.init({
server: "./public/www",
online: true
});
...and the delay is gone!
Going by the BrowserSync docs ( http://www.browsersync.io/docs/options/#option-online ), it seems that setting the online option to true skips the online check. So, I guess that check was somehow what was causing the delay? That seems odd to me, but it's working better now.
In my case I had this code in gulpfile which delay startup about 50 seconds
gulp.watch('./**/*.{js,html}').on('change', browserSync.reload);
and the problem was in the glob string. It inspects even node_modules folder. And I did some changes
gulp.watch(['./scripts/**/*.{js,html}', './index.html'])
.on('change', browserSync.reload);
I think that it is performance feature, that we should more exactly specify glob.

Gulp Fingerprinting + Production Deploys

I'm using gulp for common tasks on a front-end project. My goal is to fingerprint my JS+CSS assets and update my rev-manifest on deploy without interrupting anything. My tasks look something like this:
gulp.task("clean-js", function() {
return del(["./public/shop-assets/javascripts/production/*.js", "./rev-manifest.json"], function(){
console.log("Production JS folder and rev-manifest JSON cleared");
});
});
gulp.task("clean-css", function() {
return del(["./public/shop-assets/stylesheets/production/*.css", "./rev-manifest-css.json"], function(){
console.log("Production CSS folder and rev-manifest-css JSON cleared");
});
});
gulp.task('js:prod',['clean-js'], function() {
return gulp.src("./public/shop-assets/javascripts/*.js/")
.pipe(uglify())
.pipe(rev())
.pipe(gulp.dest("./public/shop-assets/javascripts/production/"))
.pipe(rev.manifest())
.pipe(gulp.dest("."));
});
gulp.task('css:minify',["clean-css"], function() {
return gulp.src("./public/shop-assets/stylesheets/*.css")
.pipe(minifyCss())
.pipe(rev())
.pipe(gulp.dest("./public/shop-assets/stylesheets/production/"))
.pipe(rev.manifest())
.pipe(rename("rev-manifest-css.json"))
.pipe(gulp.dest("."));
});
This does what I expect-it clears the manifest files each time, then rewrites them. What I would like to do is merely replace the contents of each manifest after I bundled + minified my JS +CSS files without blocking the user experience.
Also, in my express routes file, I am sending the manifest on down so I can then include the scripts/stylesheets like so:
script(src="/shop-assets/javascripts/production/#{assetPathJS}")
But when I delete and rewrite the manifest files, users will see an intermittent failure.
Does anyone have any tips on this matter? Most examples I have seen have only one entrypoint for the gulpfile. Thanks!
I wound up doing something like this in my routes files:
var jsPaths = ServerConfig.assetPaths(["cleanout.js", "hiw.js", "do_good.js"], revManifestJS, "javascripts/");
where that function assetPaths resolves the pathname based on the environment. Simple than I thought.

Categories