Cache and hard reload

I’m using Sage, but each time I change the CSS or Javascript, I have to hard reload the browser, the user don’t see my change, how can I prevent this situation?

You’ll avoid this when using the production build which will version all your assets and prevent caching issues :slight_smile:

Simply run npm run build:production or gulp --production (depending if you’re using sage 9 or 8)

1 Like

I’m using Sage 8, and this didn’t resolve my problem, the client still has an old version, js, CSS, images.
I’m doing gulp --production and deploy.
I was looking to gulp-rev:

But I didn’t have luck!
I’m trying those techniques:

EDIT: I surprised by this issue bc the production with gulp-rev create a new file based on the timestamp I imagine?
May the problem be from my server (Hostgator) and Apache?

What’s the result of the gulp --production process? You should find versioned files in your dist folder and a json manifest with the reference to those files. Those versioned files should also be pulled in the your php templates with the asset_path() helper. Have a look in the HTML of your website and see if the files are referenced correctly. Otherwise there might be something wrong in the way you’re adding them to WordPress

As @Nicolo_Sacchi said, Sage 8 will also add a unquie hash to your CSS and JS files with the production flag for cache busting purposes. You shouldn’t have to hard refresh or cache clear. Do you see the hashes at the end of your CSS and JS files in your site’s source?

the file is changed for each gulp --production:

here the page:

my assets json is correct and the site works well:

~/dist]# cat

  "customizer.js": "customizer-301757a02e.js",
  "jquery.js": "jquery-a7399e807a.js",
  "main.css": "main-02f2a01f3b.css",
  "main.js": "main-b08a0baf4f.js"

for each gulp --production, my hash in css doesn’t change, even after I added a class?
here my config.

// ## Globals
var argv         = require('minimist')(process.argv.slice(2));
var autoprefixer = require('gulp-autoprefixer');
var browserSync  = require('browser-sync').create();
var changed      = require('gulp-changed');
var concat       = require('gulp-concat');
var flatten      = require('gulp-flatten');
var gulp         = require('gulp');
var gulpif       = require('gulp-if');
var imagemin     = require('gulp-imagemin');
var jshint       = require('gulp-jshint');
var lazypipe     = require('lazypipe');
//var less         = require('gulp-less');
var merge        = require('merge-stream');
var cssNano      = require('gulp-cssnano');
var plumber      = require('gulp-plumber');
var rev          = require('gulp-rev');
var runSequence  = require('run-sequence');
var sass         = require('gulp-sass');
var sourcemaps   = require('gulp-sourcemaps');
var uglify       = require('gulp-uglify');

// See
var manifest = require('asset-builder')('./assets/manifest.json');

// `path` - Paths to base asset directories. With trailing slashes.
// - `path.source` - Path to the source files. Default: `assets/`
// - `path.dist` - Path to the build directory. Default: `dist/`
var path = manifest.paths;

// `config` - Store arbitrary configuration values here.
var config = manifest.config || {};

// `globs` - These ultimately end up in their respective `gulp.src`.
// - `globs.js` - Array of asset-builder JS dependency objects. Example:
//   ```
//   {type: 'js', name: 'main.js', globs: []}
//   ```
// - `globs.css` - Array of asset-builder CSS dependency objects. Example:
//   ```
//   {type: 'css', name: 'main.css', globs: []}
//   ```
// - `globs.fonts` - Array of font path globs.
// - `globs.images` - Array of image path globs.
// - `globs.bower` - Array of all the main Bower files.
var globs = manifest.globs;

// `project` - paths to first-party assets.
// - `project.js` - Array of first-party JS assets.
// - `project.css` - Array of first-party CSS assets.
var project = manifest.getProjectGlobs();

// CLI options
var enabled = {
  // Enable static asset revisioning when `--production`
  rev: argv.production,
  // Disable source maps when `--production`
  maps: !argv.production,
  // Fail styles task on error when `--production`
  failStyleTask: argv.production,
  // Fail due to JSHint warnings only when `--production`
  failJSHint: argv.production,
  // Strip debug statments from javascript when `--production`
  stripJSDebug: argv.production

// Path to the compiled assets manifest in the dist directory
var revManifest = path.dist + 'assets.json';

// Error checking; produce an error rather than crashing.
var onError = function(err) {

// ## Reusable Pipelines
// See

// ### CSS processing pipeline
// Example
// ```
// gulp.src(cssFiles)
//   .pipe(cssTasks('main.css')
//   .pipe(gulp.dest(path.dist + 'styles'))
// ```
var cssTasks = function(filename) {
  return lazypipe()
    .pipe(function() {
      return gulpif(!enabled.failStyleTask, plumber());
    .pipe(function() {
      return gulpif(enabled.maps, sourcemaps.init());
    //.pipe(function() {
      //return gulpif('*.less', less());
    .pipe(function() {
      return gulpif('*.scss', sass({
        outputStyle: 'nested', // libsass doesn't support expanded yet
        precision: 10,
        includePaths: ['.'],
        errLogToConsole: !enabled.failStyleTask
    .pipe(concat, filename)
    .pipe(autoprefixer, {
      browsers: [
        'last 2 versions',
        'android 4',
        'opera 12'
    .pipe(cssNano, {
      safe: true
    .pipe(function() {
      return gulpif(enabled.rev, rev());
    .pipe(function() {
      return gulpif(enabled.maps, sourcemaps.write('.', {
        sourceRoot: 'assets/styles/'

// ### JS processing pipeline
// Example
// ```
// gulp.src(jsFiles)
//   .pipe(jsTasks('main.js')
//   .pipe(gulp.dest(path.dist + 'scripts'))
// ```
var jsTasks = function(filename) {
  return lazypipe()
    .pipe(function() {
      return gulpif(enabled.maps, sourcemaps.init());
    .pipe(concat, filename)
    .pipe(uglify, {
      compress: {
        'drop_debugger': enabled.stripJSDebug
    .pipe(function() {
      return gulpif(enabled.rev, rev());
    .pipe(function() {
      return gulpif(enabled.maps, sourcemaps.write('.', {
        sourceRoot: 'assets/scripts/'

// ### Write to rev manifest
// If there are any revved files then write them to the rev manifest.
// See
var writeToManifest = function(directory) {
  return lazypipe()
    .pipe(gulp.dest, path.dist + directory)
    .pipe(, {match: '**/*.{js,css}'})
    .pipe(rev.manifest, revManifest, {
      base: path.dist,
      merge: true
    .pipe(gulp.dest, path.dist)();

// ## Gulp tasks
// Run `gulp -T` for a task summary

// ### Styles
// `gulp styles` - Compiles, combines, and optimizes Bower CSS and project CSS.
// By default this task will only log a warning if a precompiler error is
// raised. If the `--production` flag is set: this task will fail outright.
gulp.task('styles', ['wiredep'], function() {
  var merged = merge();
  manifest.forEachDependency('css', function(dep) {
    var cssTasksInstance = cssTasks(;
    if (!enabled.failStyleTask) {
      cssTasksInstance.on('error', function(err) {
    merged.add(gulp.src(dep.globs, {base: 'styles'})
      .pipe(plumber({errorHandler: onError}))
  return merged

// ### Scripts
// `gulp scripts` - Runs JSHint then compiles, combines, and optimizes Bower JS
// and project JS.
gulp.task('scripts', ['jshint'], function() {
  var merged = merge();
  manifest.forEachDependency('js', function(dep) {
      gulp.src(dep.globs, {base: 'scripts'})
        .pipe(plumber({errorHandler: onError}))
  return merged

// ### Fonts
// `gulp fonts` - Grabs all the fonts and outputs them in a flattened directory
// structure. See:
gulp.task('fonts', function() {
  return gulp.src(globs.fonts)
    .pipe(gulp.dest(path.dist + 'fonts'))

// ### Images
// `gulp images` - Run lossless compression on all the images.
gulp.task('images', function() {
  return gulp.src(globs.images)
      imagemin.jpegtran({progressive: true}),
      imagemin.gifsicle({interlaced: true}),
      imagemin.svgo({plugins: [{removeUnknownsAndDefaults: false}, {cleanupIDs: false}]})
    .pipe(gulp.dest(path.dist + 'images'))

// ### JSHint
// `gulp jshint` - Lints configuration JSON and project JS.
gulp.task('jshint', function() {
  return gulp.src([
    'bower.json', 'gulpfile.js'
    .pipe(gulpif(enabled.failJSHint, jshint.reporter('fail')));

// ### Clean
// `gulp clean` - Deletes the build folder entirely.
gulp.task('clean', require('del').bind(null, [path.dist]));

// ### Watch
// `gulp watch` - Use BrowserSync to proxy your dev server and synchronize code
// changes across devices. Specify the hostname of your dev server at
// `manifest.config.devUrl`. When a modification is made to an asset, run the
// build step for that asset and inject the changes into the page.
// See:
gulp.task('watch', function() {
    files: ['{lib,templates}/**/*.php', '*.php'],
    proxy: config.devUrl,
    snippetOptions: {
      whitelist: ['/wp-admin/admin-ajax.php'],
      blacklist: ['/wp-admin/**']
  });[path.source + 'styles/**/*'], ['styles']);[path.source + 'scripts/**/*'], ['jshint', 'scripts']);[path.source + 'fonts/**/*'], ['fonts']);[path.source + 'images/**/*'], ['images']);['bower.json', 'assets/manifest.json'], ['build']);

// ### Build
// `gulp build` - Run all the build tasks but don't clean up beforehand.
// Generally you should be running `gulp` instead of `gulp build`.
gulp.task('build', function(callback) {
              ['fonts', 'images'],

// ### Wiredep
// `gulp wiredep` - Automatically inject Less and Sass Bower dependencies. See
gulp.task('wiredep', function() {
  var wiredep = require('wiredep').stream;
  return gulp.src(project.css)
    .pipe(changed(path.source + 'styles', {
      hasChanged: changed.compareSha1Digest
    .pipe(gulp.dest(path.source + 'styles'));

// ### Gulp
// `gulp` - Run a complete build. To compile for production run `gulp --production`.
gulp.task('default', ['clean'], function() {

For each production the manifest.json doesn’t recreate a new hash.
I just notice this.

If the file hasn’t changed then this is good - no cache to bust if nothing has changed…

1 Like

I changed to
.test {
I didn’t ecpected any change…

You’re adding the selector but you don’t have a property or value set, so it’ll minify to nothing and make no change. Add a property and value and the hash will change.

As for the issue you’re seeing, check the error logs to see if file_get_contents is disabled on your host.