Vue SPA单页面

525 阅读6分钟

一、SPA 理解

  • SPA 也是单页面应用的意思,通俗来说就是只有一个 index.html 页面,内部通过路由来实现页面的局部切换,公共资源部分只加载一次

  • SPA 将所有的活动局限于一个 Web 页面中,仅在该 Web 页面初始化时加载相应的 HTML 、 JavaScript 、 CSS 。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转,而是利用 JavaScript 动态的变换 HTML(采用的是 div 切换显示和隐藏),从而实现UI与用户的交互。在 SPA 应用中,应用加载之后就不会再有整页刷新。相反,展示逻辑预先加载,并有赖于内容Region(区域)中的视图切换来展示内容

image.png

二、SPA 和 MPA 的区别

  • MPA 也是多页面应用的意思,就是每个页面都是一个主页面,都是独立的,当我们在访问另一个页面的时候,都需要重新加载他们相应的 HTML 、 JavaScript 、 CSS

image.png

SPAMPA
结构一个主页面 + 许多模块的组件多完整的页面
体验页面切换快,体验佳;当初次加载文件过多时,需要做相关的调优页面切换慢,网速慢的时候,体验尤其不好
资源加载组件公用的资源只需要加载一次每个页面都要自己加载公用的资源
适用场景对体验度和流畅度有较高要求的应用,不利于 SEO(可借助 SSR 优化 SEO)适用于对 SEO 要求较高的应用
适用场景可以使用 hash ,也可以使用 historyhistory
数据传递单页面引用,可以使用全局状态管理(VueX)通过url、cookie、localStorage等传递

三、SPA 优缺点

3-1 优点   

  1. 良好的交互体验,能提升页面切换体验,用户在访问应用页面是不会频繁的去切换浏览页面,从而避免了页面的重新加载
  2. 前后端分离开发,单页Web应用可以和 RESTful 规约一起使用,通过 REST API 提供接口数据,并使用 Ajax 异步获取,这样有助于分离客户端和服务器端工作。更进一步,可以在客户端也可以分解为静态页面和页面交互两个部分
  3. 减轻服务器压力,服务器只用出数据就可以,不用管展示逻辑和页面合成,吞吐能力会提高几倍
  4. 共用一套后端程序代码,不用修改后端程序代码就可以同时用于 Web 界面、手机、平板等多种客户端

3-2 缺点

  1. 不利于SEO,由于所有的内容都在一个页面中动态替换显示,所以在SEO上其有着天然的弱势,所以如果你的站点对SEO很看重,且要用单页应用,那么就做些静态页面给搜索引擎用吧
  2. 浏览器前进、后退管理,由于单页Web应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理,当然此问题也有解决方案,比如利用URI中的散列+iframe实现
  3. 初次加载耗时多,为实现单页Web应用功能及显示效果,需要在加载页面的时候将JavaScript、CSS统一加载,部分页面可以在需要的时候加载。所以必须对JavaScript及CSS代码进行合并压缩处理

四、SPA 首屏加载优化

4-1 首屏加载慢的原因

首屏时间指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前页面需要的内容,在页面渲染的过程,导致加载速度慢的因素可能如下:

  1. 网络延时问题
  2. 资源文件体积过大
  3. 资源重复发送请求去加载了
  4. 加载脚本的时候,渲染内容堵塞了

4-2 首屏加载慢的解决方案

路由动态加载

  • 按需加载指的就是按照当前呈现的不同页面加载不同的文件,而不是最开始就把所有文件都加载出来,从而避免首屏加载很慢
  • 当首屏加载完毕后,设备和网络处于空闲状态,再去对其他路由组件进行预加载,以便提升页面切换性能
  • 根据路由拆分减少初始加载体积,利用异步加载方式,在路由注册时提供异步拉取组件的方法,仅在需要进入对应路由时,对应组件才会被加载进来
// 在`vue-router`配置路由的时候,采用动态加载路由的形式
routes:[ 
    {
        path: 'Blog', 
        name: 'Blog', 
        component: () => import('./components/Blog.vue') 
    }
]

UI组件按需加载

// 引用了整个库
import ElementUI from 'element-ui'
Vue.use(ElementUI)

// 按需引用
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui';
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)

修改webpack配置,避免重复打包
在多个页面引用了同一个常用库的时候会造成该库的重复下载

// 解决方案:在 webpack的 config 文件中,修改 CommonsChunkPlugin 的配置
minChunks: 3

minChunks 为3表示会把使用3次及以上的包抽离出来,放进公共依赖文件,避免了重复加载组件

使用webpack插件,开启GZip压缩

// 安装 compression-webpack-plugin
cnmp i compression-webpack-plugin -D
// 修改 webpack 配置,再拆完包之后,使用 gzip 做一下压缩
const CompressionPlugin = require('compression-webpack-plugin')

configureWebpack: (config) => {
    if (process.env.NODE_ENV === 'production') {
        // 为生产环境修改配置...
        config.mode = 'production'
        return {
            plugins: [new CompressionPlugin({
                test: /.js$|.html$|.css/, //匹配文件名
                threshold: 10240, //对超过10k的数据进行压缩
                deleteOriginalAssets: false //是否删除原文件
            })]
        }
    }

图片资源的压缩

页面中使用到的icon,可以使用在线字体图标,或者雪碧图,将众多小图标合并到同一张图上,用以减轻 http 请求压力

SSR 服务端渲染

服务端渲染就是组件或页面通过服务器生成html字符串,再发送到浏览器

五、SPA 体验优化

  1. 构建骨架图,SPA 首屏加载面临较长时间白屏,骨架图是一个完美的”缓兵之计”,相当于加载到下个界面时先把下个页面的雏形加载出来,再加载其余的组件,做到缓冲作用,配合 PWA 首屏缓存,骨架图可实现瞬间加载的展示,首屏视觉上有冲击性地提升

  2. 页面切换时的转场动画,无论如何优化性能加载,在页面切换时候依旧需要获取页面数据,若处理不好,可能会在数据返回前有短暂的不友好”空白”,在大多数原生应用,转场动画属于标配,即使组件的数据已经完全加载,在切换至新页面瞬间,依旧需要页面渲染时间,这段时间可能导致页面短暂空白或者”视觉阻塞”,通过转场动画时间,可以很好地缓解这个问题,大多数页面保证在转场动画完毕之后依然渲染完毕