详解基于 Nuxt 的 Vue.js 服务端渲染实践


Posted in Javascript onOctober 24, 2017

Vue.js 是目前最火热的前端框架之一,而 Nuxt.js 是针对 Vue.js 推出的服务端渲染框架,通过高度定制化的配置以及简洁的 API,开发者可以快速进行服务端渲染项目的开发,本文将对 Nuxt.js 框架做一个简要介绍。

服务端渲染

服务端渲染(Server Side Render)并不是一个新的概念,在单页应用(SPA)还没有流行起来的时候,页面就是通过服务端渲染好,并传递给浏览器的。当用户需要访问新的页面时,需要再次请求服务器,返回新的页面。

为了优化体验,开发者们开始选择采用 JavaScript 在前端完成渲染过程,用前后端分离的手段,使后端更专注于数据,而前端注重于处理展示,通过设计良好的 API 以及 Ajax 技术完成前后端的交互,jQuery、React.js、Vue.js、Angular.js 等框架应运而生。

这些框架给开发者带来了巨大的便利,但是对于一些论坛、资讯网站、或是企业的官方网站来说,他们对 搜索引擎优化(SEO) 有强烈的要求,而前端渲染技术是无法满足他们的需求的。如果无法通过搜索引擎的搜索输出自身的内容,那么网站的价值就会大大受影响,要解决这类问题,还是要靠服务端渲染。

本文会介绍 Vue.js 的服务端渲染解决方案 Nuxt.js。Vue.js 推出后,其数据驱动和组件化思想,以及简洁易上手的特性给开发者带来了巨大的便利,Vue.js 官方提供的 vue-server-renderer 可以用来进行服务端渲染的工作,但是需要增加额外的工作量,开发体验仍有待提高,而 Nuxt.js 推出后,这个问题被很好的解决了。

Nuxt.js 简介

Nuxt.js 是一个基于 Vue.js 的通用应用框架,Nuxt.js 预设了利用 Vue.js 开发服务端渲染的应用所需要的各种配置,并且可以一键生成静态站点。同时,Nuxt.js 的热加载机制可以使开发者非常便捷的进行网站的开发。

Nuxt.js 于 2016 年 10 月 25 号发布,上线还不足一年,但是已经受到了广泛的好评,最新的稳定版本是 0.10.7,目前仍在进行 1.0 版本的内测,Nuxt.js 社区也在逐步完善中,官网已经支持了中文文档。

简单上手

Vue.js 的 vue-cli 工具可以很方便的让我们使用现成的模板初始化 Vue.js 项目,而 Nuxt.js 团队已经为我们提供了初始化 Nuxt.js 项目的模板,安装 vue-cli 后,只需在命令行中输入

vue init nuxt/starter <projectName>

即可完成项目的创建工作,然后进入项目目录中执行以下命令:

npm installnpm run dev

Nuxt.js 会使用 3000 端口运行服务,在浏览器中输入 http://localhost:3000 就可以看到一个带有 Nuxt.js 的 logo 的原始的页面了。

详解基于 Nuxt 的 Vue.js 服务端渲染实践 项目目录

完成了一个简单的 Hello World 项目后,我们来进一步研究 Nuxt.js。进入 Nuxt.js 项目后,项目目录如下:

详解基于 Nuxt 的 Vue.js 服务端渲染实践

下面简要介绍一下各个目录的作用:

.nuxt/ :用于存放 Nuxt.js 的核心库文件。例如,你可以在这个目录下找到 server.js 文件,描述了 Nuxt.js 进行服务端渲染的逻辑(参见下一段 “Nuxt.js 的渲染流程”), router.js 文件包含一张自动生成的路由表。

assets/ :用于存放静态资源,该目录下的资源使用 Webpack 构建。

components/ :存放项目中的各种组件。注意,只有在这个目录下的文件才能被称为 组件

layouts/ :创建自定义的页面布局,可以在这个目录下创建全局页面的统一布局,或是错误页布局。如果需要在布局中渲染 pages 目录中的路由页面,需要在布局文件中加上 <nuxt /> 标签。

middleware/ :放置自定义的中间件,会在加载组件之前调用。

pages/ :在这个目录下,Nuxt.js 会根据目录的结构生成 vue-router 路由,详见下文。

plugins/ :可以在这个目录中放置自定义插件,在根 Vue 对象实例化之前运行。例如,可以将项目中的埋点逻辑封装成一个插件,放置在这个目录中,并在 nuxt.config.js 中加载。

static/ :不使用 Webpack 构建的静态资源,会映射到根路径下,如 robots.txt

store/ :存放 Vuex 状态树。

nuxt.config.js :Nuxt.js 的配置文件,详见下文。

Nuxt.js 的渲染流程

Nuxt.js 通过一系列构建于 Vue.js 之上的方法进行服务端渲染,具体流程如下:

调用 nuxtServerInit 方法

当请求打入时,最先调用的即是 nuxtServerInit 方法,可以通过这个方法预先将服务器的数据保存,如已登录的用户信息等。另外,这个方法中也可以执行异步操作,并等待数据解析后返回。

Middleware

经过第一步后,请求会进入 Middleware 层,在该层中有三步操作:

读取 nuxt.config.js 中全局 middleware 字段的配置,并调用相应的中间件方法 匹配并加载与请求相对应的 layout 调用 layoutpage 的中间件方法

调用 validate 方法

在这一步可以对请求参数进行校验,或是对第一步中服务器下发的数据进行校验,如果校验失败,将抛出 404 页面。

调用 fetchasyncData 方法

这两个方法都会在组件加载之前被调用,它们的职责各有不同, asyncData 用来异步的进行组件数据的初始化工作,而 fetch 方法偏重于异步获取数据后修改 Vuex 中的状态。

我们在 Nuxt.js 的源码 util.js 中可以看到以下方法:

export function applyAsyncData (Component, asyncData = {}) {
 const ComponentData = Component.options.data || noopData
 Component.options.data = function () {
  const data = ComponentData.call(this)
  return { ...data, ...asyncData }
 }
 if (Component._Ctor && Component._Ctor.options) {
  Component._Ctor.options.data = Component.options.data
 }
}

这个方法会在 asyncData 方法调用完毕后进行调用,可以看到,组件从 asyncData 方法中获取的数据会和组件原生的 data 方法获取的数据做一次合并,最终仍然会在 data 方法中返回,所以得出, asyncData 方法其实是原生 data 方法的扩展。

经过以上四步后,接下来就是渲染组件的工作了,整个过程可以用下图表示:

详解基于 Nuxt 的 Vue.js 服务端渲染实践

(图片来源:Nuxt.js 官网)

如上文所述,在 .nuxt 目录下,你可以找到 server.js 文件,这个文件封装了 Nuxt.js 在服务端渲染的逻辑,包括一个完整的 Promise 对象的链式调用,从而完成上面描述的整个服务端渲染的步骤。

Nuxt.js 的一些使用技巧

nuxt.config.js 的配置

nuxt.config.js 是 Nuxt.js 的配置文件,可以通过针对一系列参数的设置来完成 Nuxt.js 项目的配置,可以在Nuxt.js 官网 找到针对这个文件的说明,下面举例一些常用的配置:

head: 可以在这个配置项中配置全局的 head ,如定义网站的标题、 meta ,引入第三方的 CSS、JavaScript 文件等:

head: {
   title: '百姓店铺',
   meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { name: 'applicable-device', content: 'pc,mobile' },
   ],
   link: [
      { rel: 'stylesheet', type: 'text/css', href: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css'}
   ],
   script: [
      {src: 'https://code.jquery.com/jquery-3.1.1.min.js'},
      {src: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js'}
   ]
 },

build: 这个配置项用来配置 Nuxt.js 项目的构建规则,即 Webpack 的构建配置,如通过 vendor 字段引入第三方模块,通过 plugin 字段配置 Webpack 插件,通过 loaders 字段自定义 Webpack 加载器等。通常我们会在 build 的 vendor 字段中引入 axios 模块,从而在项目中进行 HTTP 请求( axios 也是 Vue.js 官方推荐的 HTTP 请求框架)。

build: {
   vendor: ['core-js', 'axios'],
   loaders: [
     {
       test: /\.(scss|sass)$/,
       use: [{
         loader: "style-loader"
       }, {
         loader: "css-loader"
       }, {
         loader: "sass-loader"
       }]
     },
     {
       test: /\.(png|jpe?g|gif|svg)$/,
       loader: 'url-loader',
       query: {
         limit: 1000,
         name: 'img/[name].[hash:7].[ext]'
       }
     },
     {
       test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
       loader: 'url-loader',
       query: {
         limit: 1000,
         name: 'fonts/[name].[hash:7].[ext]'
       }
     }
   ]
 }

css: 在这个配置项中,引入全局的 CSS 文件,之后每个页面都会被引入。

router: 可以在此配置路由的基本规则,以及进行中间件的配置。例如,你可以创建一个用来获取 User-Agent 的中间件,并在此加载。

loading: Nuxt.js 提供了一套页面内加载进度指示组件,可以在此配置颜色,禁用,或是配置自定义的加载组件。

env: 可以在此配置用来在服务端和客户端共享的全局变量。

目录即路由

Nuxt.js 在 vue-router 之上定义了一套自动化的生成规则,即依据 pages 的目录结构生成。例如,我们有以下目录结构:

详解基于 Nuxt 的 Vue.js 服务端渲染实践

这个目录下含有一个基础路由(无参数)以及两个动态路由(带参数),Nuxt.js 会生成如下的路由配置表(可以在 .nuxt 目录下的 router.js 文件中找到):

routes: [
  {
    path: "/",
    component: _abe13a78,
    name: "index"
  },
  {
    path: "/article/:id?",
    component: _48f202f2,
    name: "article-id"
  },
  {
    path: "/:page",
    component: _5ccbb43a,
    name: "page"
  }
]

对于 article-id 这个路由,路径中带有 :id? 参数,表明这是一个可选的路由,如果要将其设为必选,则必须在 article 的目录下添加 index.vue 文件。

再看下面一个例子:

详解基于 Nuxt 的 Vue.js 服务端渲染实践

由于有同名文件和文件夹的存在,Nuxt.js 会为我们生成嵌套路由,生成的路由结构如下,在使用时,需要增加 <nuxt-child /> 标签来显示子视图的内容。

routes: [
  {
    path: "/article",
    component: _f930b330,
    children: [
      {
        path: "",
        component: _1430822a,
        name: "article"
      },
      {
        path: ":id",
        component: _339e8013,
        name: "article-id"
      }
    ]
  }
]

此外,Nuxt.js 还可以设置动态嵌套路由,具体可参见Nuxt.js 的官方文档。

总结

Nuxt.js 尽管是一个非常年轻的框架,目前也有很多待改进的问题,但它的出现为 Vue.js 开发者搭建服务端渲染项目提供了巨大的便利,期待 Nuxt.js 1.0 版本发布后,能给我们带来更多实用的新功能。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
判断文档离浏览器顶部的距离的方法
Jan 08 Javascript
Jquery树插件zTree用法入门教程
Feb 17 Javascript
使用jquery提交form表单并自定义action的实现代码
May 25 Javascript
js制作支付倒计时页面
Oct 21 Javascript
JQuery 动态生成Table表格实例代码
Dec 02 Javascript
教大家轻松制作Bootstrap漂亮表格(table)
Dec 13 Javascript
Vue实现双向绑定的方法
Dec 22 Javascript
js Canvas绘制圆形时钟效果
Feb 17 Javascript
Vue 让元素抖动/摆动起来的实现代码
May 31 Javascript
JS实现模糊查询带下拉匹配效果
Jun 21 Javascript
新手简单了解vue
May 29 Javascript
JavaScript提升机制Hoisting详解
Oct 23 Javascript
Vue基于NUXT的SSR详解
Oct 24 #Javascript
nuxt+axios解决前后端分离SSR的示例代码
Oct 24 #Javascript
使用js获取伪元素的content实例
Oct 24 #Javascript
原生JS实现Ajax跨域请求flask响应内容
Oct 24 #Javascript
JS去掉字符串末尾的标点符号及删除最后一个字符的方法
Oct 24 #Javascript
AngularJS模糊查询功能实现代码(过滤内容下拉菜单排序过滤敏感字符验证判断后添加表格信息)
Oct 24 #Javascript
基于js中this和event 的区别(详解)
Oct 24 #Javascript
You might like
PHP中MVC模式的模板引擎开发经验分享
2011/03/23 PHP
php四种基础算法代码实例
2013/10/29 PHP
php实现异步将远程链接上内容(图片或内容)写到本地的方法
2016/11/30 PHP
PHP中时间加减函数strtotime用法分析
2017/04/26 PHP
jquery 实现的全选和反选
2009/04/15 Javascript
jquery 与NVelocity 产生冲突的解决方法
2011/06/13 Javascript
js文本框输入点回车触发确定兼容IE、FF等
2013/11/19 Javascript
在Firefox下js select标签点击无法弹出
2014/03/06 Javascript
JavaScript中停止执行setInterval和setTimeout事件的方法
2015/05/14 Javascript
jQuery的end()方法使用详解
2015/07/15 Javascript
jquery关于事件冒泡和事件委托的技巧及阻止与允许事件冒泡的三种实现方法
2015/11/27 Javascript
使用bootstrap实现多窗口和拖动效果
2016/09/22 Javascript
微信小程序开发中var that =this的用法详解
2020/01/18 Javascript
JS代码检查工具ESLint介绍与使用方法
2020/02/04 Javascript
线程和进程的区别及Python代码实例
2015/02/04 Python
10款最好的Web开发的 Python 框架
2015/03/18 Python
Python随机生成一个6位的验证码代码分享
2015/03/24 Python
Python内置数据结构与操作符的练习题集锦
2016/07/01 Python
使用python调用zxing库生成二维码图片详解
2017/01/10 Python
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
2017/10/29 Python
Scrapy抓取京东商品、豆瓣电影及代码分享
2017/11/23 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
python常用函数与用法示例
2019/07/02 Python
python实现超级马里奥
2020/03/18 Python
Python ConfigParser模块的使用示例
2020/10/12 Python
美国折扣地毯销售网站:Rugs.com
2020/03/27 全球购物
新浪网技术部笔试题
2016/08/26 面试题
如何找出EMP表里面SALARY第N高的employee
2013/12/05 面试题
写给妈妈的道歉信
2014/01/11 职场文书
建筑结构施工专业推荐信
2014/02/21 职场文书
文案策划求职信
2014/04/14 职场文书
青年志愿者先进事迹
2014/05/06 职场文书
2014年后勤工作总结
2014/11/18 职场文书
经理岗位职责范本
2015/04/15 职场文书
2015年社区环境卫生工作总结
2015/04/21 职场文书
主题班会开场白
2015/06/01 职场文书