详解基于 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 相关文章推荐
form中限制文本字节数js代码
Jun 10 Javascript
JavaScript入门教程(7) History历史对象
Jan 31 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
Jun 06 Javascript
jquery实现网页查找功能示例分享
Feb 12 Javascript
js实现图片漂浮效果的方法
Mar 02 Javascript
AngularJS入门教程之AngularJS指令
Apr 18 Javascript
深入浅析jQuery对象$.html
Aug 22 Javascript
AngularJs directive详解及示例代码
Sep 01 Javascript
Ajax 加载数据 练习代码
Jan 05 Javascript
Angular5中调用第三方js插件的方法
Feb 26 Javascript
浅谈JavaScript中this的指向问题
Jul 28 Javascript
javascript中Set、Map、WeakSet、WeakMap区别
Dec 24 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 preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
用来解析.htpasswd文件的PHP类
2012/09/05 PHP
Yii2主题(Theme)用法详解
2016/07/23 PHP
在Javascript中定义对象类别
2006/12/22 Javascript
Javascript Global对象
2009/08/13 Javascript
JS控制图片翻转示例代码(兼容firefox,ie,chrome)
2013/12/19 Javascript
微信分享的标题、缩略图、连接及描述设置方法
2014/10/14 Javascript
充分发挥Node.js程序性能的一些方法介绍
2015/06/23 Javascript
12个超实用的JQuery代码片段
2015/11/02 Javascript
Vuejs第一篇之入门教程详解(单向绑定、双向绑定、列表渲染、响应函数)
2016/09/09 Javascript
Angular实现购物车计算示例代码
2017/02/21 Javascript
使用jQuery和ajax代替iframe的方法(详解)
2017/04/12 jQuery
详解微信小程序设置底部导航栏目方法
2017/06/29 Javascript
Javascript将图片的绝对路径转换为base64编码的方法
2018/01/11 Javascript
electron中使用bootstrap的示例代码
2018/11/06 Javascript
vue封装可复用组件confirm,并绑定在vue原型上的示例
2019/10/31 Javascript
JavaScript canvas仿代码流瀑布
2020/02/10 Javascript
基于canvasJS在PHP中制作动态图表
2020/05/30 Javascript
EXTJS7实现点击拖拉选择文本
2020/12/17 Javascript
Python全局变量操作详解
2015/04/14 Python
pygame学习笔记(4):声音控制
2015/04/15 Python
python PIL模块与随机生成中文验证码
2016/02/27 Python
用Python解决计数原理问题的方法
2016/08/04 Python
Python subprocess模块详细解读
2018/01/29 Python
python实现装饰器、描述符
2018/02/28 Python
python numpy 部分排序 寻找最大的前几个数的方法
2018/06/27 Python
浅析python3字符串格式化format()函数的简单用法
2018/12/07 Python
对Python正则匹配IP、Url、Mail的方法详解
2018/12/25 Python
python实现爬山算法的思路详解
2019/04/09 Python
html5使用canvas绘制文字特效
2014/12/15 HTML / CSS
日本卡普空电视游戏软件公司官方购物网站:e-CAPCOM
2018/07/17 全球购物
保证书范文大全
2014/04/28 职场文书
小学生清明节演讲稿
2014/09/05 职场文书
党校毕业个人总结
2015/02/28 职场文书
幼儿园班级工作总结2015
2015/05/25 职场文书
pytorch中的model=model.to(device)使用说明
2021/05/24 Python