优化站点:静态官网,由于租的阿里云的服务器配置低,带宽小,资源下载速度慢,打开网站需要的响应时间较长。
主要方式:浏览器展示的内容都需要从服务端下载,通过减少http请求次数和减少文件的体积,提高页面的响应速度。
测试工具:Google pageSpeed(访问需要线上地址,需要科学上网工具)

一个请求过程:浏览器提交URL,dns解析成ip地址,tcp连接,http请求,经过网关,服务器返回资源,前端处理。

这里主要提到的是浏览器缓存和前端资源的优化。

一.浏览器缓存

主要是HTTP协议定义的缓存机制,当页面资源被缓存后,页面再次请求资源时,会先从缓存获取资源,缓存不存在再从服务器获取。

1.浏览器缓存机制

缓存状态会表现在http协议的header中,header中常见的有四种:

  • Expires
  • Cache-Control
  • Last-modified(if-modified-since)
  • Etag(if-none-match)

ps:MDN http headr

1.Expires

Expires头是HTTP1.0中定义的,指定了一个日期/时间,这是一个绝对时间,在Response中显示,在这个日期/时间之后,HTTP响应被认为是过时的。当请求头中存在cache-control时,忽略expires

1
2
3
4
#语法:
Expires: <http-date> # http-date是一个HTTP-date时间戳
#示例:
Expires: Wed, 21 Oct 2015 07:28:00 GMT

2.Cache-Controle

Cache-Control头是HTTP1.1中定义的,(general header)通用首部,即可应用与Request也可应用与Response,通过指定指令来实现缓存机制。缓存指令是单向的, 这意味着在请求设置的指令,在响应中不一定包含相同的指令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#语法:
## 请求
Cache-Control: max-age=<seconds>
Cache-Control: max-stale[=<seconds>]
Cache-Control: min-fresh=<seconds>
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: only-if-cached
## 响应
Cache-control: must-revalidate
Cache-control: no-cache
Cache-control: no-store
Cache-control: no-transform
Cache-control: public
Cache-control: private
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>
Cache-control: s-maxage=<seconds>
示例:
Cache-control: 3600;

3.Last-modified(if-[un]modified-since)

Last-Modified是一个header Response,其中包含源头服务器认定的资源做出修改的日期及时间。它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比ETag要低,所以这是一个备用机制。当header Request包含有If-Modified-Since或If-Unmodified-Since条件时,会在响应中使用这个字段。

1
2
3
4
语法:
Last-Modified: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
示例:
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

4.Etag(if[-none]-match)

ETag是一个header Response,是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容过期但内容没有改变,Web服务器不需要发送完整的响应。而如果内容发生了变化,使用ETag有助于防止资源的同时更新相互覆盖(“空中碰撞”)。

如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。

1
2
3
4
5
6
语法:
ETag: W/"<etag_value>"
ETag: "<etag_value>"
示例:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
ETag: W/"0815"

2.nginx实现

1.配置缓存

在nginx中匹配相应的资源,通过expires字段添加缓存时间

1
2
3
4
5
6
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
expires 30d;
}
location ~ .*\.(js|css)?$ {
expires 1h;
}

2.配置gzip

开启gzip,gzip(GNU-ZIP)是一种压缩技术,服务器端压缩,传到浏览器后浏览器解压并解析,减小传输体积,提高传输速度。

1
2
3
4
5
6
7
8
9
10
## `gzip` Settings
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;

二.前端构建工具

1.gulp

尝试选用gulp前端构建工具构建项目。相比于webpack的完整强大,gulp相对小巧。

准备:

  • node
  • npm

安装:

  • 全局安装gulp
1
$ npm install --global gulp
  • 添加项目依赖
1
2
$ cd /path/your/project
$ npm install --save-dev gulp #生成pageage.json文件
  • 创建gulpfile.js文件
1
$ touch gulpfile.js

开发:

gulp以链式方式编程,通过pipe函数连接,从源目录,中途经过插件处理生成处理后文件存放到目标目录。例:

  • gulp.task(name[, deps], fn)
1
2
3
4
5
6
7
// 格式
gulp.task('sth', function() {
return gulp.src('your/assert/path')
.pipe([plugin]())
...
.pipe(gulp.dest('dist/path'))
})
  • 终端执行
1
gulp sth

ps:gulp文档

2.gulp实现

  • 安装插件
1
2
# 压缩css,js,html,image
$ npm install --save-dev gulp-minify-css gulp-uglify gulp-imagemin gulp-htmlmin gulp-rename gulp-cache gulp-concat
  • gulpfile.js
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
var gulp = require('gulp')
// 引入 gulp及组件
var gulp = require('gulp'),
autoprefixer = require('gulp-autoprefixer'),
minifycss = require('gulp-minify-css'), //压缩css
uglify = require('gulp-uglify'), //压缩JS
imagemin = require('gulp-imagemin'), //压缩图片
rename = require('gulp-rename'), //合并js文件
concat = require('gulp-concat'),
cache = require('gulp-cache'),
htmlmin = require('gulp-htmlmin'),
del = require('del');
gulp.task('html', function () {
var options = {
removeComments: true,//清除HTML注释
collapseWhitespace: true,//压缩HTML
collapseBooleanAttributes: true,//省略布尔属性的值 <input checked="true"/> ==> <input />
removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
removeScriptTypeAttributes: true,//删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true,//删除<style>和<link>的type="text/css"
minifyJS: true,//压缩页面JS
minifyCSS: true//压缩页面CSS
};
gulp.src('./index-src.html')
.pipe(htmlmin(options))
.pipe(rename('index.html'))
.pipe(gulp.dest('./'));
});
// Styles
gulp.task('css', function() {
return gulp.src('./statics/css/*.css')
// .pipe(rename({ suffix: '.min' }))
.pipe(minifycss())
.pipe(gulp.dest('./dist/css'));
});
// Scripts
gulp.task('js', function() {
return gulp.src('./statics/js/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist/js'));
});
// Images
gulp.task('img', function() {
return gulp.src(['./statics/img/*', './statics/case_img/*'])
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest('dist/img'));
});
// Clean 任务执行前,先清除之前生成的文件
gulp.task('clean', function(cb) {
del(['dist/css', 'dist/js', 'dist/img'], cb)
});
// Default task 设置默认任务
gulp.task('default', ['clean', 'css', 'js', 'img', 'html'], function() {
// gulp.start('css', 'js', 'img');
});

—-完—-