There is the following gulpfile.js
const { watch, src, dest, parallel, series } = require('gulp')
const uglify = require('gulp-uglify')
const browserSync = require('browser-sync').create()
const htmlMin = require('gulp-htmlmin')
const cleanCSS = require('gulp-clean-css')
const imagemin = require('gulp-imagemin')
const hash = require('gulp-hash') // !!!
const references = require('gulp-hash-references') // !!!
const del = require('del')
const path = require('path')
const manifestFile = 'asset-manifest.json'
const buildDir = './build'
function serve() {
browserSync.init({
server: {
baseDir: "./"
}
})
watch("./*.html").on('change', browserSync.reload)
watch("./css/**/*.css").on('change', browserSync.reload)
watch("./**/*.js").on('change', browserSync.reload)
}
function buildHTML(cb) {
src('index.html')
.pipe(references(manifestFile)) // replace file paths in index.html according to the manifest
.pipe(htmlMin({
collapseWhitespace: true
}))
.pipe(dest(buildDir))
cb()
}
function buildCSS(cb) {
src('./css/**/*.css')
.pipe(cleanCSS())
.pipe(hash())
.pipe(dest(path.join(buildDir, 'css')))
.pipe(hash.manifest(manifestFile)) // generate a manifest file
.pipe(dest('.'))
cb()
}
function buildJS(cb) {
src(['./**/*.js', '!./node_modules/**', '!./gulpfile.js'])
.pipe(uglify())
.pipe(hash())
.pipe(dest('build/'))
.pipe(hash.manifest(manifestFile)) // generate a manifest file
.pipe(dest('.'))
cb()
}
function buildImages(cb) {
src('./img/**/*.png')
.pipe(imagemin([
imagemin.optipng({ optimizationLevel: 7 })
]))
.pipe(dest(path.join(buildDir, 'img')))
cb()
}
exports.build = series(buildJS, buildCSS, buildHTML) // !!!
exports.default = serve
I'm trying to hash *.css and *.js file names and replace their old names with hashed ones in the build/index.html file. But the problem is that the function "buildHTML" starts working earlier than the "asset-manifest.json" file created. What am I doing wrong?
You have to return
the streams created by your functions to ensure that they run in the expected order and to catch any possible errors. No need to use a callback:
function buildHTML() {
return src('index.html')
.pipe(references(manifestFile)) // replace file paths in index.html according to the manifest
.pipe(htmlMin({
collapseWhitespace: true
}))
.pipe(dest(buildDir));
}
function buildCSS() {
return src('./css/**/*.css')
.pipe(cleanCSS())
.pipe(hash())
.pipe(dest(path.join(buildDir, 'css')))
.pipe(hash.manifest(manifestFile)) // generate a manifest file
.pipe(dest('.'));
}
function buildJS() {
return src(['./**/*.js', '!./node_modules/**', '!./gulpfile.js'])
.pipe(uglify())
.pipe(hash())
.pipe(dest('build/'))
.pipe(hash.manifest(manifestFile)) // generate a manifest file
.pipe(dest('.'));
}
function buildImages() {
return src('./img/**/*.png')
.pipe(imagemin([
imagemin.optipng({ optimizationLevel: 7 })
]))
.pipe(dest(path.join(buildDir, 'img')));
}