-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathasset_pipeline.html
More file actions
433 lines (424 loc) · 29.1 KB
/
asset_pipeline.html
File metadata and controls
433 lines (424 loc) · 29.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
<!doctype html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The Asset Pipeline — Ruby on Rails Guides</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style.css" data-turbo-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print">
<link rel="stylesheet" type="text/css" href="stylesheets/highlight.css" data-turbo-track="reload">
<link rel="icon" href="images/backend-development.svg" sizes="any">
<script src="javascripts/@hotwired--turbo.js" data-turbo-track="reload"></script>
<script src="javascripts/clipboard.js" data-turbo-track="reload"></script>
<script src="javascripts/guides.js" data-turbo-track="reload"></script>
<meta property="og:title" content="The Asset Pipeline — Ruby on Rails Guides" />
<meta name="description" content="The Asset PipelineA web site consist of many more files than just the HTML documents we have been generating up to now: css files, javascript files, image files, font files, ...The asset pipeline is rails' way of preparing theses files for publication using the current state of knowledge regarding web performance.By referring to this guide, you will be able to: keep your assets in the right place have all your assets compiled and minified for production" />
<meta property="og:description" content="The Asset PipelineA web site consist of many more files than just the HTML documents we have been generating up to now: css files, javascript files, image files, font files, ...The asset pipeline is rails' way of preparing theses files for publication using the current state of knowledge regarding web performance.By referring to this guide, you will be able to: keep your assets in the right place have all your assets compiled and minified for production" />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="Textbook Backend Developemnt" />
<meta property="og:image" content="images/backend-development.svg" />
<meta property="og:type" content="website" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Heebo:wght@100..900&family=Noto+Sans+Arabic:wght@100..900&display=swap" rel="stylesheet">
<meta name="theme-color" content="#2e56e9">
</head>
<body class="guide">
<header id="page_header">
<div class="wrapper clearfix">
<nav id="feature_nav">
<div class="header-logo">
<a href="/">Backend Development</a>
</div>
<ul class="nav">
<li><a class="nav-item" id="home_nav" href="/">Home</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">Index</a>
<div id="guides" class="clearfix" style="display: none;">
<hr />
<dl class="guides-section-container">
<div class="guides-section">
<dt>Ruby on Rails</dt>
<dd><a href="ruby_commandline.html">Ruby Commandline</a></dd>
<dd><a href="rails_database_and_model.html">Models and ActiveRecord</a></dd>
<dd><a href="rails_db.html">Database and Migrations</a></dd>
<dd><a href="rails_associations_and_validations.html">Associations and Validations</a></dd>
<dd><a href="rails_view_and_controller.html">Routing, View and Controller</a></dd>
<dd><a href="rails_authentication.html">Simple Authentication</a></dd>
<dd><a href="assets_and_import_map.html">The Asset Pipeline and Importmaps</a></dd>
<dd><a href="testing.html">Getting started with Testing</a></dd>
<dd><a href="refactoring_rails.html">Refactoring Rails</a></dd>
<dd><a href="deploy-to-paas.html">Deploy to PAAS</a></dd>
<dd><a href="rails_gems.html">Ruby Gems for your Rails Project</a></dd>
<dd><a href="deploying_rails.html">Deploying Rails</a></dd>
</div>
<div class="guides-section">
<dt>Ruby on Rails - Advanced Topics</dt>
<dd><a href="deploy-to-paas.html">Deploy to PAAS</a></dd>
<dd><a href="rest-api.html">REST API</a></dd>
<dd><a href="graphql-api.html">GraphQL API</a></dd>
<dd><a href="rails_websockets.html">Websocket in Rails</a></dd>
<dd><a href="jobs_and_tasks.html">Jobs and Tasks in Rails</a></dd>
<dd><a href="rails_security.html">Rails Security</a></dd>
</div>
<div class="guides-section">
<dt>Overarching Concerns</dt>
<dd><a href="issue.html">Issue Lifecycle</a></dd>
<dd><a href="security.html">Security</a></dd>
<dd><a href="adv_authentication.html">Advanced Authentication</a></dd>
<dd><a href="caching.html">Caching</a></dd>
<dd><a href="advanced_testing.html">Advanced Testing</a></dd>
<dd><a href="internationalization.html">Internationalization (I18n)</a></dd>
<dd><a href="git_rebasing.html">Git Rebasing</a></dd>
</div>
<div class="guides-section">
<dt>Nodes.js</dt>
<dd><a href="node_vs_rails.html">Node vs. Rails</a></dd>
<dd><a href="node_basics.html">Node Basics</a></dd>
<dd><a href="node_websockets.html">Node Websockets</a></dd>
<dd><a href="node_express.html">Node Web App</a></dd>
<dd><a href="node_cluster.html">Scaling Node</a></dd>
</div>
<div class="guides-section">
<dt>Next.js</dt>
<dd><a href="nextjs.html">Next.js</a></dd>
</div>
</dl>
</div>
</li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">Index</option>
<optgroup label="Ruby on Rails">
<option value="ruby_commandline.html">Ruby Commandline</option>
<option value="rails_database_and_model.html">Models and ActiveRecord</option>
<option value="rails_db.html">Database and Migrations</option>
<option value="rails_associations_and_validations.html">Associations and Validations</option>
<option value="rails_view_and_controller.html">Routing, View and Controller</option>
<option value="rails_authentication.html">Simple Authentication</option>
<option value="assets_and_import_map.html">The Asset Pipeline and Importmaps</option>
<option value="testing.html">Getting started with Testing</option>
<option value="refactoring_rails.html">Refactoring Rails</option>
<option value="deploy-to-paas.html">Deploy to PAAS</option>
<option value="rails_gems.html">Ruby Gems for your Rails Project</option>
<option value="deploying_rails.html">Deploying Rails</option>
</optgroup>
<optgroup label="Ruby on Rails - Advanced Topics">
<option value="deploy-to-paas.html">Deploy to PAAS</option>
<option value="rest-api.html">REST API</option>
<option value="graphql-api.html">GraphQL API</option>
<option value="rails_websockets.html">Websocket in Rails</option>
<option value="jobs_and_tasks.html">Jobs and Tasks in Rails</option>
<option value="rails_security.html">Rails Security</option>
</optgroup>
<optgroup label="Overarching Concerns">
<option value="issue.html">Issue Lifecycle</option>
<option value="security.html">Security</option>
<option value="adv_authentication.html">Advanced Authentication</option>
<option value="caching.html">Caching</option>
<option value="advanced_testing.html">Advanced Testing</option>
<option value="internationalization.html">Internationalization (I18n)</option>
<option value="git_rebasing.html">Git Rebasing</option>
</optgroup>
<optgroup label="Nodes.js">
<option value="node_vs_rails.html">Node vs. Rails</option>
<option value="node_basics.html">Node Basics</option>
<option value="node_websockets.html">Node Websockets</option>
<option value="node_express.html">Node Web App</option>
<option value="node_cluster.html">Scaling Node</option>
</optgroup>
<optgroup label="Next.js">
<option value="nextjs.html">Next.js</option>
</optgroup>
</select>
</li>
</ul>
</nav>
</div>
</header>
<hr class="hide" />
<section id="feature">
<div class="wrapper">
<h1>The Asset Pipeline</h1><p>A web site consist of many more files than just the
HTML documents we have been generating up to now:
css files, javascript files, image files, font files, ...</p><p>The asset pipeline is rails' way of preparing
theses files for publication using the current state
of knowledge regarding web performance.</p><p>By referring to this guide, you will be able to:</p>
<ul>
<li>keep your assets in the right place</li>
<li>have all your assets compiled and minified for production</li>
</ul>
<nav id="subCol">
<h3 class="chapter">
<picture>
<!-- Using the `source` HTML tag to set the dark theme image -->
<source
srcset="images/icon_book-close-bookmark-1-wht.svg"
media="(prefers-color-scheme: dark)"
/>
<img src="images/icon_book-close-bookmark-1.svg" alt="Chapter Icon" />
</picture>
Chapters
</h3>
<ol class="chapters">
<li><a href="#web-performance">Web Performance</a>
<ul>
<li><a href="#myths-about-performance">Myths About Performance</a></li>
<li><a href="#measuring-web-performance">Measuring Web Performance</a></li>
<li><a href="#rules">Rules...</a></li>
<li><a href="#less-http-requests-questionmark">Less HTTP Requests?</a></li>
</ul></li>
<li><a href="#how-rails-helps-with-performance">How Rails helps with Performance</a>
<ul>
<li><a href="#rails-environments">Rails Environments</a></li>
<li><a href="#development-environment-and-the-asset-pipeline">development Environment and the Asset Pipeline</a></li>
<li><a href="#production-environment-and-the-asset-pipeline">production Environment and the Asset Pipeline</a></li>
<li><a href="#fingerprinting-for-better-expiry">Fingerprinting for better Expiry</a></li>
</ul></li>
<li><a href="#user-generated-content">User Generated Content</a></li>
<li><a href="#further-reading">Further Reading</a></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<div class='slide'>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-0' href='slides_asset_pipeline.html#/0'>◻</a></p>
<h2 id="web-performance"><a class="anchorlink" href="#web-performance"><span>1</span> Web Performance</a></h2><p>What do we mean by 'web performance'? From the viewpoint of one user,
the crucial value is the time it takes from requesting a page (by clicking a link
or button, or typing in an URL) to having the page displayed and interactive in your browser.
We will call this the 'response time'.</p><p>From the publishers point of view it might also encompass the question of
how many users you can serve (with acceptable response time) on a given
server. If you look at the question of how to serve more users in case
of more demand you enter the realm of 'scalability'. This is a more advanced
question that goes beyond the scope of this guide.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-1' href='slides_asset_pipeline.html#/1'>◻</a></p>
<h3 id="myths-about-performance"><a class="anchorlink" href="#myths-about-performance"><span>1.1</span> Myths About Performance</a></h3><p>If you have never studied this subject you might still have
an intuition about where performance problems come from.
Many beginners are fascinated by details of their programming
language like: <code>will using more variables make my program slower?</code>
or <code>is string concatenation faster than string interpolation?</code>.</p><p>These 'micro optimizations' are hardly ever necssary with modern
programming languages and computers. Using Rails, Postgres and a modern
hosting service you will have no trouble serving hundreds
of users a day and achieving adequate performance for all of them.</p><p>Trying to 'optimize' you code if there is no problem, or
if you don't know where the problem is,
will make your code worse, not better.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-2' href='slides_asset_pipeline.html#/2'>◻</a></p>
<p>Donald Knuth stated this quite forcefully:</p><p>"The real problem is that programmers have spent far too much time worrying about efficiency in the wrong places and at the wrong times; <strong>premature optimization is the root of all evil</strong>" -- <a href="https://en.wikiquote.org/wiki/Donald_Knuth#Computer_Programming_as_an_Art_.281974.29">Donald Knuth</a></p><p>Only after you have measured the performance factors that are
relevant to your project, and only after you have found out
which part of the system is causing theses factors to go over
the threshold of acceptable values, only then can you truly
start to 'optimize'.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-3' href='slides_asset_pipeline.html#/3'>◻</a></p>
<h3 id="measuring-web-performance"><a class="anchorlink" href="#measuring-web-performance"><span>1.2</span> Measuring Web Performance</a></h3><p>The "exceptional performance group" at Yahoo published the browser addon
<code>yslow</code> in 2007. It measures performance and displays the timing
of the different HTTP connections as a "waterfall graph":</p><p><img src="images/network-souders-2008.png" alt="displaying http downloads with yslow"></p><p>(Image from Steve Souders <a href="https://conferences.oreilly.com/web2expo/webexsf2008/public/schedule/detail/3321">talk at Web 2.0 Expo</a> in April 2008)</p><p>Each bar is one resource being retrieved via HTTP, the x-axis
is a common timeline for all. The most striking result you can read from
this graph: the backend is only responsible for 5% of the time in this
example! 95% of time is spent loading and parsing javascript and css files
and loading and displaying images!</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-4' href='slides_asset_pipeline.html#/4'>◻</a></p>
<p>This graph was later integrated into the built in developer tools
of several browsers, and into the online tool <a href="https://catchpoint.com/webpagetest">webpagetest</a>.</p><p><strong>Firefox</strong></p><p><img src="images/network-view-firefox.png" alt="network view in firefox"></p><p><strong>Chrome</strong></p><p><img src="images/network-view-chrome.png" alt="network view in chrom"></p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-5' href='slides_asset_pipeline.html#/5'>◻</a></p>
<h3 id="rules"><a class="anchorlink" href="#rules"><span>1.3</span> Rules...</a></h3><p>Yahoo first published 14 rules for web performance in 2007, based
on the measurements back then:</p>
<ul>
<li>Make Less HTTP Requests</li>
<li>Use a Content Delivery Network</li>
<li>Avoid empty src or href</li>
<li>Add an Expires or a Cache-Control Header</li>
<li>Gzip Components</li>
<li>Put StyleSheets at the Top</li>
<li>Put Scripts at the Bottom</li>
<li>Avoid CSS Expressions...</li>
<li>Make JavaScript and CSS External</li>
<li>Reduce DNS Lookups</li>
<li>Minify JavaScript and CSS</li>
<li>Avoid Redirects</li>
<li>Remove Duplicate Scripts</li>
</ul>
<p>Even with changing browsers and
protocols some of these are still very valid today.
But as a web developer you should always keep an eye on the changing
landscape of web performance! These rules and their priority will change!</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-6' href='slides_asset_pipeline.html#/6'>◻</a></p>
<h3 id="less-http-requests-questionmark"><a class="anchorlink" href="#less-http-requests-questionmark"><span>1.4</span> Less HTTP Requests?</a></h3><p>Making less HTTP Requests was a main goal in performance optimization for many years.
Many JavaScript files were combined into one, the same for CSS. Icon Fonts were used
to combine many small image files into one file.</p><p>On the other hand the HTTP protocol itself was improved again and again,
to make repeated requests to the same server "cheaper":</p>
<ul>
<li><a href="https://en.wikipedia.org/wiki/HTTP/2">HTTP/2</a> server HTTP requests can be multiplexed over a single TCP connection</li>
<li><a href="https://en.wikipedia.org/wiki/HTTP/3">HTTP/3</a> uses UDP instead of TCP</li>
</ul>
<p>In 2022 HTTP/3 is <a href="https://caniuse.com/http3">supported by</a> all common browsers except safari and use by <a href="https://w3techs.com/technologies/details/ce-http3">about a quater</a> of the top 10 million websites.</p><p>So today this "first rule" for avoiding HTTP requests can be relaxed.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-7' href='slides_asset_pipeline.html#/7'>◻</a></p>
<h2 id="how-rails-helps-with-performance"><a class="anchorlink" href="#how-rails-helps-with-performance"><span>2</span> How Rails helps with Performance</a></h2><p>The Rails asset pipeline was introduced in Rails 3.1 in the year 2011.
It automates handling static assets:</p>
<ul>
<li>Compile to CSS (e.g. LESS, SASS)</li>
<li>Minify and combine several CSS files into one</li>
<li>Compile to JavaScript (e.g. typescript, babel)</li>
<li>Minify and combine several JavaScript files into one</li>
<li>Optimize images</li>
<li>Create several versions of pixel images</li>
<li>Create CSS Sprites</li>
</ul>
<p><img src="images/asset-pipeline.svg" alt="Asset Pipeline"></p><p>There are two main folders:</p>
<ul>
<li>you put source files in <code>app/assets/*</code></li>
<li>you configure which files are built and included in <code>app/assets/config/manifest.js</code>, <code>app/assets/stylesheets/application.css</code> and <code>app/assets/javascript/application.js</code></li>
<li>files for publishing are created in <code>public/assets/*</code></li>
</ul>
<p>The second folder will be served by the web server directly, without going through the Rails stack.
The expires header for these files is set to a far future date.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-8' href='slides_asset_pipeline.html#/8'>◻</a></p>
<h3 id="rails-environments"><a class="anchorlink" href="#rails-environments"><span>2.1</span> Rails Environments</a></h3><p>The Asset Pipeline works differently in different Rails Environments.
There are three environments that exist by default:</p>
<ul>
<li><code>development</code>
<ul>
<li>this is the environment you have been working in until now,</li>
<li>it is optimized for debugging, shows error messages and the error console.</li>
</ul></li>
<li><code>testing</code>
<ul>
<li>this is used for running the <a href="testing.html">automatic tests</a>.</li>
</ul></li>
<li><code>production</code>
<ul>
<li>this is how the finished app will run after it is published,</li>
<li>it is optimized for speed and stability.</li>
</ul></li>
</ul>
<p>How each envirnoments behaves is configured in files in <code>config/environments/*.rb</code>.</p><p>The development environment is used by default on your machine. If you deploy
to heroku or to another hosting server, production will be used there.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-9' href='slides_asset_pipeline.html#/9'>◻</a></p>
<h3 id="development-environment-and-the-asset-pipeline"><a class="anchorlink" href="#development-environment-and-the-asset-pipeline"><span>2.2</span> development Environment and the Asset Pipeline</a></h3><p>In <code>development</code> the asset pipeline will not write files to <code>public/assets</code>. Instead
these files will be created on the fly, and not be conactenated. The two lines
in your Layout:</p><div class="interstitial code">
<pre><code class="highlight plaintext"># app/views/layouts/application.html.erb
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
</code></pre>
<button class="clipboard-button" data-clipboard-text="# app/views/layouts/application.html.erb
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
">Copy</button>
</div>
<p>Will each result in a number of links. Here an example from a real project:</p><div class="interstitial code">
<pre><code class="highlight plaintext"><link rel="stylesheet" href="/asset-files/search-a01b0css?body=1" />
<link rel="stylesheet" href="/asset-files/slider-974d5css?body=1" />
<link rel="stylesheet" href="/asset-files/static-7fe63css?body=1" />
<link rel="stylesheet" href="/asset-files/token-input-f5febcss?body=1" />
<link rel="stylesheet" href="/asset-files/wizzard-9a065css?body=1" />
<script src="/asset-files/jquery-4075ejs?body=1"></script>
<script src="/asset-files/jquery_ujs-f9f4ajs?body=1"></script>
<script src="/asset-files/portfolio/portfolio-78775js?body=1"></script>
<script src="/asset-files/swfobject-40913js?body=1"></script>
<script src="/asset-files/jquery-uploadify-702eajs?body=1"></script>
<script src="/asset-files/application-d7727js?body=1"></script>
<script src="/asset-files/can-custom-c11b4js?body=1"></script>
<script src="/asset-files/easySlider-6386djs?body=1"></script>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<link rel="stylesheet" href="/asset-files/search-a01b0css?body=1" />
<link rel="stylesheet" href="/asset-files/slider-974d5css?body=1" />
<link rel="stylesheet" href="/asset-files/static-7fe63css?body=1" />
<link rel="stylesheet" href="/asset-files/token-input-f5febcss?body=1" />
<link rel="stylesheet" href="/asset-files/wizzard-9a065css?body=1" />
<script src="/asset-files/jquery-4075ejs?body=1"></script>
<script src="/asset-files/jquery_ujs-f9f4ajs?body=1"></script>
<script src="/asset-files/portfolio/portfolio-78775js?body=1"></script>
<script src="/asset-files/swfobject-40913js?body=1"></script>
<script src="/asset-files/jquery-uploadify-702eajs?body=1"></script>
<script src="/asset-files/application-d7727js?body=1"></script>
<script src="/asset-files/can-custom-c11b4js?body=1"></script>
<script src="/asset-files/easySlider-6386djs?body=1"></script>
">Copy</button>
</div>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-10' href='slides_asset_pipeline.html#/10'>◻</a></p>
<h3 id="production-environment-and-the-asset-pipeline"><a class="anchorlink" href="#production-environment-and-the-asset-pipeline"><span>2.3</span> production Environment and the Asset Pipeline</a></h3><p>When you deploy to production, you deployment process will run <code>rake assets:precompile</code>,
which generates the files in <code>public/assets</code>, including <code>public/assets/manifest-md5hash.json</code>.</p><p>If you look at the generated HTML code on the production server,
you will only find two links (plus some code to handle IE 8): in production
the many css files have been concatenated into one <code>application*.css</code>, and
all JavaScript files have been concatenated into one <code>application*.js</code>:</p><div class="interstitial code">
<pre><code class="highlight plaintext"><link href="/assets/application-dee0187.css" media="screen" rel="stylesheet" />
<!--[if lte IE 8]>
<link href="/assets/application-ie-d369224.css" rel="stylesheet" />
<![endif]-->
<script src="/assets/application-c51a73.js" type="text/javascript"></script>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<link href="/assets/application-dee0187.css" media="screen" rel="stylesheet" />
<!--[if lte IE 8]>
<link href="/assets/application-ie-d369224.css" rel="stylesheet" />
<![endif]-->
<script src="/assets/application-c51a73.js" type="text/javascript"></script>
">Copy</button>
</div>
<p>You can also try out the production environment on your own machine:</p>
<ul>
<li>start the web server: <code>rails server -e production</code></li>
<li>rails console: <code>rails console -e production</code></li>
<li>other rails commands: add <code>RAILS_ENV=production</code> at the beginning or the end of the command.</li>
</ul>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-11' href='slides_asset_pipeline.html#/11'>◻</a></p>
<h3 id="fingerprinting-for-better-expiry"><a class="anchorlink" href="#fingerprinting-for-better-expiry"><span>2.4</span> Fingerprinting for better Expiry</a></h3><p>The filenames mentioned in the last chapter all contain a part that seems random:</p>
<ul>
<li>you named the file <code>slider.css</code></li>
<li>but it shows up as <code>slider-974d585dcb6f5aec673164664a4e49d5.css</code></li>
</ul>
<p>Where do the extra characters come from and what do they mean?</p><p>These extra characters are the "fingerprint". It is computed from the full
content of the file. If only one byte changes in the file, the fingerprint will
be different.</p><p>This enables a neat trick with the expiry of the file: You can set the expiry time
to infinite, every browser can save the file forever and never try to reload it.
If the contents of the file change, a new file with a new fingerprint in the name will
be generated, and the HTML-page will link to that file.</p><p>This way we avoid one the the <a href="https://twitter.com/codinghorror/status/506010907021828096">two hard problems in computer science</a>: cache invalidation.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-12' href='slides_asset_pipeline.html#/12'>◻</a></p>
<h2 id="user-generated-content"><a class="anchorlink" href="#user-generated-content"><span>3</span> User Generated Content</a></h2><p>The asset pipeline handles assets that are
added by developers during development.
Images uploaded by users in production
are handled by <a href="https://edgeguides.rubyonrails.org/active_storage_overview.html">activestorage</a>.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-13' href='slides_asset_pipeline.html#/13'>◻</a></p>
<h2 id="further-reading"><a class="anchorlink" href="#further-reading"><span>4</span> Further Reading</a></h2>
<ul>
<li>Souders(2007): High Performance Web Sites. O'Reilly. ISBN-13: 978-0596529307.</li>
<li>Souders(2009): Even Faster Web Sites. O'Reilly. ISBN-13: 978-0596522308.</li>
<li><a href="https://calendar.perfplanet.com/2018/">The Web Performance (Advent) Calendar</a> new every year</li>
</ul>
</div>
</div>
</div>
</main>
<hr class="hide" />
<footer id="page_footer">
<div class="wrapper">
<p class="copyright">published under <a href="https://creativecommons.org/licenses/by-nc-sa/3.0/at/deed.de">creative commons by-nc-sa</a> in 2012-2025 by <a href="https://brigitte-jellinek.at">Brigitte Jellinek</a>.
</p>
<p>If you want to contribute: <a href="https://github.com/backend-development/backend-development-textbook/fork">fork the source on github</a>
</p>
<p>Favicon "backend development" by Arkinasi from <a href="https://thenounproject.com/browse/icons/term/backend-development/" target="_blank" title="backend development Icons">Noun Project</a> (CC BY 3.0)</p>
</div>
</footer>
</body>
</html>