-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathassets_and_webpacker.html
More file actions
441 lines (432 loc) · 30.1 KB
/
assets_and_webpacker.html
File metadata and controls
441 lines (432 loc) · 30.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
434
435
436
437
438
439
440
441
<!doctype html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Web Performance, Assets and Webpacker — 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="Web Performance, Assets and Webpacker — Ruby on Rails Guides" />
<meta name="description" content="Web Performance, Assets and WebpackerA 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, ...Webpacker is Rails' way of preparing theses files for publication using current frontend tools.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 by using the Rails Asset Pipeline for CSS and image by using Webpacker for JavaScript" />
<meta property="og:description" content="Web Performance, Assets and WebpackerA 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, ...Webpacker is Rails' way of preparing theses files for publication using current frontend tools.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 by using the Rails Asset Pipeline for CSS and image by using Webpacker for JavaScript" />
<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>Web Performance, Assets and Webpacker</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>Webpacker is Rails' way of preparing
theses files for publication using current
frontend tools.</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>
<li>by using the Rails Asset Pipeline for CSS and image</li>
<li>by using Webpacker for JavaScript</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="#permature-optimization">Permature Optimization</a></li>
<li><a href="#measuring-web-performance">Measuring Web Performance</a></li>
<li><a href="#rules">Rules...</a></li>
</ul></li>
<li><a href="#how-rails-helps-with-performance">How Rails helps with Performance</a>
<ul>
<li><a href="#static-files-are-fastest">Static files are fastest</a></li>
<li><a href="#rails-asset-pipeline">Rails Asset Pipeline</a></li>
<li><a href="#webpacker">Webpacker</a></li>
<li><a href="#rails-environments">Rails Environments</a></li>
<li><a href="#rails-environments-and-assets">Rails Environments and Assets</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="#using-webpacker-for-images-and-css">Using webpacker for images and css</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_assets_and_webpacker.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_assets_and_webpacker.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 and thousands
of users a day and achieving adequate performance for all of them.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-2' href='slides_assets_and_webpacker.html#/2'>◻</a></p>
<h3 id="permature-optimization"><a class="anchorlink" href="#permature-optimization"><span>1.2</span> Permature Optimization</a></h3><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><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 indicators that are
relevant to your project, and only after you have found out
which part of the system is causing theses indicators 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_assets_and_webpacker.html#/3'>◻</a></p>
<h3 id="measuring-web-performance"><a class="anchorlink" href="#measuring-web-performance"><span>1.3</span> Measuring Web Performance</a></h3><p>The "exceptional performance" group at Yahoo published the browser addon
<code>yslow</code> in 2007. It first measured performance and displayed 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><p>This graph was later integrated into the 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-4' href='slides_assets_and_webpacker.html#/4'>◻</a></p>
<h3 id="rules"><a class="anchorlink" href="#rules"><span>1.4</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 improving HTTP 1 to HTTP 2 and now HTTP 3 / QUIC
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-5' href='slides_assets_and_webpacker.html#/5'>◻</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></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-6' href='slides_assets_and_webpacker.html#/6'>◻</a></p>
<h3 id="static-files-are-fastest"><a class="anchorlink" href="#static-files-are-fastest"><span>2.1</span> Static files are fastest</a></h3><p>The first thing to know, is that assets do not need to be
served through the rails stack, but should be served by the
web server directly. In the following diagram they are
called 'static files':</p><p><img src="images/rails-mvc.svg" alt="MVC in Rails"></p><p>In production these static css, js, svg, gif, webp, ... files are found in the <code>public</code> folder.</p><p>In development we will write other files
that need to be compiled, optimized and / or concatenated to
create the static files.</p>
<ul>
<li>Compile to JavaScript (e.g. typescript, coffeescript,...)</li>
<li>Compile to CSS (e.g. LESS, SASS)</li>
<li>Minify and combine several JavaScript files into one</li>
<li>Minify and combine several CSS files into one</li>
<li>Optimize images</li>
<li>Create several versions of pixel images</li>
<li>Create CSS Sprites</li>
</ul>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-7' href='slides_assets_and_webpacker.html#/7'>◻</a></p>
<h3 id="rails-asset-pipeline"><a class="anchorlink" href="#rails-asset-pipeline"><span>2.2</span> Rails Asset Pipeline</a></h3><p>In a Rails 6 project The Rails Asset Pipeline handles everything except JavaScript.</p>
<ul>
<li>you put CSS (and less, sass, scss) files in <code>app/assets/stylesheets/*</code></li>
<li>you configure which CSS files are built and included in <code>app/assets/stylesheets/application.css</code></li>
<li>you put images in <code>app/assets/images/*</code></li>
<li>files for publishing are automatically created in <code>public/assets/*</code></li>
</ul>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-8' href='slides_assets_and_webpacker.html#/8'>◻</a></p>
<h3 id="webpacker"><a class="anchorlink" href="#webpacker"><span>2.3</span> Webpacker</a></h3><p>Since Rails 6 webpack and yarn are included with Rails.
These frontend tools are used to generate the JavaScript,
and can be used for other assets.</p><p>The gem that handles the setup of webpack is called <code>webpacker</code>,
you can find it in the <code>Gemfile</code>.</p><p>JavaScript packages are installed using <code>yarn install --check-files</code>. Just like
<code>npm</code>, <code>yarn</code> reads the list of packages to install form <code>package.json</code> and
installs them to the folder <code>node_modules</code>. The lockfile for <code>yarn</code> is called <code>yarn.lock</code>.
You should never find a <code>package-lock.json</code> file in your Rails folder.</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-9' href='slides_assets_and_webpacker.html#/9'>◻</a></p>
<h3 id="rails-environments"><a class="anchorlink" href="#rails-environments"><span>2.4</span> Rails Environments</a></h3><p>Building assets 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-10' href='slides_assets_and_webpacker.html#/10'>◻</a></p>
<h3 id="rails-environments-and-assets"><a class="anchorlink" href="#rails-environments-and-assets"><span>2.5</span> Rails Environments and Assets</a></h3><p>In <code>development</code> no assets will be written to <code>public/</code>. Instead
these files will be created on the fly by the Asset Pipeline and by <code>webpack-dev-server</code>.</p><p>If you look at the output of <code>rails s</code> or the logfile <code>log/development.log</code>
you will see messages from <code>webpack-dev-server</code> when this happens:</p><div class="interstitial code">
<pre><code class="highlight plaintext">[Webpacker] Compiling...
[Webpacker] Compiled all packs in /Users/bjelline/teach-dev/backend-assign/a4_job_board/public/packs
[Webpacker] Hash: 83233949a2f44e57ae52
Version: webpack 4.44.2
Time: 1345ms
Built at: 08.12.2020 19:36:18
Asset Size Chunks Chunk Names
js/application-cd9baa997ab2a6e5febb.js 70.9 KiB application [emitted] [immutable] application
js/application-cd9baa997ab2a6e5febb.js.map 80.2 KiB application [emitted] [dev] application
manifest.json 364 bytes [emitted]
Entrypoint application = js/application-cd9baa997ab2a6e5febb.js js/application-cd9baa997ab2a6e5febb.js.map
[./app/javascript/channels sync recursive _channel\.js$] ./app/javascript/channels sync _channel\.js$ 160 bytes {application} [built]
[./app/javascript/channels/index.js] 211 bytes {application} [built]
[./app/javascript/packs/application.js] 717 bytes {application} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 552 bytes {application} [built]
+ 2 hidden modules
</code></pre>
<button class="clipboard-button" data-clipboard-text="[Webpacker] Compiling...
[Webpacker] Compiled all packs in /Users/bjelline/teach-dev/backend-assign/a4_job_board/public/packs
[Webpacker] Hash: 83233949a2f44e57ae52
Version: webpack 4.44.2
Time: 1345ms
Built at: 08.12.2020 19:36:18
Asset Size Chunks Chunk Names
js/application-cd9baa997ab2a6e5febb.js 70.9 KiB application [emitted] [immutable] application
js/application-cd9baa997ab2a6e5febb.js.map 80.2 KiB application [emitted] [dev] application
manifest.json 364 bytes [emitted]
Entrypoint application = js/application-cd9baa997ab2a6e5febb.js js/application-cd9baa997ab2a6e5febb.js.map
[./app/javascript/channels sync recursive _channel\.js$] ./app/javascript/channels sync _channel\.js$ 160 bytes {application} [built]
[./app/javascript/channels/index.js] 211 bytes {application} [built]
[./app/javascript/packs/application.js] 717 bytes {application} [built]
[./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 552 bytes {application} [built]
+ 2 hidden modules
">Copy</button>
</div>
<p>When you deploy to production, the assets will be built and stored in <code>public/</code>.</p><p>If you look at the generated HTML code on the production server,
you will only find two links: 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 rel="stylesheet" media="all" href="/assets/application-1ea07225edcc7e47.css"/>
<script src="/assets/application-58af49959ef0.js"></script>
</code></pre>
<button class="clipboard-button" data-clipboard-text="<link rel="stylesheet" media="all" href="/assets/application-1ea07225edcc7e47.css"/>
<script src="/assets/application-58af49959ef0.js"></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_assets_and_webpacker.html#/11'>◻</a></p>
<h3 id="fingerprinting-for-better-expiry"><a class="anchorlink" href="#fingerprinting-for-better-expiry"><span>2.6</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> in development</li>
<li>and is part of <code>application-1ea07225edcc7e47.css</code> in production</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 concerning caching: 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_assets_and_webpacker.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><p>When you are using a PAAS to deploy your app there is no simple
way of storing uploaeded data: the <a href="https://12factor.net/build-release-run">release</a> cannot be
changed and should be deposable. You need a <a href="https://12factor.net/backing-services">backing service</a>
for storing files. This can be another cloud service like S3 (storage only) or <a href="https://cloudinary.com/">cloudinary</a> (storage and image processing)</p></div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-13' href='slides_assets_and_webpacker.html#/13'>◻</a></p>
<h2 id="using-webpacker-for-images-and-css"><a class="anchorlink" href="#using-webpacker-for-images-and-css"><span>4</span> Using webpacker for images and css</a></h2>
<ul>
<li><a href="https://stackoverflow.com/questions/57748953/importing-css-with-webpacker-in-rails-6#answer-57750067">CSS with Webpacker</a></li>
<li><a href="https://rossta.net/blog/importing-images-with-webpacker.html">Images with Webpacker</a></li>
</ul>
</div>
<div class='slide'>
<p class='slide_break_block'><a class='slide_break' id='slide-14' href='slides_assets_and_webpacker.html#/14'>◻</a></p>
<h2 id="further-reading"><a class="anchorlink" href="#further-reading"><span>5</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>