Skip to content

Commit 2018bc7

Browse files
author
Jan Henning Thorsen
committed
Add stages to Asset so the checksum is less volatile
1 parent 39ca280 commit 2018bc7

File tree

4 files changed

+68
-31
lines changed

4 files changed

+68
-31
lines changed

lib/Mojolicious/Plugin/AssetPack.pm

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,14 @@ sub _process {
132132
$asset->checksum;
133133
}
134134

135-
for my $method (qw(before_process process after_process)) {
135+
for my $stage (qw(before_process process after_process)) {
136+
$assets->map(stage => $stage);
137+
136138
for my $pipe (@{$self->{pipes}}) {
137-
next unless $pipe->can($method);
139+
next unless $pipe->can($stage);
138140
local $pipe->{topic} = $topic;
139-
diag '%s->%s("%s")', ref $pipe, $method, $topic if DEBUG;
140-
$pipe->$method($assets);
141+
diag '%s->%s("%s")', ref $pipe, $stage, $topic if DEBUG;
142+
$pipe->$stage($assets);
141143
}
142144
}
143145

lib/Mojolicious/Plugin/AssetPack/Asset.pm

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ $TAG_TEMPLATE{js} = [qw(script src)];
1313
$TAG_TEMPLATE{$_} = [qw(img src)] for qw(gif jpg jpeg png svg);
1414
$TAG_TEMPLATE{$_} = [qw(source src)] for qw(mp3 mp4 ogg ogv webm);
1515

16-
has checksum => sub { Mojolicious::Plugin::AssetPack::Util::checksum(shift->content) };
16+
has stage => 'init';
17+
1718
has format => sub {
1819
my $self = shift;
1920
my $name = $self->url =~ /^https?:/ ? Mojo::URL->new($self->url)->path->[-1] : (split m!(\\|/)!, $self->url)[-1];
@@ -69,6 +70,15 @@ sub asset {
6970
return $clone;
7071
}
7172

73+
sub checksum {
74+
my $self = shift;
75+
return $self->{checksum} ||= Mojolicious::Plugin::AssetPack::Util::checksum($self->content) unless @_;
76+
Carp::confess(qq(Cannot change checksum when stage is "@{[$self->stage]}")) unless $self->stage eq 'before_process';
77+
$self->{checksum} = shift;
78+
diag qq(checksum(@{[$self->url]}) = $self->{checksum}) if DEBUG;
79+
return $self;
80+
}
81+
7282
sub content {
7383
my $self = shift;
7484
return $self->_asset->slurp unless @_;
@@ -98,7 +108,7 @@ sub _default_tag_for {
98108

99109
sub FROM_JSON {
100110
my ($self, $attrs) = @_;
101-
$self->$_($attrs->{$_}) for grep { defined $attrs->{$_} } qw(checksum format minified);
111+
$self->$_($attrs->{$_}) for grep { defined $attrs->{$_} } qw(format minified);
102112
$self;
103113
}
104114

@@ -125,13 +135,6 @@ L<Mojolicious::Plugin::AssetPack::Asset> represents an asset.
125135
126136
=head1 ATTRIBUTES
127137
128-
=head2 checksum
129-
130-
$str = $self->checksum;
131-
$self = $self->checksum($str);
132-
133-
The L<checksum|Mojolicious::Plugin::AssetPack::Util/checksum> of L</content>.
134-
135138
=head2 format
136139
137140
$str = $self->format;
@@ -161,6 +164,13 @@ Returns the basename of L</url>, without extension.
161164
Can be used to register a custom render method for this asset. This is called
162165
by L<Mojolicious::Plugin::AssetPack::Store/serve_asset>.
163166
167+
=head2 stage
168+
169+
$str = $self->stage;
170+
$self = $self->stage("process");
171+
172+
Contains the pipe stage name "before_process", "process" or "after_process".
173+
164174
=head2 tag_for
165175
166176
$code = $self->tag_for;
@@ -207,6 +217,14 @@ content or path from this object.
207217
208218
This method is EXPERIMENTAL.
209219
220+
=head2 checksum
221+
222+
$str = $self->checksum;
223+
$self = $self->checksum($str);
224+
225+
The L<checksum|Mojolicious::Plugin::AssetPack::Util/checksum> of L</content>.
226+
The value can only be changed if L</stage> is "before_process".
227+
210228
=head2 content
211229
212230
$bytes = $self->content;

lib/Mojolicious/Plugin/AssetPack/Pipe/Combine.pm

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,15 @@ sub process {
3131
my $checksum = checksum $combine->map('checksum')->join(':');
3232
my $content = $combine->map('content')->map(sub { /\n$/ ? $_ : "$_\n" })->join;
3333
diag 'Combining assets into "%s" with checksum %s.', $self->topic, $checksum if DEBUG;
34-
push @$assets,
35-
Mojolicious::Plugin::AssetPack::Asset->new(url => $self->topic)->checksum($checksum)->minified(1)
36-
->content($content);
34+
push(
35+
@$assets,
36+
Mojolicious::Plugin::AssetPack::Asset->new(
37+
checksum => $checksum,
38+
content => $content,
39+
minified => 1,
40+
url => $self->topic,
41+
)
42+
);
3743
}
3844
}
3945

lib/Mojolicious/Plugin/AssetPack/Pipe/Sass.pm

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ $SOURCE_MAP_PLACEHOLDER =~ s!::!_!g;
1515
has functions => sub { +{} };
1616
has generate_source_map => sub { shift->app->mode eq 'development' ? 1 : 0 };
1717

18+
sub before_process {
19+
my ($self, $assets) = @_;
20+
21+
return $assets->each(sub {
22+
my ($asset, $index) = @_;
23+
return if $asset->format !~ $FORMAT_RE;
24+
my @paths = (_include_path_for_asset($asset), @{$self->store->paths});
25+
my $content = $asset->content;
26+
$asset->checksum($self->_checksum(\$content, $asset, [grep {$_} @paths]));
27+
$asset->content($content) unless $asset->path;
28+
});
29+
}
30+
1831
sub process {
1932
my ($self, $assets) = @_;
2033
my $store = $self->assetpack->store;
@@ -33,29 +46,24 @@ sub process {
3346

3447
return $assets->each(sub {
3548
my ($asset, $index) = @_;
36-
3749
return if $asset->format !~ $FORMAT_RE;
50+
3851
my ($attrs, $content) = ($asset->TO_JSON, $asset->content);
39-
local $self->{checksum_for_file} = {};
40-
local $opts{include_paths}[0] = _include_path($asset);
4152
$attrs->{minified} = $self->assetpack->minify;
4253
$attrs->{key} = sprintf 'sass%s', $attrs->{minified} ? '-min' : '';
4354
$attrs->{format} = 'css';
44-
$attrs->{checksum} = $self->_checksum(\$content, $asset, $opts{include_paths});
4555

4656
return $asset->content($file)->FROM_JSON($attrs) if $file = $store->load($attrs);
4757
return if $asset->isa('Mojolicious::Plugin::AssetPack::Asset::Null');
48-
$opts{include_paths}[0] = $asset->path ? $asset->path->dirname : undef;
49-
$opts{include_paths} = [grep {$_} @{$opts{include_paths}}];
50-
diag 'Process "%s" with checksum %s.', $asset->url, $attrs->{checksum} if DEBUG;
58+
local $opts{include_paths}[0] = $asset->path ? $asset->path->dirname : undef;
59+
local $opts{include_paths} = [grep {$_} @{$opts{include_paths}}];
60+
diag 'Process "%s" with checksum %s.', $asset->url, $asset->checksum if DEBUG;
5161

5262
if ($self->{has_module} //= eval { load_module 'CSS::Sass'; 1 }) {
5363
$opts{output_style} = _output_style($attrs->{minified});
5464
$content = CSS::Sass::sass2scss($content) if $asset->format eq 'sass';
5565
my ($css, $err, $stats) = CSS::Sass::sass_compile($content, %opts);
56-
if ($err) {
57-
die sprintf '[Pipe::Sass] Could not compile "%s" with opts=%s: %s', $asset->url, dumper(\%opts), $err;
58-
}
66+
$err and Carp::confess(qq/[Pipe::Sass] Could not compile "@{[$asset->url]}" with opts=@{[dumper(\%opts)]}: $err/);
5967
$css = Mojo::Util::encode('UTF-8', $css);
6068
$self->_add_source_map_asset($asset, \$css, $stats) if $stats->{source_map_string};
6169
$asset->content($store->save(\$css, $attrs))->FROM_JSON($attrs);
@@ -94,7 +102,6 @@ sub _checksum {
94102
my $store = $self->assetpack->store;
95103
my @c = (checksum $$ref);
96104

97-
SEARCH:
98105
while ($$ref =~ /$IMPORT_RE/gs) {
99106
my $pre = $1;
100107
my $rel_path = $4;
@@ -113,12 +120,12 @@ SEARCH:
113120
next if $rel_path =~ m!^https?://! and !$dynamic;
114121

115122
unshift @basename, "_$name.$ext", "$name.$ext" unless $name =~ /\.$ext$/;
116-
my $imported = $store->asset([map { join '/', @rel, $_ } @basename], $paths)
117-
or die qq([Pipe::Sass] Could not find "$rel_path" file in @$paths);
123+
my $imported = $self->store->asset([map { join '/', @rel, $_ } @basename], $paths)
124+
or Carp::confess(qq([Pipe::Sass] Could not find "$rel_path" file in [@{[join ', ', @$paths]}].));
118125

119126
if ($imported->path) {
120127
diag '@import "%s" (%s)', $rel_path, $imported->path if DEBUG >= 2;
121-
local $paths->[0] = _include_path($imported);
128+
local $paths->[0] = _include_path_for_asset($imported);
122129
push @c, $self->_checksum(\$imported->content, $imported, $paths);
123130
}
124131
else {
@@ -132,7 +139,7 @@ SEARCH:
132139
return checksum join ':', @c;
133140
}
134141

135-
sub _include_path {
142+
sub _include_path_for_asset {
136143
my $asset = shift;
137144
return $asset->url if $asset->url =~ m!^https?://!;
138145
return $asset->path->dirname if $asset->path;
@@ -224,6 +231,10 @@ dev tools.
224231
225232
=head1 METHODS
226233
234+
=head2 before_process
235+
236+
See L<Mojolicious::Plugin::AssetPack::Pipe/before_process>.
237+
227238
=head2 process
228239
229240
See L<Mojolicious::Plugin::AssetPack::Pipe/process>.

0 commit comments

Comments
 (0)