zoukankan      html  css  js  c++  java
  • vue项目优化

    代码压缩
    代码压缩值得是文件级别的压缩,类似于你用的winrar以及好压等压缩工具来压缩的结果。压缩的文件一般以.gz结尾。比如:app.ea467643.js.gz。
    服务端压缩
    以nginx为例,找到配置文件,添加如下配置即可

    server {
      gzip on;
      gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
      ...
    }

    开启前,文件大小1.7MB

    开启后,文件大小646Kb

    如何确定,后端返回的是压缩过的文件
    如果服务器对资源进行压缩编码了,它就会通过响应头Content-Encoding告知当前请求用了什么编码格式,当然如果服务器没干这事,则不会返回这个响应头,比如某个请求用gzip压缩了返回的内容

    客户端压缩
    webpack打包时直接使用gzip压缩。
    返回内容是在请求服务器的时候使用gzip进行动态压缩。这样存在的问题时,对于同一个资源的不同请求,反复压缩,这无疑会增加服务器的CPU和内存消耗。使用webpack去提前压缩好,然后让后端服务器拿去用现成压缩好的,则就可以避免这个问题。
    安装压缩工具包

    npm install compression-webpack-plugin --save-dev

    在vue.config.js里配置如下(其实就是在配置webpack)

    const CompressionPlugin = require('compression-webpack-plugin');
    const compressionPlugin = new CompressionPlugin({
      test: /.(js|css)?$/i, // 哪些文件要压缩
      filename: '[path].gz[query]',// 压缩后的文件名
      algorithm: 'gzip',// 使用gzip压缩
      minRatio: 1,// 压缩率小于1才会压缩
      deleteOriginalAssets: false // 删除未压缩的文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false
    })
    
    module.exports = {
      configureWebpack:{ // 配置压缩gz插件
        plugins:[compressionPlugin]
      }
    };

    然后配置nginx.conf
    gzip_static设置为on之后,这样在访问资源的时候,如果存在“资源路径.gz”的文件,则会直接返回该文件,其优先级高于动态的gzip。

    server {
        ...
        gzip on;
        gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
        gzip_static on;
    }

    最后重启服务器,刷新页面就可以看到效果了。

    类库不打包,引用外部模块
    在 webpack 里有个 externals,可以忽略不需要打包的库。这样,就大大减少了chunk-vendors包的体积。
    防止将某些 import 的包 ( package ) 打包到 bundle 中,而是在运行时 (runtime ) 再去从外部获取这些扩展依赖 ( external dependencies )。
    即webpack外部扩展,依赖前置。利用cdn加速
    这是没有使用外部模块前的体积,1.7MB

    这是使用之后的,43kb

    使用配置如下
    在vue.config.js中

    module.exports = {
      configureWebpack:{
        externals: {  // 使用外部资源
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'vuex': 'Vuex',
          'axios': 'axios',
          'echarts': 'echarts',
          'element-ui':'ELEMENT',
          'lodash': '_',
          'dayjs': 'dayjs'
        }
      }
    };

    在public/index.html中,配置如下

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.2.0/vuex.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.1.3/vue-router.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.7.0/echarts.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/index.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.8.27/dayjs.min.js"></script>
        <title>xxx</title>
      </head>
      <body>
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>

    其他注意的
    开发环境下是不需要如上这些配置的,所以如果追求极致,可以额外判断一下
    index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="icon" href="<%= BASE_URL %>favicon.ico">
        <% if(NODE_ENV==='production'){ %>
          <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.2.0/vuex.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.1.3/vue-router.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.7.0/echarts.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/index.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
          <script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.8.27/dayjs.min.js"></script>
        <% } %>
        <title>xxx</title>
      </head>
      <body>
        <noscript>
          <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
        </noscript>
        <div id="app"></div>
        <!-- built files will be auto injected -->
      </body>
    </html>
    View Code

    vue.config.js

    externals: process.env.NODE_ENV === 'production'?{  // 使用外部资源(开发环境下不用这个)
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'vuex': 'Vuex',
          'axios': 'axios',
          'echarts': 'echarts',
          'element-ui':'ELEMENT',
          'lodash': '_',
          'dayjs': 'dayjs'
    }:{}
    View Code

    打包分析工具
    在如上的讲解中,都是通过network来分析查看,工具出库前后包大小,请求时长的对比。实际上,有个专业的工具包来做此事,那就是BundleAnalyzerPlugin。
    是一个webpack的插件,使用也很简单。

    const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
    const bundleAnalyzerPlugin = new BundleAnalyzerPlugin({});
    
    module.exports = {
      configureWebpack:{ 
        plugins:[
            bundleAnalyzerPlugin // 打包分析
        ]
      }
    };    

    然后,每次npm run build成功之后,就会自动打开8888端口号的该分析结果页面
    这个分析的更加清晰

    vendors提取的是第三方公共库,公共资源,这些文件会打到dist/js/chunk-vendors.js里面 ,提取规则是每个页面都引入的才会打到chunk-vendors.js里面(如vue.js)
     

    完整配置
    提出上边完整的vue.config.js配置

    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer');
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const CompressionPlugin = require('compression-webpack-plugin');
    const bundleAnalyzerPlugin = new BundleAnalyzerPlugin({
    
    });
    const compressionPlugin = new CompressionPlugin({
      test: /.(js|css)?$/i, // 哪些文件要压缩
      filename: '[path].gz[query]',// 压缩后的文件名
      algorithm: 'gzip',// 使用gzip压缩
      minRatio: 1,// 压缩率小于1才会压缩
      deleteOriginalAssets: false // 删除未压缩的文件,谨慎设置,如果希望提供非gzip的资源,可不设置或者设置为false
    })
    
    
    module.exports = {
      publicPath: process.env.BASE_URL,
      devServer: {
        proxy: process.env.VUE_APP_SERVER,  // 代理
        open: true // 启动项目自动开启浏览器
      },
      configureWebpack:{
        plugins:[  //插件
          bundleAnalyzerPlugin, // 打包分析
          compressionPlugin // gz压缩
        ],
        externals: {  // 使用外部资源
          'vue': 'Vue',
          'vue-router': 'VueRouter',
          'vuex': 'Vuex',
          'axios': 'axios',
          'echarts': 'echarts',
          'element-ui':'ELEMENT',
          'lodash': '_',
          'dayjs': 'dayjs'
        }
      }
    };

    路由和组件懒加载

    const routes = [
      {
        path: '/',
        name: 'data-home',
        component: () => import(/* webpackChunkName: "data-home" */ '../views/data/index.vue'),
        children: [
          {
            path: '/',
            name: 'today-data',
            component: () => import(/* webpackChunkName: "today-data" */ '../views/data/today-data/index.vue')
          },
          {
            path: '/our-data',
            name: 'our-data',
            component: () => import(/* webpackChunkName: "our-data" */ '../views/data/our-data/index.vue')
          },
          {
            path: '/customer-data',
            name: 'customer-data',
            component: () => import(/* webpackChunkName: "customer-data" */ '../views/data/customer-data/index.vue')
          }
        ]
      },
      {
        path: '/login',
        name: 'login',
        component: () => import(/* webpackChunkName: "login" */ '../views/accounts/login.vue')
      }
    
    ];

    这样的话,单个组件或文件依赖其他部分,并不会在打包的时打在一起,而非根据懒加载关键字来切割。
    当需要的使用的时候,再去请求并加载。
    这样就减少了单个模块或文件的体积,从而加快相应速度(尤其是首屏)。

    需要注意的是在vue-cli3升级之后,配置了webpack的预加载,这时候除了路由懒加载需要的当前页面资源,其他资源也会被请求,但不会被解析。
    白色文件就是预加载的文件,仍然会耗时下载,只是不会被解析。这些文件属于prefetch,也就是预读取,他的加载基本不会影响到当前页面的打开,而且在读取完成后,可以降低页面跳转的等待时间,是一个非常好的功能。
    预加载技术(prefetch)是在用户需要前我们就将所需的资源加载完毕,不是所有浏览器都支持,主要是Chrome浏览器。
    有人说:单如果由于预加载文件比较多,反而阻塞了实际需要的文件下载,首页渲染速度可能也会导致变慢。
    但是我不这么认为,因为这是浏览器提供的功能,它会处理好这个关系。倒是会给开发人员造成疑惑“我明明懒加载”了,则么还是一起请求

    解决办法

    // vue.config.js
    module.exports = {
      chainWebpack: config => {
        // 移除 prefetch 插件
        config.plugins.delete('prefetch')
    
        // 或者
        // 修改它的选项:
        config.plugin('prefetch').tap(options => {
          options[0].fileBlacklist = options[0].fileBlacklist || []
          options[0].fileBlacklist.push(/myasyncRoute(.)+?.js$/)
          return options
        })
      }
    }


    参考:
    https://www.jb51.net/article/182323.htm
    https://blog.csdn.net/crazywoniu/article/details/73480344
    https://www.cnblogs.com/HYZhou2018/p/10419703.html
    https://www.jianshu.com/p/078afc10fd3c
    https://segmentfault.com/q/1010000018392785
    https://blog.csdn.net/huangpb123/article/details/84170557
    https://www.cnblogs.com/callmesummer/p/4345197.html

  • 相关阅读:
    程序打包(通过VS2015插件 InstallShield2015 Limited Edition 方式)
    QSS单独设置四个边角
    Qt 设置窗口圆角
    Qt实现鼠标拖动窗口
    关于split切割的几种情况
    java开发过程中,报错Dangling meta character '*' near index 0,解决办法
    关于ArrayList的contains方法
    WPS文档按回车键不能换行怎么解决
    正则表达式截取数字
    如何用hibernate中查询出一个表数量总数
  • 原文地址:https://www.cnblogs.com/dshvv/p/12951576.html
Copyright © 2011-2022 走看看