简介

网站加载的速度取决于浏览器必须下载的所有文件的大小。减少要传输的文件的大小可以使网站不仅加载更快,而且对于那些宽带是按量计费的人来说也更友好。

gzip是一种流行的数据压缩程序。您可以使用gzip压缩Nginx实时文件。这些文件在检索时由支持它的浏览器解压缩,好处是web服务器和浏览器之间传输的数据量更小,速度更快。

gzip不一定适用于所有文件的压缩。例如,文本文件压缩得非常好,通常会缩小两倍以上。另一方面,诸如JPEG或PNG文件之类的图像已经按其性质进行压缩,使用gzip压缩很难有好的压缩效果或者甚至没有效果。压缩文件会占用服务器资源,因此最好只压缩那些压缩效果好的文件。

在本指南中,我们将讨论如何配置安装在Ubuntu 16.04服务器上的Nginx,以利用gzip压缩,来减少发送给网站访问者的文件的大小。

vue-cli 打包vendor大如何处理

在写admin的时候项目地址
打包发现vendor.js特别大 如何提高用户体验呢

接下来我们看看怎么做

定位 webpack 大的原因

1
"analyz": "NODE_ENV=production npm_config_report=true npm run build"

尽量使用模块化引入

如果说 jQuery 确实没有引入必要,很多人会同意;但对于 lodash 这类依赖的工具,并不是所有人都会去造一发轮子的。然而全包引入 400kb 的体量,可否有让你心肝一颤?幸好的是,lodash 提供了模块化的引入方式;可按需引入,快哉快哉:

1
2
3
4
5
6
7
import { debounce } from 'lodash'
import { throttle } from 'lodash'

// 改成如下写法

import debounce from 'lodash/debounce'
import throttle from 'lodash/throttle'

擅懒如你的优秀程序员,是否也发现这样写颇为麻烦?那么恭喜你,这个问题已经被解决;lodash-webpack-plugin 和 babel-plugin-lodash 的存在(组合使用),即是解决这问题的。它可将全路径引用的 lodash, 自动转变为模块化按使用引入(如下例示);并且所需配置也十分简单,就不在此赘述(温馨提示:当涉及些特殊方法时,尚需些留意)。

1
2
3
4
// 引入组件,自动转换
import _ from 'lodash'
_.debounce()
_.throttle()

额外补充的是,即便采用如上写法,还是不够快捷,每个用到的文件,都写一遍 import,实在多有不便。更可取的是,将项目所需的方法,统一引入,按需添加,组建出本地 lodash 类库,然后 export 给框架层(比如 Vue.prototype),以便全局使用;详情可参见:vue-modular-import-lodash。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// helper 文件夹下 lodash,统一引入你需要的方法
import _ from 'lodash'

export default {
cloneDeep: _.cloneDeep,
debounce: _.debounce,
throttle: _.throttle,
size: _.size,
pick: _.pick,
isEmpty: _.isEmpty
}

// 注入到全局
import _ from '@helper/lodash.js'
Vue.prototype.$_ = _

// vue 组件内运用
this.$_.debounce()

按需异步加载模块

关于前端开发优化,重要的一条是,尽可能合并请求及资源,如常用的请求数据合并,压缩合并 js,构造雪碧图诸此等等(当然得适当,注意体积,过大不宜);但,同时也当因需制宜,根据需要去异步加载,避免无端就引入早成的浪费。webpack 也是内置对这方面的支持; 假如,你使用的是 Vue,将一个组件(以及其所有依赖)改为异步加载,所需要的只是把:

1
import Foo from './Foo.vue'

改写成

1
const Foo = () => import('./Foo.vue')

如此分割之时,该组件所依赖的其他组件或其他模块,都会自动被分割进对应的 chunk 里,实现异步加载,当然也支持把组件按组分块,将同组中组件,打包在同个异步 chunk 中。如此能够非常有效的抑制 Javascript 包过大,同时也使得资源的利用更加合理化。

生产环境,压缩混淆并移除console

现代化中等规模以上的开发中,区分开发环境、测试环境和生产环境,并根据需要予以区别对待,已然成为行业共识;可能的话,还会有预发布环境。对待生产环境,压缩混淆可以很有效的减小包的体积;同时,如果能够移除使用比较频繁的 console,而不是简单的替换为空方法,也是精彩的一笔小优化。如果使用 UglifyJsPlugin 插件来压缩代码,加入如下配置,即可移除掉代码中的 console:

1
2
3
4
5
6
7
8
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
drop_console: true,
pure_funcs: ['console.log']
},
sourceMap: false
})

依赖包

很多人发现自己引用的第三方依赖包特别多的时候vendor.js会打包的特别大

解决方法:

在config/index.js 中找到productionGzip 设置为true 并且安装 npm install –save-dev compression-webpack-plugin

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
const path = require('path')

module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: true,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: process.env.PORT || 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

接下来我们看看webpack.prod.conf 这里做了什么,会生成gz文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')

webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}

这样做就可以了吗,然而并不是 配合nginx

没有设置的效果Nginx响应头

1
2
3
4
5
6
7
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 19 Jan 2016 20:04:12 GMT
Content-Type: text/html
Last-Modified: Tue, 04 Mar 2014 11:46:45 GMT
Connection: keep-alive
Content-Encoding: gzip

在最后一行中,您可以看到Content-Encoding: gzip。这告诉我们gzip压缩已用于发送此文件。这是因为在Ubuntu 16.04上,Nginx的 gzip在安装后使用默认设置自动启用了压缩。

但是,默认情况下,Nginx仅压缩HTML文件。新安装中的每个其他文件都将以未压缩的形式提供。要验证这一点,您可以请求以test.jpg相同方式命名的测试图像。

1
curl -H "Accept-Encoding: gzip" -I http://localhost/test.jpg

结果应该与以前略有不同:

Nginx响应头

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 19 Jan 2016 20:10:34 GMT
Content-Type: image/jpeg
Content-Length: 0
Last-Modified: Tue, 19 Jan 2016 20:06:22 GMT
Connection: keep-alive
ETag: "569e973e-0"
Accept-Ranges: bytes

Content-Encoding: gzip没有输出,这意味着文件是在没有压缩的情况下提供。

您可以使用测试CSS样式表重复测试。

1
curl -H "Accept-Encoding: gzip" -I http://localhost/test.css

再一次,输出中没有提到压缩。

CSS文件的Nginx响应头

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 19 Jan 2016 20:20:33 GMT
Content-Type: text/css
Content-Length: 0
Last-Modified: Tue, 19 Jan 2016 20:20:33 GMT
Connection: keep-alive
ETag: "569e9a91-0"
Accept-Ranges: bytes

下一步是将Nginx配置支持其他类型文件的压缩。

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
server {
listen 80;
server_name vue.phalcon.app;
root /Users/limx/Applications/vue/dist;
index index.html index.htm;
client_max_body_size 8M;

proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Real-PORT $remote_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

gzip on;
gzip_static on;
gzip_min_length 1k;
gzip_buffers 16 64k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;

#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;

location / {
try_files $uri $uri/ /index.html$is_args$args;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}

# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}