About me:
CTO & Co-founder naustud.io
Front End Architect goalify.plus
Contact me:
Website: int3ractive.com
Github, Twitter, Facebook: @trongthanh
Today's discussion:
How to make your web apps load fast
“Amazon's calculated page load slowdown of just 01 second could cost it $1.6 billion in sales each year”
from entering URL on address bar to full rendered page
devtool network timing
DNS Lookup
Initial Connection
Time to First Byte (TTFB)
Content Download
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Page title</title>
<link rel="stylesheet" href="/css/global.min.css">
<link rel="stylesheet" href="/css/page.min.css">
<script src="/js/vendor.min.js"></script>
<script src="/js/main.min.js"></script>
</head>
<body>
<!-- HTML markups here -->
</body>
</html>
Typical SPA's downloaded HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Single Page Application</title>
<link rel="stylesheet" href="/app.min.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/...">
</head>
<body>
<div id="app"></div>
<script src="/bundle.min.js"></script>
</body>
</html>
Common performance problems with SPA:
User-centric performance metrics
First Paint -> First Contentful Paint -> First Meaningful Paint -> Time to Interactive
FP -> FCP -> FMP -> TTI
SPA page speed optimization target:
Reduce JS bundle size
What is common among Angular, React, Vue?
Webpack
if (PRODUCTION) {
config.plugins = config.plugins.concat([
new webpack.optimize.UglifyJsPlugin({
beautify: false,
mangle: {
screw_ie8: true,
keep_fnames: true,
},
compress: {
screw_ie8: true,
drop_debugger: true,
drop_console: true,
},
output: {
comments: false,
},
sourceMap: !PRODUCTION,
}),
]);
}
rules: {
test: /\.s?css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {/*...*/},
}, {
loader: 'postcss-loader',
options: {/*...*/},
}, {
loader: 'sass-loader',
options: {/*...*/},
},
],
}),
},
plugins: [
new ExtractTextPlugin('styles/styles-[chunkhash].css'),
]
const config = {
entry: {
vendor: [
'classnames',
'dom-helpers',
'moment',
'react',
'react-dom',
'react-prop-types',
'react-router',
'jquery',
/*...*/
],
},
output: {
filename: 'vendor.js',
path: path.join(__dirname, buildPath),
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: `${buildPath}vendor-manifest.json`,
}),
],
}
<Route path="achievement" getComponent={(nextState, cb) => {
showModuleLoading();
import(/* webpackChunkName: "views/admin/achievement" */ './views/admin/AdminCoreValuePage' )
.then(PageComp => {
showModuleLoading.cancel();
AppActions.toggleLoading(false);
return cb(null, PageComp.default);
});
}}
/>
Lazy loaded route component with dynamic import
$ npm install --global webpack-bundle-analyzer
$ webpack --profile --json > stats.json
$ webpack-bundle-analyzer stats.json
// utils.js
// instead of this:
export default const utils = {
trim() {/*...*/},
format() {/*...*/},
}
// do this:
export function trim() {/*...*/};
export function format() {/*...*/};
// Ends up pulling in everything.
import { truncate } from 'lodash';
// Just pull in the module we're interested in.
import truncate from 'lodash-es/truncate';
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
]
date-fns
import {format, parse} from 'date-fns/esm';
<link rel="preload" href="/page/index.js" as="script"/>
<link rel="preload" href="/page/_error.js" as="script"/>
<link rel="preload" href="/app.js" as="script"/>
Preload common chunks and next page JS bundle for faster transition to next page
Can we make critical rendering path works for SPA?
Client only Redux architecture
Universal Redux architecture
That's all folks!
How do we audit our optimization effort?
What we discussed was only part of
Front End Optimization
To be continued...