一、背景
在今年年初我开始接触vue的时候,就发现在vue官方文档中“服务端渲染”的一节中提到了Nuxt.js框架,SSR这种方式对于首屏的加载时间优化显而易见,同时还可以方便的进行SEO。美团点评的点餐业务中,数据平台因为其数据量大的特点,首页加载时间很长,非常适合进行SSR改造;于是,我在非工作时间对nuxt.js框架进行了尝试,吃了一波螃蟹。本文对nuxt.js框架应用于生产环境进行了系统的论述,同时对所踩的坑也进行了一定的介绍。
官方对nuxt.js的介绍如下:
Properly configuring all the discussed aspects of a production-ready server-rendered app can be a daunting task. Luckily, there is an excellent community project that aims to make all of this easier: Nuxt.js. Nuxt.js is a higher-level framework built on top of the Vue ecosystem which provides an extremely streamlined development experience for writing universal Vue applications. Better yet, you can even use it as a static site generator (with pages authored as single-file Vue components)! We highly recommend giving it a try.
可以看出,vue官方对于nuxt.js的态度非常积极,还是值得大家尝试的,目前最新版本:1.0.0-rc2;1.0正式版即将发布,撒花!
因本文作者水平所限,如有错误,欢迎拍砖。
二、nuxt.js 简单介绍
1、nuxt.js的原理图:
具体的原理介绍官网有详细的解释,欢迎读者移步官网,这里不再复述。
2、nuxt.js的优势
三、技术栈选型
1、nuxt.js:0.10.6
2、axios:0.16.2 → 选择axios的原因很简单,它是vue官方推荐的包,并且axios可以运行于浏览器端和服务器端,减少了前端工程师的学习成本。
3、elementUI:1.3.7 → elementUI是基于vue的很全面的ui组件库,对于一个自己的验证项目很合适,可以快速开发,快速上线。
四、实施方案
工程的目录结构如下:
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/acab72bcb3e75009cb36193435240fb8?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
1、插件安装
你可以配置需要在“根vue.js应用”实例化之前需要运行的js插件,当然可以是你自己写的或第三方模块。
注意:在任何vue组件的生命周期内,只有beforeCreate和created这两个钩子会在浏览器端和服务端均被调用;其他的钩子都只会在浏览器端调用。
1)对于axios这种ajax请求插件,无疑会使用在页面的方方面面中,那么如果在每个页面中使用import方式进行引入,会导致在打包的时候打包多次。而实际上我们只需要打包一次,可以通过在nuxt.config.js里面的build.vendor来解决。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/d61a9c30bca600504f76229408a74ad6?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
当然,如果你需要区分测试环境和线上环境的接口地址,就需要在plugins文件中对axios进行编写,如图:
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/7e0f604afb7a7723027165c61c1a5cbe?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
2)使用vue插件 – elementUI
普通的npm包的引入方式如上面的axios所述,那么vue插件我们该怎么处理呢?
- 首先我们需要在plugins文件夹中添加插件文件,element-ui.js
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/9842d6f12e14e37d257218617d9bd10d?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/50ab1329d1e682f5773806f6509f2741?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ /> - 在nuxt.config.js中配置plugins字段
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/cfd2fad860cdda12fbfa0c507a5223a3?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ /> - 由于elementUI是第三方库,我们需要把它打包到库文件里面以获得更好的缓存效果。在nuxt.config.js中配置element-ui即可。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/8d7ddd3232032372ceff2fe3019ec842?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
3)同时nuxt还支持区分只在浏览器中运行和只在服务端运行的插件。
- 只在浏览器运行:配置nuxt.config.js中plugins字段,将引入的插件属性设置为ssr: false
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/8a37e4283d6c1f6f959df90c9ef7956e?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ /> - 只在服务端运行:直接在webpack打包server.bundle.js文件中,将process.SERVER_BUILD设置为true即可
2、layout布局
nuxt.js实现了一个新的概念,layout布局,我们可以通过layout布局方便的实现页面的多个布局之间方便的切换。本项目中实现了三种常用的布局,即:1)两栏布局,左栏固定,右栏动态宽度;2、错误页提示,页面中间一个提示框的布局方案;3、纯白页面布局。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/976bdc4662cbdc623bded53fcad4d609?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
以两栏布局举例:
- 首先,在layout → default.vue中编写默认布局
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/8223e3864bc11e2b174f28fd30e8668b?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />layout与页面的具体内容的插口即:nuxt标签 - 具体开发的页面中,如果使用默认布局,则不需指定页面的布局,nuxt框架会自动对没有指定布局的页面和default布局进行关联。如果需要指定布局,则在layout字段中对布局进行指定。如图在login页面中对full布局进行了指定。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/f76cd921acf3cf0ced6a351f1a6f115f?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
注:个人开发感受:layout布局对于页面类型多变的工程很有好处,我们可以减少冗余代码,并且方便开发人员在多个布局中简单切换。nuxt框架将页面分层划分为3层:1、布局;2、页面;3、组件
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/b97e8772d283fb0cece7f8f07cc3121d?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
这么划分逻辑上更清楚,也更贴近组件化页面开发的思想。
PS:个人在非vue项目中也自行实现了一个简单的layout布局,使用slot插口即可实现。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/cfdee7bc3842d3c0b386f31c2ea1bcfb?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
layout文件提供slot插口
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/d30dfbadd9356b0fb61f606e6495903c?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
在开发页面中将layout文件以组件的方式引入即可。
3、server端api编写
nuxt的server端使用的是express,故server端api直接编写express router即可。server端目录组织如图:
server/index.js 文件是express的启动文件,plugins和middleware文件是axios的配置,api文件夹内即api接口。
server/index.js文件里面对api引用如下:
我们先看看axios的配置,通过对process.env的匹配来区分线上与测试环境,同时在middleware文件中对接口进行鉴权。
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/042eaaaeea63368ac4c176cea851d19a?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/cdacbb318bc983120c2e97d6691c9cb5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
之后在api/index.js文件中对各接口进行引用和聚合
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/3672d06d4dd4cdd1bc3b435f929fa7f5?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
在所有接口文件中,以announcement.js举例:
” data-src=”https://user-gold-cdn.xitu.io/2017/8/9/209f429d29bb0a703cf835526049df00?imageView2/0/w/1280/h/960/format/webp/ignore-error/1″ data-width=”800″ data-height=”600″ />
可以看到为了实现简便和避免过度设计,api接口没有对数据进行重新封装,直接进行了透传处理。
4、页面路由
nuxt框架的页面路由使用了vue-router,但是我们不需要对页面的路由进行过多的操心,因为我们只要按照nuxt规范的页面文件目录结构进行设计,就可以自动生成vue-router文件。或者说我们存放页面的目录结构会直接影响最终生成的路由配置。
本项目的页面目录结构如图所示:
而生成的router文件为:
可以看出生成的路由与pages文件夹目录结构是一一对应的。
注意:其中带参数的动态路由,需要创建对应的下划线作为前缀的vue文件或目录。例如图中bidDetail/_id.vue文件,最终生成的路由即为:path: “/bidDetail/:id?”。
五、总结
从头搭建一个服务端渲染的框架其实是相当复杂的,不过有了nuxt.js后,我们可以很轻易的搭建出一个可扩展可定制的SSR框架,这大大的减少了我们搭建框架的时间成本。因为nuxt的官方文档写的足够详细,我没有对安装这类常规项进行描述,直接从插件安装、新概念 – layout布局、server端api、pages的组织入手,介绍了我在项目实战中使用nuxt框架的一些关键路径。目前项目上线在aws跑了半个多月,总体稳定,说明虽然nuxt不是1.0版本,但是也足够用于生产实践了。(考虑到github上说。nuxt的1.0版本即将到来,我们有理由期待vue的SSR前景)
由于本文作者水平与篇幅所限,不能对项目中的所有细节尽述,对nuxt感兴趣的读者可以邮件联系:[email protected],感谢~
作者:美团点评点餐
链接:https://juejin.im/post/598aabe96fb9a03c335a8dde
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。