web下的性能优化1(网络方向)

2020-4-20    seo达人

性能优化(网络方向)

web应用无非是两台主机之间互相传输数据包的一个过程; 如何减少传输过程的耗时就是网络方向优化的重点, 优化出发点从第一篇文章中说起


DNS解析过程的优化

当浏览器从第三方服务跨域请求资源的时候,在浏览器发起请求之前,这个第三方的跨域域名需要被解析为一个IP地址,这个过程就是DNS解析;

DNS缓存可以用来减少这个过程的耗时,DNS解析可能会增加请求的延迟,对于那些需要请求许多第三方的资源的网站而言,DNS解析的耗时延迟可能会大大降低网页加载性能。


dns-prefetch

当站点引用跨域域上的资源时,都应在<head>元素中放置dns-prefetch提示,但是要记住一些注意事项。首先,dns-prefetch仅对跨域域上的DNS查找有效,因此请避免将其用于您当前访问的站点


<link rel="dns-prefetch" href="https://fonts.googleapis.com/">

preconnect

由于dns-prefetch仅执行DNS查找,但preconnect会建立与服务器的连接。如果站点是通过HTTPS服务的,则此过程包括DNS解析,建立TCP连接以及执行TLS握手。将两者结合起来可提供机会,进一步减少跨源请求的感知延迟


<!-- 注意顺序, precontent和dns-prefetch的兼容性 -->

<link rel="preconnect" href="https://fonts.googleapis.com/" crossorigin>

<link rel="dns-prefetch" href="https://fonts.googleapis.com/">

TCP传输阶段优化

这个前端方面好像能做的有限, 我们都知道 http协议 是基于 tcp的;

升级http协议版本可以考虑下, 比如把 http/1.0 -> http/1.1 -> http/2;

这个需要我们在应用服务器上配置(nginx, Apache等), 不做概述了, 另外还需要客户端和服务器都支持哦, 目前还没开发出稳定版本,好多只支持https,不过也不远了...


http2 的优势

#  1.多路复用: 同一个tcp连接传输多个资源

这样可以突破统一域名下只允许有限个tcp同时连接,

这样http1.1所做的减少请求数优化就没有太大必要了

如多张小图合成一张大图(雪碧图),合并js和css文件


# 2.报文头压缩和二进制编码: 减少传输体积

http1 中第一次请求有完整的http报文头部,第二次请求的也是;

http2 中第一次请求有完整的http报文头部,第二次请求只会携带 path 字段;

这样就大大减少了发送的量。这个的实现要求客户端和服务同时维护一个报文头表。


# 3.Server Push

http2可以让服务先把其它很可能客户端会请求的资源(比如图片)先push发给你,

不用等到请求的时候再发送,这样可以提高页面整体的加载速度

但目前支持性不太好...emm...

总的来说, 在 c 端业务下不会太普及, 毕竟需要软件支持才行...


http 请求响应阶段优化

为了让数据包传输的更快, 我们可以从两个方面入手: 请求的数据包大小(服务器), 请求数据包的频率(客户端)


减少请求文件的大小

请求文件对应的是我们项目完成后,打包所指的静态资源文件(会被部署到服务器), 文件越小, 传输的数据包也会相对较小, 讲道理也会更快到达客户端


how to reduce a package size?

目前我们都会使用打包工具了(比如webpack, rollup, glup 等), 如何使用工具来减小包的体积呢? 这边建议您去官网文档呢...当然这里列举一下常用的手段(webpack 的), 但是注意要插件版本更新哦


JS文件压缩

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

module.exports = {

plugins: [

  new UglifyJsPlugin({

    // 允许并发

    parallel: true,

    // 开启缓存

    cache: true,

    compress: {

      // 删除所有的console语句    

      drop_console: true,

      // 把使用多次的静态值自动定义为变量

      reduce_vars: true,

    },

    output: {

      // 不保留注释

      comment: false,

      // 使输出的代码尽可能紧凑

      beautify: false

    }

  })

]

}

CSS 文件压缩

// optimize-css-assets-webpack-plugin

plugins: [

 new OptimizeCSSAssetsPlugin({

   assetNameRegExp: /\.css$/g,

   cssProcessor: require('cssnano'),

 }),

];

html 文件压缩

// html-webpack-plugin

plugins: [

 new HtmlWebpackPlugin({

   template: path.join(__dirname, 'src/index.html'),

   filename: 'index.html',

   chunks: ['index'],

   inject: true,

   minify: {

     html5: true,

     collapseWhitespace: true,

     preserveLineBreaks: false,

     minifyCSS: true,

     minifyJS: true,

     removeComments: false,

   },

 }),

];

source map 文件关闭

tree shaking

1.代码不会被执行,不可到达,比如 if(false){// 这里边的代码}

2.代码执行的结果不会被用到

3.代码只会影响死变量(只写不读)

4.方法不能有副作用


// 原理相关: 以后在研究

利用 ES6 模块的特点:

 只能作为模块顶层的语句出现

 import 的模块名只能是字符串常量

 import binding 是 immutable 的

代码擦除: uglify 阶段删除无用代码

scope hoisting(作用域提升)

分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗余


const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin');

module.exports = {

 resolve: {

   // 针对 Npm 中的第三方模块优先采用 jsnext:main 中指向的 ES6 模块化语法的文件

   mainFields: ['jsnext:main', 'browser', 'main']

 },

 plugins: [

   // 开启 Scope Hoisting

   new ModuleConcatenationPlugin(),

 ],

};

项目中使用按需加载,懒加载(路由,组件级)

const router = new VueRouter({

 routes: [

   { path: '/foo', component: () => import(/* webpackChunkName: "foo" */ './Foo.vue') }

   { path: '/bar', component: () => import(/* webpackChunkName: "bar" */ './Bar.vue') }

 ]

})

开启 gizp 压缩

有时候启用也会消耗服务器性能, 看情况使用吧

暂时先提这么些吧...后续想到了再加


减少请求频率

因为同一域名下 tcp 连接数的限制导致过多的请求会排队阻塞, 所以我们需要尽量控制请求的数量和频率


常见措施

将静态资源的内联到HTML中

这样这些资源无需从服务器获取, 但可能影响到渲染进程...


<!-- 1.小图片内联 base64 (url-loader) -->

<!-- 2.css内联 -->

<!-- 3.js内联 -->

<script>

 ${require('raw-loader!babel-loader!./node_modules/lib-flexible/flexible.js')}

</script>

利用各级缓存(下一篇存储方面介绍)

通常都是在服务端做相关配置, 但你要知道


我们可以利用http缓存(浏览器端)来减少和拦截二次请求, 当然一般都是在服务端设置的;

服务器端也可以设置缓存(redis等), 减少数据查询的时间同样可以缩短整个请求时间

利用本地存储

我们可以将常用不变的信息存在本地(cookie,storage API 等);

判断存在就不去请求相关的接口, 或者定期去请求也是可以的

花钱买 CDN 加速

CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速资源的获取速度。 CDN 其实是通过优化物理链路层传输过程中的网速有限、丢包等问题来提升网速的...


购买 cdn 服务器;

然后把网页的静态资源上传到 CDN 服务上去,

在请求这些静态资源的时候需要通过 CDN 服务提供的 URL 地址去访问;


# 注意, cdn 缓存导致的新版本发布后不生效的问题

所以打包的时候常在文件后面加上 hash 值

然后在 HTML 文件中的资源引入地址也需要换成 CDN 服务提供的地址

/alicdn/xx12dsa311.js


# 利用不同域名的 cdn 去存放资源, (tcp连接限制)

webpack 构建时添加 cdn

// 静态资源的导入 URL 需要变成指向 CDN 服务的绝对路径的 URL 而不是相对于 HTML 文件的 URL。

// 静态资源的文件名称需要带上有文件内容算出来的 Hash 值,以防止被缓存。

// 不同类型的资源放到不同域名的 CDN 服务上去,以防止资源的并行加载被阻塞。

module.exports = {

 // 省略 entry 配置...

 output: {

   // 给输出的 JavaScript 文件名称加上 Hash 值

   filename: '[name]_[chunkhash:8].js',

   path: path.resolve(__dirname, './dist'),

   // 指定存放 JavaScript 文件的 CDN 目录 URL

   publicPath: '//js.cdn.com/id/',

 },

 module: {

   rules: [

     {

       // 增加对 CSS 文件的支持

       test: /\.css$/,

       // 提取出 Chunk 中的 CSS 代码到单独的文件中

       use: ExtractTextPlugin.extract({

         // 压缩 CSS 代码

         use: ['css-loader?minimize'],

         // 指定存放 CSS 中导入的资源(例如图片)的 CDN 目录 URL

         publicPath: '//img.cdn.com/id/'

       }),

     },

     {

       // 增加对 PNG 文件的支持

       test: /\.png$/,

       // 给输出的 PNG 文件名称加上 Hash 值

       use: ['file-loader?name=[name]_[hash:8].[ext]'],

     },

     // 省略其它 Loader 配置...

   ]

 },

 plugins: [

   // 使用 WebPlugin 自动生成 HTML

   new WebPlugin({

     // HTML 模版文件所在的文件路径

     template: './template.html',

     // 输出的 HTML 的文件名称

     filename: 'index.html',

     // 指定存放 CSS 文件的 CDN 目录 URL

     stylePublicPath: '//css.cdn.com/id/',

   }),

   new ExtractTextPlugin({

     // 给输出的 CSS 文件名称加上 Hash 值

     filename: `[name]_[contenthash:8].css`,

   }),

   // 省略代码压缩插件配置...

 ],

};

/*

以上代码中最核心的部分是通过 publicPath 参数设置存放静态资源的 CDN 目录 URL,

为了让不同类型的资源输出到不同的 CDN,需要分别在:


output.publicPath 中设置 JavaScript 的地址。

css-loader.publicPath 中设置被 CSS 导入的资源的的地址。

WebPlugin.stylePublicPath 中设置 CSS 文件的地址。

设置好 publicPath 后,WebPlugin 在生成 HTML 文件和 css-loader 转换 CSS 代码时,会考虑到配置中的 publicPath,用对应的线上地址替换原来的相对地址。

*/

参考

DNS MDN]

webpack 文档

深入浅出 Webpack

Scope Hoisting



分享本文至:

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档