Gulp-rev-all создает новые файлы при каждом запуске

#javascript #ruby-on-rails #gulp

#javascript #ruby-on-rails #gulp

Вопрос:

У меня проблема gulp-rev-all . У меня есть следующий базовый файл gulp:

 var gulp = require('gulp'),
    RevAll = require('gulp-rev-all'),
    autoPrefixer = require('gulp-autoprefixer'),
    rename = require('gulp-rename'),
    sass = require('gulp-sass'),
    sourceMaps = require('gulp-sourcemaps');

gulp.task('sass', function () {
  var stream = gulp.src('./app/assets/stylesheets/application.scss')
    .pipe(sourceMaps.init())
    .pipe(sass({errLogToConsole: true}))
    .pipe(autoPrefixer())
    .pipe(rename("application.css"))
    .pipe(sourceMaps.write("."))
    .pipe(gulp.dest("./public/assets/stylesheets/"))
});

gulp.task('production', function() {
  gulp.src('./public/*assets/**')
    .pipe(RevAll.revision())
    .pipe(gulp.dest('./public'))
    .pipe(RevAll.versionFile())
    .pipe(gulp.dest('./app/assets'));
});

gulp.task('default', ['sass', 'production']);
  

Ожидание против реальности

Когда я запускаю gulp, он выдает следующую ошибку:

 Error: revision() must be called first!
  

Но когда я удаляю производственную задачу и выполняю следующее, задача sass завершается как обычно:

 gulp.task('default', ['sass']);
  

После того, как эта задача создаст файлы, изменение задачи по умолчанию обратно на включение рабочей задачи успешно завершится и создаст файл CSS с отпечатками пальцев.

Когда я снова запускаю gulp, он делает что-то странное:

  1. Первая задача gulp (без задачи proudction) создает:

    application.css (this task is idempotent)

  2. Затем я впервые запускаю задачу gulp с производством. Теперь папка выглядит так:

    application.css

    application.4434fcd5.css

  3. Затем я запускаю его снова, и теперь папка выглядит так:

    application.css

    application.4434fcd5.css

    application.4434fcd5.4434fcd5.css

Проблема

Я думаю, что обе проблемы связаны с тем, что что-то в производственной задаче создает какую-то проблему поиска. Что это?

Ответ №1:

(1) Ваша первая проблема заключается в этой строке:

 gulp.task('default', ['sass', 'production']);
  

Это не делает того, что вы думаете. Он не запускает sass задачу, а затем production задачу. Он выполняется одновременно.

Это означает, что ваша production задача попытается изменить файлы в вашей ./public/ папке еще до того, как ваша sass задача создаст там какие-либо файлы. Поскольку файлов нет, вы получаете сообщение об revision() must be called first! ошибке.

Вам нужно сообщить gulp, что ваша production задача зависит от вашей sass задачи:

 gulp.task('production', ['sass'], function() {
  

И затем вам нужно вернуть поток из вашей sass задачи, чтобы gulp знал, когда ваша sass задача завершена:

 gulp.task('sass', function () {
  var stream = gulp.src('./app/assets/stylesheets/application.scss')
  //...
  return stream;
});
  

(2) Ваша вторая проблема заключается в этой строке:

 gulp.src('./public/*assets/**')
  

Это не просто совпадает application.css , но и application.4434fcd5.css . Таким образом, ваши уже пересмотренные файлы пересматриваются снова.

Вы можете решить это по-разному, но проще всего, вероятно, просто удалять всю вашу ./public папку каждый раз, когда вы запускаете свою sass задачу (используя del ).

 var del = require('del');

gulp.task('clean', function() { 
  return del('./public');
});

gulp.task('sass', ['clean'], function() {
  //...
});
  

Это имеет дополнительное преимущество, заключающееся в том, что при изменении ./public/ одного из ваших файлов в вашей папке не остается нескольких измененных файлов (что приводит к другому хэшу и, следовательно, к другому имени файла).).

Комментарии:

1. Отличный материал. Спасибо, Свен!

Ответ №2:

Я не очень разбираюсь в gulp, но:

Когда я столкнулся с этой проблемой, мне просто нужно было вызвать .pipe(revDelete()) после .pipe(revAll.revision()) предположим, что revDelete поступает из require(‘gulp-rev-delete-original’)

Выполняя вышеописанное, вы избавитесь от старых хэшированных файлов. Проблема с этим решением заключается в том, что при каждом запуске задачи у вас будут более длинные имена файлов application.4434fcd5.4434fcd5.css, application.4434fcd5.4434fcd5.4434fcd5.4434fcd5.4434fcd5.4434fcd5.4434fcd5.css и так далее… Чтобы решить эту проблему, вы можете проверить, имеет ли файл уже хэш или нет, и в положительном случае вы его удаляете. Для достижения этого вы можете поместить следующий код перед .pipe(revAll.revision()):

.pipe(gulpif(hasOldHash, переименовать(filenameHashRegex, «))) . hasOldHash — это метод, который содержит регулярное выражение, соответствующее формату хэша, и удаляет его из имени файла, если в файле уже есть старый хэш.

Хорошо, это было слишком много текста, я обобщу все, используя код:

 // Imports
const gulp = require('gulp');
const revDelete = require('gulp-rev-delete-original');
const rename = require('gulp-regex-rename');
const gulpif = require('gulp-if');
const path = require('path');
const revAll = require("gulp-rev-all");

gulp.task('revall', function(){

    const dest = 'src/app/commons/components';

    // .   hash (8 exact alfanumeric characters), i.e.: test.a345fk39.js matches .a345fk39
    const filenameHashRegex = ****TODO****

    // Function that returns true if the filename has an old hash
    const hasOldHash = function(file) {
        const fileName = path.parse(file.path).name;

        if(filenameHashRegex.test(fileName)){
            console.log("***has old hash***");
            return true;
        }
    };

    return gulp.src('yourdesiredpath/**/*.{js,html}') // Source files to be hashed
        .pipe(gulpif(hasOldHash, rename(filenameHashRegex, ''))) // If the filename contains and old hash, removes it to add the new one
        .pipe(revAll.revision()) // Adds hash to the filename and update the references to that new hash
        .pipe(revDelete()) // Deletes all inactive and out of date files, so you are left with only the most recent hashed file
        .pipe(gulp.dest('yourdesiredpath')); // Final destinations where new hashed files are located
});