#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, он делает что-то странное:
-
Первая задача gulp (без задачи proudction) создает:
application.css
(this task is idempotent)
-
Затем я впервые запускаю задачу gulp с производством. Теперь папка выглядит так:
application.css
application.4434fcd5.css
-
Затем я запускаю его снова, и теперь папка выглядит так:
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
});