Trening na redukcję

jak spalić kilobajty

Trening na redukcję

jak spalić kilobajty

Paweł Kondraciuk

Hands on the orange typewriter in a park

Specyfikacja

Statystyki

źródło: Akamai 10For10, KissMetrics

Każda sekunda to

źródło: Amazon, Walmart, KissMetrics

To nie wszystko

Udziały urządzeń w internecie

źródło: StatCounter (2.5mln stron)

Czas pobierania 100KB

* Najczęściej stosowany lejek

Angular

4MB => 10min @ 3G

Co wpływa na szybkość ładowania strony

Minifikacja, obfuskacja i optymalizacja

Minifikacja - Webpack + UglifyJsPlugin

			new UglifyJsPlugin({
			  beautify: false,
        output: { comments: false },
        compress: {
          unused: true,
          dead_code: true
        }
      })
		

Angular + UglifyJs

1.5MB => 3:51min @ 3G

Analiza struktury aplikacji

Graph analyse

Analiza struktury aplikacji

No optimisation

Wszystko jest pakowane

			// maths.js
			export function square(x) { return x * x; }
			export function cube(x) { return x * x * x; }
			// main.js
			import { cube } from './maths.js';
			console.log(cube(5)); // 125
		
			function(module, exports) { // CommonJS
				Object.defineProperty(exports, "__esModule", {
					value: true
				});
				exports.square = square;
				exports.cube = cube;
				function square(x) {
					return x * x;
				}
				function cube(x) {
					return x * x * x;
				}
			}
		

Tree Shaking

Tree Shaking

Tree Shaking - Webpack

      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      options: {
        presets: [
          [ 'es2015', { modules: false } ] // default CommonJS
        ]
      }
		
			// ES6
			function(module, exports, __webpack_require__) {
				/* harmony export */ exports["cube"] = cube;
				/* unused harmony export square */;
				function square(x) {
					return x * x;
				}
				function cube(x) {
					return x * x * x;
				}
			}
		
Tree shaking

Angular + UglifyJs + Tree Shaking

1.3MB => 3:25min @ 3G

Prekompilacja (AoT)

Prekompilacja (AoT) - @ngtools/webpack

      let AotPlugin = require('@ngtools/webpack').AotPlugin;
			rules: [{ test: /\.ts/, use: '@ngtools/webpack' }]
			plugins: [
				new AotPlugin({
					tsConfigPath: path.resolve('tsconfig.json'),
					entryModule: path.resolve('app.module#AppModule')
				})
			]
		

Prekompilacja (AoT) - czego nie robić

Ahead of time

Angular + UglifyJs + Tree Shaking + AoT

0.9MB => 2:20min @ 3G

Kompresja GZip

			.selector { /* ... */ }
			.selector .child-selector { /* ... */ }
		
bootstrap.min.css 118KB
bootstrap.min.css.gz 19KB
Różnica 83,9%

compression-webpack-plugin

			new CompressionPlugin({
        regExp: /\.css$|\.html$|\.js$$/,
        threshold: 2 * 1024
      })
		
			AddOutputFilterByType DEFLATE text/javascript
			AddOutputFilterByType DEFLATE text/css
			AddOutputFilterByType DEFLATE text/html
		

Angular + UglifyJs + Tree Shaking + AoT + GZip

158KB => 0:24min @ 3G

Closure*

* Do codziennego użytku wystarczy UglifyJS

			function square(x) {
				return x * x;
			}
			function cube(x) {
				return x * x * x;
			}
			console.log(cube(5));
		
			console.log(125);
			
		

Spróbuj sam :)

Podsumowanie

Optymalizacja Waga Czas pobierania @ 3G
Brak 4186KB (100%) 10:47min
Minifikacja 1449KB (34,62%) 3:43min
Tree shaking 1315KB (31,41%) 3:23min
Prekompilacja 907KB (21,67%) 2:20min
Gzip 158KB (3,77%) 0:24min

Co wpływa na szybkość ładowania strony

			GET /index.html HTTP/1.1
			
		

HTTP/1.1: co najwyżej 2 równoczesne połączenia per host

Keep-Alive

			Keep-Alive: timeout=15, max=100
			
		

Nginx potrafi utrzymać 10 000 połączeń przy pomocy zaledwie 2,5 MB RAM

Cache

			GET /logo.png HTTP/1.1
			Expires: Tue, 17 May 2018 18:00:00 GMT
		

Google radzi: conajmniej miesiąc, zalecany rok.

Cache-control - polityka buforowania

public Przeglądarka klienta i serwery pośrednie
private Przeglądarka klienta
no-store Odpowiedzi nie wolno buforować

Cache - .htaccess

			<filesMatch ".(jpg|jpeg|png|gif|ico)$">
			Header set Cache-Control "max-age=31536000, public"
			</filesMatch>
			
			<filesMatch ".(css|js)$">
			Header set Cache-Control "max-age=2628000, public"
			</filesMatch>
		

Content Delivery Network

Podsumowanie

HSDPA, DL: 3.5Mb/s, UP: 2.1Mb/s, Waga: 525KB
Optymalizacja Czas dociagania
Brak ~0.8s - 0.9s
Keep-alive (timeout=10, max=499) ~0.5s - 0.65s
Cache ~0.08s-0.1s (165B)

Co wpływa na szybkość ładowania strony

Jak przeglądarka renderuje stronę

Optmalizacja HTML

Optymalizacja CSS

Optymalizacja obrazków

Optymalizacja JavaScript

Lazy loading

Lazy loading

			const routes: Routes = [
				{ path: '', component: Component },
				{ 
					path: 'lazy', 
					loadChildren: 'lazy/lazy.module#LazyModule'
				}
			];
		

Podsumowanie

Optymalizacja Czas skryptowania
Brak ~5s
Prekompilacja 3sek (907KB)
Lazy load ~600ms (525KB)

Ogólne podsumowanie

Optmalizacja Czas do wyrenderowania strony
Brak ~9s
+ optymalizacja połączenia ~6s - 8s
+ optymalizacja wagi ~5s - 6s
+ optymalizacja skryptowania ~1s

Linki

Pytania?