I'm implementing a build using Gulp
, Browsersync
, Sass
for CSS and Pug
for HTML. I'm also injecting stylesheets <link>
s into HTML after the styles and markup are compiled.
Initial build works fine, but I'm having a problem to implement watching for changes in CSS and HTML files using Gulp. What happens now is on changing any source file (markup or stylesheets), when Browsersync reloads the browser, I'm left with an unstyled page, which has no stylesheets injected into it's <head>
. It seems that Browsersync reload fires after pug
(Pug to HTML compilation) has been done, but before sass
(Sass to CSS compilation) finishes and so there is nothing to inject then.
Main question: Please tell me how to force the right order in Gulp.
Extra question: How to do it in a way that would do full page reload when the markup changes, but not do full page reload on stylesheet changes, instead only inject CSS into <head>
as described in this article and Gulp docs under "SASS + CSS Injecting".
This is my code:
gulpfile.babel.js
import gulp from "gulp";
// Gulpfile is split across multiple files located in .gulp/.
// Importing them executes them and registers appropriate tasks.
import "./gulp/browser-sync.js";
import "./gulp/inject.js";
import "./gulp/markup.js";
import "./gulp/styles.js";
import "./gulp/watch.js";
// Build all the source files.
gulp.task("build", ["markup", "styles"]);
// Default task ran when `gulp` executed with no arguments.
gulp.task("default", ["build", "browser-sync"]);
gulp/browser-sync.js
import gulp from "gulp";
import browserSync from "browser-sync";
import paths from "./paths.js";
// Running a local server, which posts live updates to connected browsers when
// any of the source files change.
gulp.task("browser-sync", ["build", "watch"], () => {
browserSync.init({
server: {
baseDir: paths.global.tmp
}
});
});
gulp/styles.js
import gulp from "gulp";
import sass from "gulp-sass";
import sassModuleImporter from "sass-module-importer";
import sourcemaps from "gulp-sourcemaps";
import browserSync from "browser-sync";
import del from "del";
import paths from "./paths.js";
gulp.task("styles", ["clean:styles", "sass", "inject"]);
// Compiles Sass stylesheets to CSS.
gulp.task("sass", ["clean:styles"], () => {
const SASS_OPTIONS = {
includePaths: paths.styles.src,
importer: sassModuleImporter()
};
return gulp.src(paths.styles.srcMainGlob, { base: paths.styles.src })
.pipe(sourcemaps.init())
.pipe(sass(SASS_OPTIONS))
.pipe(sourcemaps.write(paths.styles.maps))
.pipe(gulp.dest(paths.styles.tmp))
.pipe(browserSync.stream({ match: "**/*.css" }));
});
gulp.task("clean:styles", () => {
let pathsToDel = [paths.styles.tmp, paths.styles.dist];
return del(pathsToDel);
});
gulp.task("watch:styles", ["styles"], () => {
gulp.watch(paths.styles.srcAllGlob, ["styles"]);
});
gulp/markup.js
import gulp from "gulp";
import pug from "gulp-pug";
import browserSync from "browser-sync";
import del from "del";
import paths from "./paths.js";
gulp.task("markup", ["clean:markup", "pug", "inject"]);
// Compile Pug templates to HTML
gulp.task("pug", ["clean:markup"], () => {
return gulp.src(paths.markup.srcMainGlob)
.pipe(pug())
.pipe(gulp.dest(paths.markup.tmp))
.pipe(browserSync.stream());
});
gulp.task("clean:markup", () => {
let pathsToDel = [paths.markup.tmp, paths.markup.dist];
return del(pathsToDel);
});
gulp.task("watch:markup", ["markup"], () => {
gulp.watch(paths.markup.srcAllGlob, ["markup"]);
});
gulp/inject.js
import gulp from "gulp";
import inject from "gulp-inject";
import paths from "./paths.js";
gulp.task("inject", ["inject:styles"]);
// Inject generated stylesheets into HTML files.
gulp.task("inject:styles", ["pug", "sass"], () => {
let sources = gulp.src(paths.styles.tmpGlob, { read: false });
return gulp.src(paths.markup.tmpGlob)
.pipe(inject(sources, { relative: true }))
.pipe(gulp.dest(paths.markup.tmp));
});
gulp/watch.js
import gulp from "gulp";
// Watching for all the changes in source files.
gulp.task("watch", ["watch:markup", "watch:styles"]);
And here is output of the console after running gulp
and making a change to one of the source Sass files:
[BS] Access URLs:
--------------------------------------
Local: http://localhost:3000
External: http://192.168.88.32:3000
--------------------------------------
UI: http://localhost:3001
UI External: http://192.168.88.32:3001
--------------------------------------
[BS] Serving files from: .tmp/
[12:00:30] Starting 'clean:styles'...
[12:00:30] Starting 'clean:markup'...
[12:00:30] Finished 'clean:markup' after 3.12 ms
[12:00:30] Starting 'pug'...
[12:00:30] Finished 'clean:styles' after 8.61 ms
[12:00:30] Starting 'sass'...
[BS] Reloading Browsers...
[BS] 1 file changed (index.html)
[12:00:30] Finished 'pug' after 72 ms
[BS] 1 file changed (main.css)
[12:00:30] Finished 'sass' after 144 ms
[12:00:30] Starting 'inject:styles'...
[12:00:30] gulp-inject 1 files into index.html.
[12:00:30] Finished 'inject:styles' after 9.67 ms
[12:00:30] Starting 'inject'...
[12:00:30] Finished 'inject' after 2.99 μs
[12:00:30] Starting 'styles'...
[12:00:30] Finished 'styles' after 2.47 μs
The first thing to do is to add browserSync
to your inject:styles
task, otherwise it won't reload after the style links have been injected
// Inject generated stylesheets into HTML files.
gulp.task("inject:styles", ["pug", "sass"], () => {
let sources = gulp.src(paths.styles.tmpGlob, { read: false });
return gulp.src(paths.markup.tmpGlob)
.pipe(inject(sources, { relative: true }))
.pipe(gulp.dest(paths.markup.tmp))
.pipe(browserSync.stream());
});