Skip to content

Instantly share code, notes, and snippets.

@cleverfox
Forked from kraih/CSSCompressor.pm
Last active January 2, 2016 02:49
Show Gist options
  • Save cleverfox/8239771 to your computer and use it in GitHub Desktop.
Save cleverfox/8239771 to your computer and use it in GitHub Desktop.
use Mojolicious::Lite;
plugin 'Pipeline';
plugin 'Pipeline::CSSCompressor';
app->asset('app.js' => ['one.js', 'js/two.js']);
app->asset('app.css' => ['stylesheets/*.css'] => 'css_compressor');
get '/' => 'index';
app->start;
__DATA__
@@ index.html.ep
% title 'Hello!';
% layout 'default';
<div id="hello">Hello Mojo!</div>
@@ layouts/default.html.ep
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
%= asset 'app.css'
%= asset 'app.js'
</head>
<body><%= content %></body>
</html>
@@ one.js
alert('One!');
@@ js/two.js
alert('Two!');
@@ stylesheets/one.css
div {
color: #fff;
}
@@ stylesheets/two.css
body {
background-color: #000;
}
@@ stylesheets/three.css
#hello {
font: 0.9em 'Helvetica Neue', Helvetica, sans-serif;
}
@@ stylesheets/four.css
body {
margin: 0;
}
@@ stylesheets/five.css
#hello {
line-height: 1.5em;
}
package Mojolicious::Plugin::Pipeline::CSSCompressor;
use Mojo::Base 'Mojolicious::Plugin';
use CSS::Compressor 'css_compress';
sub register {
my ($self, $app) = @_;
# Register "css_compressor" filter
$app->filter(css_compressor => sub { css_compress shift });
}
1;
package Mojolicious::Plugin::Pipeline;
use Mojo::Base 'Mojolicious::Plugin';
use Mojo::Asset::Memory;
use Mojo::Home;
use Mojo::Loader;
use Mojo::Util 'md5_sum';
sub register {
my ($self, $app) = @_;
# List all static files
my @files
= map { @{Mojo::Home->new($_)->list_files} } @{$app->static->paths};
push @files,
map { keys %{Mojo::Loader->new->data($_)} } @{$app->static->classes};
# Register "filter" helper
my %filters;
$app->helper(
filter => sub {
my ($self, $name, $cb) = @_;
$filters{$name} = $cb;
}
);
# Register "asset" helper
my %assets;
$app->helper(
asset => sub {
my ($self, $name, $sources) = (shift, shift, shift);
# Generate "link" or "script" tag
unless ($sources) {
my $checksum = $assets{$name}{checksum};
$name =~ /^(.+)\.(\w+)$/;
return $self->stylesheet("/asset/$1.$checksum.$2") if $2 eq 'css';
return $self->javascript("/asset/$1.$checksum.$2");
}
$self->app->log->debug(qq/Generating asset $name/);
# Concatenate
my $asset = '';
for my $source (@$sources) {
# Glob support
$source = quotemeta $source;
$source =~ s/\\\*/[^\/]+/;
# Check all files
for my $file (@files) {
next unless $file =~ /^$source$/;
$asset .= $self->app->static->file($file)->slurp;
}
}
# Filter
for my $filter (@_) { $asset = $filters{$filter}->($asset) }
# Store source with current checksum
$assets{$name} = {source => $asset, checksum => md5_sum($asset)};
if($app->mode eq 'production'){
my $checksum = $assets{$name}{checksum};
$name =~ /^(.+)\.(\w+)$/;
my $file = Mojo::Asset::File->new();
$file->add_chunk($asset);
my $static = $self->app->static;
my $fname="/asset/$1.$checksum.$2";
$self->app->log->info('saving compiled asset into '.$fname);
$file->move_to($static->paths->[0].$fname);
}
}
);
# Asset dispatcher
$app->hook(
before_dispatch => sub {
my $self = shift;
# Match asset path with checksum
return
unless $self->req->url->path =~ /^\/asset\/?(.+)\.([[:xdigit:]]+)\.(\w+)$/;
return unless my $asset = $assets{"$1.$3"};
# Serve asset
$self->app->log->debug(qq/Serving asset "$1.$3" with checksum "$2"./);
if ($3 eq 'css') {
$self->res->headers->content_type('text/css');
} elsif ($3 eq 'js') {
$self->res->headers->content_type('application/javascript');
}
$self->app->static->serve_asset($self,
Mojo::Asset::Memory->new->add_chunk($asset->{source}));
$self->tap(sub { shift->stash('mojo.static' => 1) })->rendered;
}
);
}
1;
@cleverfox
Copy link
Author

My version saves rendered assets to public/assets for serving with nginx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment