首页 > 软件开发 > 如何用Vue构建大型单页面应用?

快速发布【软件开发】相关需求,专业顾问为您服务 快速发布

用此手机号发布,您还可以点击 更换

发布需求
请输入正确的手机号
请输入正确的验证码

您是不是要找:

  • 专家问诊,提供专业建议
  • 急速响应,体验省心
  • 根据需求灵活定制解决方案

如何用Vue构建大型单页面应用?

标签:- 2017-8-18 作者:Lfdhjbsufvycn

服务端:Node.js


前端框架:Vue (v2.x)


前端构建工具:webpack


代码检查:eslint


状态管理:Vuex


服务端通信:axios


进程管理:pm2


首先先说一下单页面的优缺点:


单页面开发的优点:


良好的用户体验


用户不需要重新刷新页面,减少TTFB的请求耗时,获取数据也是通过Ajax异步获取,页面显示流畅。


前后端分离


前端负责界面显示,后端负责数据存储和计算,各司其职,不会把前后端的逻辑混杂在一起。


减轻服务端压力


减轻服务器压力,服务器只需要提供API接口,不用管页面逻辑和页面的拼接,吞吐能力会提高几倍。


共用一套后端程序代码,适配多端


同一套后端程序代码,不用修改就可以适用于Web、手机、平板。


单页面开发的缺点:


首屏加载过慢


单页面首次加载,需要将所有页面所依赖的css和js 合并后统一加载,所      以css和js文件会较大,影响页面首次打开时间。


SEO


因为页面数据都是前端异步加载的方式,不利于搜索引擎的抓取。


基于以上的原因,所以我们引入了Vue SSR技术


引入Vue SSR


服务端预渲染


vue2.0引入了虚拟DOM,实现原理就是vue的编译器在编译模板之后,       会将这些模板编译成一个渲染函数,也就是render方法, 函数被调用的时     候就会渲染并且返回一个虚拟DOM的树,在交给一个patch函数,把虚拟     DOM施加到真实的DOM上。这样做的主要原因是因为js的运算是非常快     的,而在浏览器中直接操作DOM会对性能有一定损耗。


流式渲染


服务端渲染支持流式渲染,因为http请求也是流式的,在渲染组件时返回一个可读的 stream 流,然后直接写入 到 HTTP 响应中。流式渲染 能够确保服务端的响应度,也能让用户更快地获得渲染内容。


对组件进行缓存


前后端复用一套代码


前端和服务端可以复用一套代码,提升开发效率和维护性Vue SSR流程图


从图中可以看出,ssr有两个入口文件,client-entry 和 server-entry.js 也就是客户端和服务端入口文件,都包含了同一套应用代码,webpack 通过两个入口文件分别打包成给服务端用的 server bundle 和给客户端用的 client bundle. 当服务器接收到了来自客户端的请求之后,会创建一个渲染器 bundleRenderer,这个 bundleRenderer 会读取上面生成的 server bundle 文件,并且执行它的代码, 然后发送一个生成好的 html 到浏览器,等到客户端加载了 client bundle 之后,会和服务端生成的DOM 进行对比,也就是判断这个DOM 和自己即将生成的DOM 是否相同,如果相同就将客户端的vue实例挂载到这个DOM上, 否则会提示警告。


|—  api                        api 接口文件


|—  assets                  静态资源目录


|—  components         vue组件


|—  filters                    过滤器文件


|—  router                    路由文件


|—  views                    页面模板文件


|—  utils                       工具方法目录|—  store                      vuex相关文件


|—  app.js                    vue入口文件


|—  client-entry.js         客户端入口文件


|—  server.entry.js        服务端入口文件


|—  index.html             HTML入口文件


开启Vue SSR


使用服务端框架 express 或 koa


服务端框架,我们使用的是express,之前也使用过了koa,有了一些未知的坑,koa是不错,但是生态圈不如express,express有不少比较有特色的模块并不支持koa,并且官方的例子使用的就是express,所以我们为了方便就选择了express作为我们的ssr服务器。


安装配置webpack 和 vue


拆分入口文件,服务端和浏览器要分开渲染


vue2使用了虚拟DOM, 因此对浏览器环境和服务端环境要分开渲染, 要创建两个对应的入口文件。


server-entry: 使用 vue ssr 功能将虚拟DOM渲染成网页client-entry: 使用 $mount 直接将应用挂载到DOM上server-entry 服务端入口文件


server.js 返回一个函数,该函数接受一个从服务端传递过来的 context 的参数,将 vue 实例通过 promise 返回。 context 一般包含 当前页面的url,首先我们调用 vue-router 的 router.push(url) 切换到到对应的路由, 然后调用getMatchedComponents 方法返回对应要渲染的组件, 这里会检查组件是否有 preFetch 方法,如果有就会执行它。


在then里会将服务端获取到的数据挂载到 context 对象上,后面会把这些数据直接发送到浏览器端与客户端的vue实例进行数据(状态)同步。


client-entry 客户端入口文件


客户端入口文件很简单,同步服务端发送过来的数据,会和服务端生成的DOM 进行对比,也就是判断这个DOM 和自己即将生成的DOM 是否相同,如果相同就将客户端的vue实例挂载到服务端渲染的DOM上, 否则会提示警告。


组件化


将组件分为:基础组件、业务组件、页面组件


基础组件:


与业务低耦合,可复用


业务组件:


与业务深耦合,复用难度大,难抽象


页面组件


页面是组件的容器,将组件组合可以形式一个完整的界面├── components


│ ├── business          # 基础组件


│ └── base                 # 业务组件


├──  header


├──  header.vue


├──  logo.png


├──  header.scss


├── views                     # 页面组件


│   ├── index


├──  index.vue


└── comment


Vue的组件引入构建工具之后有一个单文件组件概念。就是眼前的这个Vue文件,在同一个Vue文件里,可以同时写 模板、脚本 和 样式,三个东西放在一个里面。 使用webpack进行打包,编译成js模块。可以使用多种预处理器Babel、ts、sass、postcss,同时可以使用方便的热重载。


在Vue中,父子组件之间的通信是通过 props 传递。从父向子单向传递;每次父组件更新时,子组件的所有 prop 都会更新为最新值。


如果想要子组件把数据传递给父组件,就需要在子组件上绑定自定义事件,然后在子组件使用emit去派发事件但开发中大型项目会遇到以下的问题


多个视图依赖于同一状态


兄弟组件间的状态传递无能为力


传参的方法对于多层嵌套的组件将会非常繁琐


所以这个时候,我们需要用Vuex负责多组件的状态管理Vuex


Vuex 是专门为 Vue.js 设计的状态管理库


结合Vue实现页面的展示更新


统一页面状态管理以及操作处理


Vuex 使用 单一状态树,通俗理解就是一个应用的数据集合,可以想象为一个“前端数据库”,让其在各个页面上实现数据的共享,并且可操作从左到右,从组件出发,组件中调用 action,在 action 这一层级我们可以和后台数据交互,比如获取初始化的数据源,或者中间数据的过滤等。然后在 action 中去派发 Mutation。Mutation 去触发状态的改变,状态的改变,将触发视图的更新。


Vuex项目结构


├── index.html        # HTML模板


├── app.js


├── api                    # API配置文件


├── components     # 组件


└── store


├── index.js          # 入口文件,提供store的module构建└── modules


├── index.js      # 首页模块


├── list.js           # 列表模块


└── common.js # 通用模块


使用单一状态树,导致应用的所有状态集中到一个对象中。所以当应用变得很大时,store对象会变得臃肿不堪为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters,让代码结构更清晰, 多人开发时,每个人只需要负责开发自己的模块即可。


state:单一状态树


getters:状态的获取


mutations:触发同步事件


action:提交mutation可以包含异步操作


数据处理


Axios


现在vue-resource,现在官方宣布不在维护,


所以我这里使用的是Axios,它能够同时支持客户端和服务端请求,拦截请求和响应,支持 Promise API,客户端支持防止 CSRF 攻击,并且可以处理并发请求。


我们在项目里,主要 利用拦截器做预处理,对API进行封装,并且讲述下在组件中如何进行使用利用拦截器做预处理


请求时的拦截器


请求完成后的拦截器


对API进行封装


对 服务端 和 客户端 API请求文件进行区分


要点:服务端 需要在headers里写入cookie


在组件中的使用


随着我们代码,项目越来越大,优化必不可少,下面介绍一下我们的优化策略优化策略


serviceWorker 预缓存


在serviceWorker进程中运行


缓存必要的 JS、CSS、font


大幅度减少CDN的压力


资源是持久性存储


和indexDB、LocalStorage共用,存储空间约有50M


使用常规的方式,用LocalStorage来缓存JS以及CSS,会与业务代码耦合性很高,并且十分容易被XSS攻击,但使用serviceWorker不会有这样问题,我们只需要关注需要缓存的文件即可,缓存文件的安全全部由浏览器自行控制,用户无法手动删除这些缓存。


唯一的缺点就是,目前有些浏览器还不支持serviceWorker,只能等浏览器自行支持我们可以使用webpack插件来实现


npm install --save-dev sw-precache-webpack-plugin服务端API数据的缓存


组件的缓存


按需分块加载


后面会单独写一篇文章,来介绍和讲解下使用方法和原理通用策略


将静态资源上传到CDN


使用Gzip压缩


图片压缩、懒加载和base64


首屏外使用异步加载


优化后,我们的项目的首页加载时间从700多ms,提升到了400多ms

最新文章推荐

软件开发暂无最新文章查看全部推荐文章>

推荐人才