Today I will explain how to optimize HTML files reduce their sizes as possible.
We can achieve that by doing 3 things first minifying
then compressing
finally cache them
.
First, let me explain the difference between minify
and compress
.
-
Minify
: remove white spaces, comments, and unnecessary characters. - while
compressing
: the process of reducing the size of data (encoding information) using algorithms to compress ex gzip, deflate.
What happens between server and browser?
- browser request index.html file.
- server sends a
.zip
file to the browser(index.html.zip)
instead of the regularindex.html
version. - The browser then downloads the
zipped file
, extracts it, and then shows it to the user.
but how server know it’s OK to send the zipped one and not the regular index file???
They have an agreement with 2 parts:
1 -The browser sends a header telling the server it accepts compressed content (gzip and deflate are two compression schemes): Accept-Encoding: gzip, deflate
2- The server sends a response if the content is actually compressed: Content-Encoding: gzip
For more info read this great article.
I'm using gulp 4 as a task runner and browser-sync. So we will need the following packages.
- gulp-htmlmin to minify html files.
- gulp-gzip to compress html files.
- connect-gzip-static to enable us serve zipped HTML in local server for testing during dev.
a- minifying
:
1- install with npm:
npm install --save gulp-htmlmin
2- create minifyIndex
task to minify index
set options like remove comments and whitespace.
function minifyIndex() {
return src('./index.html')
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true }))
.pipe(dest('dist/'));
}
b- compressing
:
1- install with npm:
npm install --save-dev gulp-gzip connect-gzip-static
2- create compressIndex
task to compress index
file
function compressIndex() {
return src('./index.html')
.pipe(gzip())
.pipe(dest('dist/'));
}
3- serve compressed files for the local server
I tried to use the following method but it failed as middleware is too late in the stack when added via the options for .html files so the server didn't serve our zipped file
const compression= require('compression');
browserSync({
server: {
baseDir: './',
middleware: [compression()]
}
})
adding override boolean will cause this middleware to be applied to the FRONT of the stack as mentioned by Shane Osbourne here
function serveTask() {
// init browserSync
browserSync.init({
// setup server
server: {
baseDir: './dist/',
},
middleware: [
{
route: '', // empty 'route' will apply this to all paths
handle: gzipStatic('./dist/'), // the callable
override: true,
},
],
});
}
Note: you need also to add the regular index version as a fallback in case the server doesn’t send the content-encoding response header, which means the file is not compressed (the default on many servers).
function initIndexHtml() {
return src('./index.html')
.pipe(htmlmin({ collapseWhitespace: true, removeComments: true }))
.pipe(dest('dist/'));
}
after doing html optimization in my project I succeeded in reducing index file size from 21kb
to 3.5kb
Test if the compressed content is served:
1- open your site and developer tools.
2- open network tab check use large request rows to be able view size before and after optimization.
3- reload.
4- click as shown to display headers and response header 'Content-encoding: gzip'
.
Thanks for reading!
Hope this article helps, feel free to share it with your friends, any feedback will be appreciated :)
Top comments (0)