zoukankan      html  css  js  c++  java
  • 再谈 webpack build 及 加载优化

    之前项目多,事情忙,一直没时间写博客,现在空闲下来了,总结一下

    之前讲过了关于 build 压缩文件的方法,有兴趣的可以看下: 点击查看

    现在讲讲一个页面的首屏加载速度该如何提升

    提前说明 需要 webpack-bundle-analyzer 插件来进行 build 文件的分析

    异步文件和必须文件

    首先是异步文件,可以按功能分,也可以按照路由分块,目的就是尽量较少首次加载的必须代码的大小
    即登录,注册和必须存在的组件是必须加载组件,优先度最高,这些组件是不能为异步的,其他尽量都要设置为异步组件

    如果你的项目足够小,一个 main 文件总共200k 那么可以不使用分块(仅限 web 端,移动端另说)

    因为我使用的是 react+antd 还有一些附带的大包 如 immutable,moment,babel-polyfill等,而且最重要的是这些包是必须的,大小快接近1M了

    当然我是不会将接近 1M 的必需文件放在一个加载包里的,这样的话首屏加载恐怕要2S以上了

    这个时候 webpack 的分块功能就出来了

    一般来说 浏览器的并发数量是6个资源,webpack 生成文件呢,至少会有一个 css 文件会在 head 加载;

    去除 css 剩余5个位置 1000k/5 = 200k 所以 将 1000k 的必需文件包平均分成5分,并发加载
    速度即可缩短至 1/5 (当然这是理想状态)

    简单解释一下: 1个人搬10公斤货物,需要 1个小时,但是现在一个线程就是一个人,就变成了5个人搬10公斤货物,速度就只要20分钟了

    现在简介一下 webpack3 和 webpack4 该怎样分块:

    webpack3:

        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor',
          minChunks(module) {
            return (
              module.resource &&
              /.js$/.test(module.resource) &&
              !new RegExp('/antd/lib|/react-dom|/moment').test(module.resource) &&
              module.resource.indexOf(
                path.join(__dirname, '../node_modules')
              ) === 0
            )
          }
        })
    

    类似于这样 RegExp 中的表示不会被加到这个包中,有一点需要注意,剩余的会自动加在默认包里,所以我前面才会说 需要 webpack-bundle-analyzer;
    因为想要达到最佳状态,需要根据插件的页面多次试验分块

    webpack4:

        splitChunks: {
          cacheGroups: {
            vendor: {
              test(chunks){
                return !new RegExp('/antd/lib|/react-dom|/moment').test(chunks.context) &&  /[\/]node_modules[\/]/.test(chunks.context)
              },
              name: "vendor",
              chunks: "all",
              reuseExistingChunk: true
            }
          }
        }
    

    webpack4 和 3 的道理差不多,只是格式不一样罢了


    prefetch , preload ,dns-prefetch

    这两个的作用,虽然网上现在也是一搜一大把,我还是在这里说下他的作用和我简单的心得和体会

    preload

    表示浏览器一检测到该条脚本就会对服务器进行请求,通常会写在上部,因为越先检测就越先加载

    prefetch

    表示浏览器一检测到该条脚本就会在空闲的时候,下载脚本,并缓存到disk

    dns-prefetch

    表示浏览器一检测到该条脚本就会解析CDN的地址的DNS放的位置越前越好

    所以他们分别作用的块是这样的:

    • 必须模块和 cdn 模块需要的是preload
    • 异步模块需要的是 prefetch 记住最好是所有异步模块都加上
    • 使用dns-prefetch前提是你必须先知道域名是什么,而且更换域名时也要同步更换,效果立竿见影,加快页面加载时间

    下面放上一个标准使用方法:

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>title</title>
      <link rel="dns-prefetch" href="//www.grewer.cn/">
      <link rel="preload" as="script" href="/static/js/module1.js" >
      <link rel="preload" as="script" href="/static/js/module2.js">
      <link rel="preload" as="script" href="/static/js/module3.js">
      <link rel="preload" as="style" href="/static/css/main.css">
      <link rel="prefetch" href="/static/js/async1.chunk.js">
      <link rel="prefetch" href="/static/js/async2.chunk.js">
      <link rel="prefetch" href="/static/js/async3.chunk.js">
      <link rel="prefetch" href="/static/js/async4.chunk.js">
      <link rel="prefetch" href="/static/js/async5.chunk.js">
      <link rel="prefetch" href="/static/js/async6.chunk.js">
      <link href="/static/css/main.css" rel="stylesheet">
    </head>
    <body>
    
    <script type="text/javascript" src="/static/js/module1.js" ></script>
    <script type="text/javascript" src="/static/js/module2.js" ></script>
    <script type="text/javascript" src="/static/js/module3.js" ></script>
    </body>
    </html>
    

    http2 服务器推送

    http2出来大概3年了吧,大多数人都以为他的作用就是加密就 HTTPS 而已,其实他还有一个最重要的功能,服务器推送

    服务器推送的基础是 HTTP2,所以需要先升级 然后需要再服务器配置,一旦有客服端请求文件,如 index.html
    就可以将文件立马推送,而且关键还是他没有并发限制,比如图片,你可以一下子推送10个,20个,任意个文件! 只有客户端需要的

    效果如下:
    服务器推送效果
    (图片来自网络,如果挂了还请自行寻找)
    但是配合 webpack 还有一个问题,就是 webpack 生成的文件会带有 hash 参数,比如这样的文件名: /static/js/system.9b7a5941.chunk.js
    要推送文件需要知道文件的名称(也许可以自动化,但是我不怎么了解)

    这个问题的解决就交给大家了

    不过即使没有服务器推送,有 preload也是十分好用了

    结语

    减小请求时间的方法有很多,还请大家酌情使用

  • 相关阅读:
    javaweb中如何给自己的网站更改ico图标
    基于Zookeeper的分布式锁
    Linux 基础——权限管理命令chmod
    Java--实现单点登录
    Session和Cookie的区别与联系
    selectedIndex返回被选中的option的index.
    onchange事件可以使用于: <input>, <select>, 和 <textarea>。
    js判断字符串长度
    在容器最前面添加DOM元素 parent.insertBefore(new, parent.children[0])
    在容器末尾添加DOM元素 parent.appendChild(newChild)
  • 原文地址:https://www.cnblogs.com/Grewer/p/9877687.html
Copyright © 2011-2022 走看看