【问题标题】:Cache busting in gulp only working with index.html changes, not css or js changesgulp 中的缓存破坏仅适用于 index.html 更改,而不适用于 css 或 js 更改
【发布时间】:2020-02-27 11:49:19
【问题描述】:

我的浏览器缓存有问题,所以如果 css、js 或 html 文件发生更改,我会尝试更新 index.html 文件。

我要更新的行是:

<link rel="stylesheet" href="styles/main.css?cb=123" />

更重要的是 ?cb=123 部分

基本上,我的 gulp 函数会查找 'cb=' 并根据日期和时间使用新数字对其进行更新。

如果我使用下面的 gulpfile.js,这个 index.html 会更新得很好。对 index.html 文件的任何更改都会产生一个新的 cb 编号。

// --------------------------------------------
// Gulp Loader
// --------------------------------------------

const {
    src,
    dest,
    task,
    watch,
    series,
    parallel
  } = require("gulp");

  // --------------------------------------------
  // Dependencies
  // --------------------------------------------

  const homedir = require("os").homedir();
  var path = require("path");
  var pathDir = require("path").resolve(__dirname, "../../");
  var parentDir = path
    .dirname(pathDir)
    .split(path.sep)
    .pop();

  var newParent = parentDir.split(" ").join("_");

  var parentdir = path.basename(path.dirname(pathDir));
  parentdir = parentDir.replace(/[^\w]/g, "");
  parentdir = parentDir.replace(/[^\w]/g, "").toLowerCase();

  // HTML plugins
  let htmlmin = require("gulp-htmlmin");

  // CSS / SASS plugins
  let sass = require("gulp-sass");
  let autoprefixer = require("autoprefixer");
  let minifycss = require("gulp-clean-css");
  let postcss = require("gulp-postcss");
  let cssnano = require("cssnano");

  // JSS / plugins
  let uglify = require("gulp-uglify");

  // Utility plugins
  let concat = require("gulp-concat");
  let del = require("del");
  let plumber = require("gulp-plumber");
  let sourcemaps = require("gulp-sourcemaps");
  let rename = require("gulp-rename");
  let fileinclude = require("gulp-file-include");
  var replace = require('gulp-replace');

  // Browser plugins
  let browserSync = require("browser-sync").create();

  // Images plugins
  let imagemin = require("gulp-imagemin");
  let embedSvg = require("gulp-embed-svg");

  // --------------------------------------------
  // Project Variables
  // --------------------------------------------

  let htmlSrc = "source/";
  let htmlDest = homedir + "/sites/blog/";

  let incSrc = "source/includes/";

  let styleSrc = "source/styles/";
  let styleDest = homedir + "/sites/blog/styles/";

  let vendorSrc = "source/scripts/vendors/";
  let scriptSrc = "source/scripts/";
  let scriptDest = homedir + "/sites/blog/scripts/";

  let imageSrc = "source/images/";
  let imageDest = homedir + "/sites/blog/images/";

  let fontSrc = "source/fonts/";
  let fontDest = homedir + "/sites/blog/fonts/";

  // --------------------------------------------
  // Tasks
  // --------------------------------------------

  // CSS
  function css(done) {
    src([
      styleSrc + 'main.scss',
    ])

      .pipe(sass({
        outputStyle: 'compressed'
      }))
      .pipe(plumber())
      .pipe(dest(styleDest));
    done();
  };

  // JS
  function js(done) {
    src([scriptSrc + "*.js", vendorSrc + "*.js"])
      .pipe(
        rename({
          basename: "main",
          suffix: ".min"
        })
      )
      .pipe(plumber())
      .pipe(uglify())
      .pipe(dest(scriptDest));
    done();
  }

  // HTML
  function html(done) {
    var cbString = new Date().getTime();
    src(htmlSrc + "index.html")
      .pipe(
        fileinclude({
          prefix: "@@",
          basepath: "source/includes"
        })
      )
      .pipe(replace(/cb=\d+/, 'cb=' + cbString))
      .pipe(
        embedSvg({
          root: "./source/images/",
          selectors: ".inline-svg"
        })
      )
      .pipe(
        htmlmin({
          collapseWhitespace: true,
          minifyCSS: true,
          minifyJS: {
            compress: {
              drop_console: true
            }
          },
          processConditionalComments: true,
          removeComments: true,
          removeEmptyAttributes: true,
          removeScriptTypeAttributes: true,
          removeStyleLinkTypeAttributes: true,
          processScripts: ["application/ld+json"]
        })
      )
      .pipe(dest(htmlDest));
    done();
  }

  // IMAGES
  function img(done) {
    src(imageSrc + "*")
      .pipe(imagemin())
      .pipe(dest(imageDest));
    done();
  }

  // FONTS
  function fonts(done) {
    src(fontSrc + "*").pipe(dest(fontDest));
    done();
  }

  // --------------------------------------------
  // Watch for changes
  // --------------------------------------------

  function watcher() {
    // Serve files from the root of this project
    browserSync.init({
      server: {
        baseDir: homedir + "/sites/blog/",
      },
      notify: false
    });

    watch(htmlSrc, series(html)).on("change", browserSync.reload);
    watch(styleSrc, series(css)).on("change", browserSync.reload);
    watch(scriptSrc, series(js)).on("change", browserSync.reload);
    watch(imageSrc, series(img)).on("change", browserSync.reload);
    watch(imageSrc, series(fonts)).on("change", browserSync.reload);
  }

  // use default task to launch Browsersync and watch JS files
  var build = parallel(css, js, html, img, fonts, watcher);
  task("default", build);

但是这个数字只有在 index.html 文件被改变后才会更新,所以回到绘图板..

现在,如果我更新 js 或 css 文件,我希望更新数字,我尝试从 html 函数中取出以下行并赋予其功能:

.pipe(replace(/cb=\d+/, 'cb=' + cbString))

像这样:

// Cachebust
function cacheBustTask(done) {
  var cbString = new Date().getTime();
  src(htmlSrc + "index.html")
    .pipe(replace(/cb=\d+/g, 'cb=' + cbString))
    .pipe(dest(htmlDest));
  done();
}

但这会破坏网站。

任何想法我可以让任务 cacheBustTaskhtml 任务一起工作。

这是完整更新的 gulpfile.js,带有单独的 cacheBustTask 任务/函数

【问题讨论】:

    标签: caching npm gulp


    【解决方案1】:

    假设你有这个文件夹结构:

    src
      js
        index.js
      scss
        index.scss
    public
    about.html     << target this one
    index.html     << target this one
    

    并且您想仅将缓存清除添加到.js.css 文件

    转换说:

    <script src="dist/index.js?cb=0"></script>
    

    进入:

    <script src="dist/index.js?cb=1607437629110"></script>
    

    在你的 gulpfile.js

    中使用它
    function cacheBustTask(){
        return src(['index.html', 'about.html'])
            .pipe(replace(/(\.(css|js)\?cb=)\d+\b/g, `$1${Date.now()}`))
            .pipe(dest('.'));
    }
    

    如果您想定位所有.html 文件,请使用通配符**

    return src(["**/*.html"])
    

    补充说明:

    由于每次您进行一些更改时,您的管道都会触发此修改,您可能会遇到问题或推送到您实际上没有接触过的 Git 文件。
    因此,只有在为生产构建时,您才应该添加到您的管道以运行上述内容。

    所以基本上在开发模式下(在您的 src 文件夹内),您应该始终看到后缀 ?cb=0 - 并且只有时间戳后缀的 ?cb=1607437629110 在最终位于 dist 内的文件中 - 只有在您构建后您的生产项目。

    【讨论】:

    • 这不起作用(无论如何对我来说)。我的情况非常相似,但我的问题是 js 和 css 文件有 cb=####### 任何数字,但在我的 html 中,###### 不匹配。这让我发疯了。
    • @e11world 您的.html 文件在哪里?如果您查看上面的示例 - 如果您的 .html 文件位于根文件夹中,则特定代码将起作用。此外,您最初应该有一个数字(定义的任何数字,即:&lt;script src="dist/functions.js?cb=0"&gt;&lt;/script&gt;
    • @e11world 也许您可以使用通配符,例如:["**/*.html"] 来定位 any .html 文件
    • 我认为我没有将默认编号应用到我的链接中,所以可能就是这样。我确实尝试了通配符,但我将它限制在某些目录(src/**/*.html)。
    • @e11world 坦率地说我不明白你的评论,这是一个建议还是一个问题?
    【解决方案2】:

    有些插件可以做到这一点,而不是制作自己的缓存清除系统。我用 gulp-version-number.

    const addVersionString = require("gulp-version-number");
    
    
    const versionConfig = {
      "value": "%DT%",
      "append": {
        "key": "v",
        "to": ["css", "js"],
      },
    };
    
    function processHTML() {
      return gulp.src(paths.html.src)
        .pipe(print())
    
        // modifyHTMLlinks: remove browserSync script link
        // update css/js links to .min.css or .min.js
        .pipe(modifyHTMLlinks())
    
        .pipe(stripComments.html(stripOptions))
    
        // add ?v=dateTime stamp to css and js links
        .pipe(addVersionString(versionConfig))
    
        .pipe(gulp.dest(paths.html.deploy));
    }
     
    

    你会结束

      <link rel="stylesheet" href="css/styles.min.css?v=20201206182221">
      <script src="js/app.min.js?v=20201206182221"></script>
    
    

    我也不将它用于html 文件,因此您必须修改配置才能添加它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多