压缩静态文件提高页面访问速度

yasuo
网站上线后,发现在移动环境下访问速度比较慢,于是做了一些优化的措施。其中一项是压缩了静态文件,减少了连接数和传输大小,效果比较明显

有一个关键点是,不能影响开发的便利性。在开发阶段,引用未经压缩的资源文件,对js和css文件的修改马上就能体现出来,方便修改和调试。而在部署时,则要引用压缩后的js,达到性能优化的目的。所以同一个页面,在开发阶段和部署阶段引用的静态文件资源是不同的,而且对开发人员是透明的

压缩和合并静态文件

主要用了grunt的2个插件:uglify和cssmin,可以把js和css文件压缩以及合并

uglify

cssmin

Gruntfile的写法见下面的附录,仅供参考

区分开发态和部署态

主要思路是,在配置文件中用env字段标识当前的环境是dev和production,然后在ejs里读取这个标识,来引用不同的资源文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<% if(env === "dev"){ %>

<%- Loader()
.js("/3rd-lib/WeixinApi.js")
.js("/3rd-lib/zepto.min.js")
.js("/resource/wechat_global.js")
.css("/resource/css/base.css")
.css("/resource/css/wechat.css")
.done(config) %>

<% }else{ %>

<%- Loader()
.js("/3rd-lib/wechat-global.min.js")
.css("/resource/css/wechat.min.css")
.done(config) %>

<% } %>

开发的时候,用dev方式启动;部署的时候用production方式启动,对开发人员完全是透明的

Gruntfile参考

比较长,仅供参考。实际还是要结合自己项目的目录结构和需求来写

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
module.exports = function (grunt) {

var sourceDir = "src";// 源码目录
var frontDir = "frontend";// 前端目录
var serverDir = "webapps";// 后端目录
var distDir = "dist";// 最终交付目录

// 从src拷贝到部署目录时,去掉中间的static路径
function clipStaticPath(dest, src){
var arr = src.split("/");
arr.splice(1, 1);
var splicePath = arr.join("/");
return dest + "/" + splicePath;
}

var thirdJSFiles = {};

thirdJSFiles[frontDir + "/3rd-lib/wechat-global.min.js"] = [
sourceDir + "/3rd-lib/*.js",
sourceDir + "/resource/*.js"
];

var globalCSSFiles = {};
globalCSSFiles[frontDir + "/resource/css/wechat.min.css"] = [sourceDir + "/resource/css/*.css"];

grunt.initConfig({

uglify: {
build: {
options: {
mangle: true
},
files: [
{
expand: true,
flatten: false,
cwd: sourceDir,
src: ["**/static/**/*.js"],
filter: "isFile",
dest: frontDir,
ext: ".min.js",
rename: clipStaticPath
}
]
},
thirdjs: {
options: {
mangle: true
},
files: thirdJSFiles
}
},
cssmin: {
global: {
files: globalCSSFiles
},
build: {
files: [
{
expand: true,
flatten: false,
cwd: sourceDir,
src: ["**/static/css/**/*.css"],
dest: frontDir,
ext: ".min.css",
rename: clipStaticPath
}
]
}
},
copy: {
frontend: {
files: [
{
expand: true,
flatten: false,
cwd: sourceDir,
src: ['resource/**/*.jpg', 'resource/**/*.png'],
filter: 'isFile',
dest: frontDir
}
]
},
server: {
files: [
{
expand: true,
flatten: false,
cwd: sourceDir,
src: ['**/*', '!**/test/**/*', '!**/static/**/*', "!3rd-lib/**/*", "!resource/**/*"],
filter: 'isFile',
dest: serverDir
}
]
},
dist: {
files: [
{
expand: true,
flatten: false,
src: ['conf/**/*', frontDir + '/**/*', serverDir + '/**/*', 'package.json'],
dest: distDir
}
]
}
},
mkdir: {
build: {
options: {
mode: 0777,
create: [distDir + '/logs', distDir + '/public']
}
}
},
clean: {
build: [frontDir, serverDir]
}
});

grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-mkdir');
grunt.loadNpmTasks('grunt-contrib-clean');

grunt.registerTask('default', ['uglify', 'cssmin', 'copy', 'mkdir', 'clean']);
};