当前位置: 首页 > Web前端 > vue.js

前端大进军——同构应用

时间:2023-03-31 15:17:31 vue.js

概述在前端领域,随着Vue、React、Angular等框架的流行,前端工程化和模块化成为了当前主流的技术方案。此类框架构建的SPA单页应用具有用户体验好、渲染性能好、可维护性高等优点,但也存在以下两个问题:首屏加载时间长。SPA应用采用客户端渲染,用户需要等待客户端js解析完成后才能看到页面,会导致首屏加载时间变长,用户体验差。不利于SEO,因为SPA应用采用客户端渲染,网站HTML在没有解析js之前是没有内容的,导致搜索引擎在抓取网站HTML时获取不到内容。为了解决这两个问题,业界提出了一种新的解决方案,如下图所示:利用服务端渲染解决首屏加载慢、不利于SEO的缺陷。首屏渲染完成后,由客户端渲染接管页面,成为单页应用,保证良好的用户体验。这种方法称为现代服务器端渲染或同构渲染。与传统的服务端渲染不同,传统的服务端渲染,如JSP,可以概括为以下几个步骤:客户端发送请求,服务端根据请求查找模板并获取数据。执行渲染生成html返回给客户端显示。这种传统的服务器端渲染方式存在以下缺点:前后端完全耦合,不利于开发和维护。前端发挥空间不大。服务器压力很大。平均用户体验。同构渲染只是在渲染首屏时类似于传统的服务器,返回渲染后的html页面。但是在同构渲染中,当客户端显示渲染后的html页面时,客户端渲染会接管页面的控制权,即后续的渲染由客户端来完成,可以保证良好的用户体验。同构渲染的缺点与单页应用相比,由于首屏渲染使用服务端渲染,所以有以下缺点:开发条件有限,开发受限(服务端只能使用nodejs,并不是所有的工具包都可以使用在服务器端呈现)。构建和部署要求高(需要部署客户端和服务端,不能再像单页应用那样部署静态站点)。更多的服务器负载。Nuxt.jsNuxt.js是基于vue技术栈的同构应用解决方案,屏蔽了用vuejs构建同构应用的难点。基本使用构建一个nuxtjs同构应用是比较简单的。最简单的同构应用程序可以通过以下四个步骤构建:创建一个项目文件夹。npm或yarn安装nuxt。添加pages文件夹并在其中添加index.vue文件。执行npxnuxt。所有的路由页面vue文件都存放在基础路由pages文件夹下,nuxt会根据pages文件夹自动生成路由。如果pages目录如下:pages/--|用户/-----|index.vue-----|one.vue--|index.vue那么nuxt会自动生成如下路由结构:router:{routes:[{name:'index',path:'/',component:'pages/index.vue'},{name:'user',路径:'/user',组件:'pages/user/index.vue''},{名称:'user-one',路径:'/user/one',组件:'pages/user/one.vue'}]}动态路由nuxt在解析路由结构时,如果遇到一个_as前缀的vue文件时,会定义为带参数的动态路由。比如下面的文件结构:pages/--|_slug/-----|评论.vue-----|index.vue--|用户/-----|_id.vue--|指数。vue生成的路由表为:router:{routes:[{name:'index',path:'/',component:'pages/index.vue'},{name:'users-id',path:'/users/:id?',component:'pages/users/_id.vue'},{name:'slug',path:'/:slug',component:'pages/_slug/index.vue'},{name:'slug-comments',path:'/:slug/comments',component:'pages/_slug/comments.vue'}]}嵌套路由在vuejs中,我们可以通过子路由实现路由的多层嵌套,同样在nuxtjs中,可以通过特殊的文件结构来实现嵌套路由。创建嵌套路由需要添加一个vue文件,并添加一个与该文件同名的文件夹存放子路由组件(需要在vue中添加一个类似于route-view的nuxt-child节点文件。)比如下面的文件结构:pages/--|用户/-----|_id.vue-----|index.vue--|users.vue生成的路由表如下:users/index.vue',name:'users'},{path:':id',component:'pages/users/_id.vue',name:'users-id'}]}]}自定义路由Nuxtjs即可不仅通过pages文件夹结构自动生成路由表,还提供配置文件配置自定义路由。nuxtjs配置文件与vue.config.js相同。在项目的根目录下创建一个nuxt.config.js文件。该文件默认导出一个配置对象。配置对象有一个router属性,你可以在这个属性下配置自定义路由。exportdefault{router:{extendRoutes(routes,resolve){//这个方法可以用来清除默认生成的路由//routes.splice(0)routes.push(...[{path:'/',component:resolve(__dirname,'your.vue'),}])}}}templatenuxtjs根据html模板生成html文件,我们可以在项目中修改这个模板。自定义模板需要在项目根目录下创建一个app.html文件。默认的html结构如下:}我们可以在head中添加相应的自定义css和js引用。asyncData在vuejs项目中,如果一个组件要从服务端获取数据,一般会在created语句循环函数中发起请求。在同构应用中,如果希望页面内容对SEO友好,则不能使用这种方法。nuxt中的Vue组件中添加了asyncData方法。该方法会在服务端执行,执行后的结果会合并到当前组件的数据对象中。以下示例获取并呈现服务器上的所有文章和标签:asyncasyncData(){const[articleRes,tagRes]=awaitPromise.all([getAllArticles({offest:0,limit:10,}),getAllTags(),])const{articles,articlesCount}=articleRes.dataconst{tags}=tagRes.datareturn{articles,articlesCount,tags,}}需要注意的是,虽然该方法是vue组件的方法,但是由于其调用了server,所以无法通过方法内部的this对象获取到vue实例。如果要获取实例的一些信息,可以使用上下文对象。context对象的asyncData方法包含一个参数context,context对象包含路由等公共信息。route:当前路由对象store:存储对象params,query:路由参数req,res:request,response对象redirect:用于重定向认证在同构应用中,用户登录时,需要在客户端和客户端之间共享身份信息server可以获取到,所以信息可以保存在cookie中。客户端获取信息并将其存储在cookie中:methods:{onSubmit(){letrequest=this.isLogin?login:registerrequest(this.user).then(({data})=>{//获取用户信息const{user}=dataif(user){constCookie=process.client?require('js-cookie'):undefined//将获取到的用户信息保存在cookie中Cookie.set('user',user)this.$store.commit('setUser',user)}}).catch((err)=>{})}}服务端读取cookie存储在store中供客户端使用:可以添加一个名为nuxtServerInit的异步方法,当nuxt应用启动时会调用该方法。nuxtServerInit({commit},{req}){letuser=nullif(req&&req.headers.cookie){constcookieParser=process.server?要求('cookieparser'):未定义;constparsed=cookieParser.parse(req.headers.cookie)try{user=JSON.parse(parsed.user)}catch(err){}}commit('setUser',user)}plugin如果你想执行一些jsvuejs程序运行前的操作,比如注册第三方组件库,此时可以使用插件。所有插件都放在plugins目录下。如果想在nuxt应用中使用elementui组件库,可以在plugins文件夹中添加element-ui.js文件:importVuefrom'vue'importElementfrom'element-ui'importlocalefrom'element-ui/lib/locale/lang/en'Vue.use(Element,{locale})然后在nuxt.config.js的plugins属性数组中添加对应的文件路径:plugins:['@/plugins/element-ui',】,可以在vue组件中正常使用element-ui。