My Rails 4 application allow it's users to import some Adobe Edge animation files (advertisement). While it works, Adobe Edge is loading a bunch of files that could be minified and optimized (images) using a tool like Grunt or Gulp.
I'm using CarrierWave to upload the files and then I extract them if they are inside an archive :
class FileUploader < CarrierWave::Uploader::Base
after :store, :uncompress_and_update_reference
def uncompress_and_update_reference(_file)
return unless archive_is_supported?(model.ext)
extractor = Uploader::Archive.const_get("Extractor#{model.ext.upcase}").new
Uploader::Archive::PubArchive.new(extractor, model, full_path).extract_and_save
end
end
I was thinking that I could use Grunt or Gulp in a background job (using Sidekiq for example) to work on those extracted files as I need. The problem is how can I do it?
From what I've read, in order to run grunt
or gulp
, they both need to have a Gruntfile.js
and Gulpfile.js
respectively, which makes things tricky as I need to run it dynamically inside the extracted folder.
Anyone?
Ok, I finally created a Node CLI to handle that case. Since I needed to be able to optimize files dynamically inside a folder, having a command line utility is somehow the best scenario :
cli.js
#!/usr/bin/env node
'use strict';
var meow = require('meow');
var fs = require('fs');
var optimizer = require('./');
var cli = meow({
help: [
'Usage : pub-optimizer <path_to_optimize> <path_to_optimize>',
''
].join('\n')
});
var paths = cli.input
paths.forEach(function (path) {
if (fs.existsSync(path) {
optimizer.minify(path);
} else {
console.log(path + ' is not a valid directory.')
}
});
index.js
'use strict';
var gulp = require('gulp');
var imagemin = require('gulp-imagemin');
var pngquant = require('imagemin-pngquant');
exports.minify = function (folderPath) {
// Remove trailing slash
folderPath = folderPath.replace(/\/+$/, "");
// Optimize images
gulp.task('default', function () {
return gulp
.src(folderPath + '/**/*.{png,jpg,jpeg,gif,webp,svg}')
.pipe(imagemin({
progressive: true,
use: [pngquant()]
}))
.pipe(gulp.dest(folderPath));
});
gulp.start();
};
Then all I need to do was to invoke that CLI from my Rails app :
uploaders/file_uploader.rb
class FileUploader < CarrierWave::Uploader::Base
after :store, :uncompress_and_update_reference
def uncompress_and_update_reference(_file)
return unless archive_is_supported?(model.ext)
extractor = Uploader::Archive.const_get("Extractor#{model.ext.upcase}").new
Uploader::Archive::PubArchive.new(extractor, model, full_path).extract_and_save
PubOptimizerWorker.perform_async(fullpath)
end
end
workers/pub_optimizer_worker.rb
class PubApprovalRequestWorker
include Sidekiq::Worker
sidekiq_options queue: :pub
def perform(path)
system("pub-optimizer #{path}")
end
end
Hope this will maybe help someone.