从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二八║ Nuxt 基础:面向源码研究Nuxt.js
前言
哈喽大家周五好,又是一个开开心心的周五了,接下来就是三天小团圆啦,这里先祝大家节日快乐咯,希望都没有加班哈哈,今天公司发了月饼,嗯~时间来不及了,上周应该搞个活动抽中几个粉丝发月饼的,下次吧,这里先预告一下,圣诞节活动,给粉丝送苹果吧哈哈,不过听起来好 low 呀,大家有好的想法可以下边评论或者来群里一起交流哟~
说接上文,昨天咱们第一次的接触到了一个新的框架 Nuxt《二七║ Nuxt 基础:框架初探》,从概念上,给大家简单说了下这个框架的产生和应用场景,大家学习这一块一定要有一定的 vue 基础,还有就是了解 SSR 服务端渲染的知识和原理,才能做到游刃有余,在之前的一系列文章中,咱们已经很详细说明了 vue 的客户端渲染 SPA 的工作原理,今天呢,咱们就重点说一下 Nuxt 的运行机制,虽说 Vue 已经发展了近两年,不过网上的资料还是比较匮乏,所有的教程也都是一篇搞定,直接就是 如何安装,如何写页面,我是不喜欢这样的,虽然自己懂得的也不是很多,但是还是想给大家分享下,至少往深层次挖掘一下,这样大家下次使用的时候,心里才有一个普。好啦,马上开始今天的讲解,今天没有涉及到代码,源码会在下周开始 Code 。
零、今天要完成绿色的部分
一、Nuxt 的初衷 —— 将核心专注于UI渲染
来个官方的说法
Nuxt.js is a minimalistic framework for server-rendered Vue applications (inspired by Next.js)
意思就是:
Nuxt 是服务器呈现的简约应用程序的框架,通过对客户端和服务端基础架构的抽象,Nuxt.js 可以让开发者更专注于页面的UI渲染。作用就是在 node.js 上进一步封装,然后省去我们搭建服务端环境的步骤,只需要遵循这个库的一些规则就能轻松实现 SSR。
说到这里大家可能稍微不是很明白,举个最简单的栗子( 这里就不说那个老生常谈的 SEO 了,这个本来就不存在于我们的客户端渲染中 ):咱们之前在用 vue-cli 脚手架搭建项目的时候,每次添加一个页面,都需要去配置路由 router ,是吧,然后呢,有时候运气不好了,在多层嵌套的路径配置时候,还时不时的不起作用,这些本来不应该属于我们开发的工作的,Nuxt 就很好的解决了这个问题,Nuxt.js 根据 pages 目录结构去生成 vue-router 配置,也就是说 pages 目录的结构直接影响路由结构,还是实时监听的方式。
再举个栗子:之前咱们在配置页面的时候,都是通过 index.html 提供一个模板,然后再一个 app.vue 的入口程序,然后将所有的 *.vue 组件通过路由填充进去,这个咱们第一次使用的时候,感觉还是很嗨皮的,不过长时间的使用的时候,就会发现其实有些问题,比如我们如果不想让某些组件路由显示出来,然后只能在配置里处理,通过配置路由是否显示等操作,显然又多了一个步骤,不过在 nuxt 框架中,我们有了动态路由,只需要在名字前加上一个下划线 _ ,比如 _id.vue ,这样就能轻松搞定,是不是很方便,这个咱们以后会讲到,这里暂时就不深入了。
再比如我们在之前说到组件的时候,用到了这个图,在入门页面中,将我们的所有组件按需加载,但是如果我们的项目有多个布局需要怎么办?比如我们商城首页,和个人中心首页有时候是不一样的,当时如果你一定要保持一个风格也是可以的,但是感觉这么配置还是怪怪的。
不过在 Nuxt.js 框架中,我们有了新的变化,layouts对应目录中的layouts文件夹,默认pages下的页面走的都是 layouts/default.vue 布局方式,但是如果自己定义的话,也可以新增新的布局页。其中<nuxt/>可以类似vue
中slot
插槽的概念,(如果对 slot 插槽不是很明白,可以看之前的文章 《二十║Vue基础终篇:组件详解+项目说明》的第四节),pages/**.vue中的内容会插在<nuxt/>
内。
在咱们的第二个项目,基于 Nuxt 的个人博客里,我就新建了一个 blog.vue 的布局页面,定制了一个博客布局:
<template>
<div class="layout-default">
<cl-header></cl-header>//定制博客页头
<nuxt class="layout-main"/>//nuxt 插入内容
<cl-footer></cl-footer>//定制博客页脚
<div class="layout-bg"></div>
</div>
</template> <script type="text/javascript">
import clHeader from "~/components/layout/header.vue";
import clFooter from "~/components/layout/footer.vue";
export default {
data () {
return {};
},
mounted () {
this.$store.dispatch("initUser");
},
components: {
clHeader,
clFooter
}
};
</script>
这个就是 nuxt 的分层页面布局。
由上边的栗子可以看出来,nuxt 是通过封装,将核心原理隐藏起来,重点实现我们的UI展示,这么做的目的就是更有经历去做 SSR 服务端渲染了,大家还记得咱们在讲 SSR 的时候么,需要很复杂的操作配合才能实现,所以,很好的底层封装,是我们更好开发 SSR 框架的第一步。
二、Nuxt 的工作流程 —— 四步走
还是老规矩,一言不合就放图系列
简单来说,当你访问一个基于Nuxt.js构建的页面时,发生了的事情如下:
1、当用户访问应用程序, 如果 store 中定义了 nuxtServerInit action,Nuxt.js 将调用它更新 store。
2、将加载即将访问页面所依赖的任何中间件。Nuxt 首先从 nuxt.config.js 这个文件中,加载全局依赖的中间件,之后检测每个相应页面对应的布局文件 ,最后,检测布局文件下子组件依赖的中间件。以上是中间件的加载顺序。
3、如果要访问的路由是一个动态路由, 且有一个相应的 validate() 方法路由的validate 方法,讲进行路由校验。
4、Nuxt.js 调用 asyncData() 和 fetch() 方法,在渲染页面之前加载异步数据。asyncData() 方法用于异步获取数据,并将 fetch 回来的数据,在服务端渲染到页面。 用 fetch() 方法取回的将数据在渲染页面之前填入store。
最后一步, 将所有数据渲染到页面。
其中核心配置文件 nuxt.config.js 是比较重要的一个文件,整个系统的配置和插件都需要这个文件来执行,感觉就像是我们 vue-cli 脚手架里的 main.js 入口文件一样,具体的配置以及使用咱们在以后的文章中再说明吧。上边咱们说到了还是工作流程,那 nuxt 到底封装了怎么的工作机制,才能很好的执行这个流程呢,重头戏来了
三、面向源码简要分析 Nuxt 的工作机制
1、通过 .nuxt 文件来执行我们的工作流程
刚刚咱们说到了,nuxt.config.js 就像是一个 main.js 入口一样,这个时候细心的你一定会发现,欸?为什么 nuxt 框架没有 router 呢,那我们的路由该如何配置呢,不要着急,nuxt 已经给我们封装了,我们无需把注意力放到这上边,这个时候我们执行
npm run dev
会发现多了一个文件(因为昨天我们已经执行过了,现在就不需要执行了)。
这个是我们项目生成的临时文件,我们项目运行时候配置的文件都是在这里,大家可以看到这里的路由文件,没错,这个就是系统自动给我们配置的路由文件,根据我们的 pages 文件夹路径生成的,大家还可以看到,由app.js ,client.js 和 server.js 这两个就是类似我们的 SSR 中配置的那个 server.js 入口文件,然后还有 middleware.js 中间件文件,其实这个时候我们大概能懂了,上边我们说的工作流程,走的就是这个 临时文件.nuxt 文件夹中的内容,但是这个文件夹是如何生成的呢,大家请往下看。
2、.nuxt 是如何产生的
本文主要研究nuxt的运行原理,分析它从接收一条nuxt指令,到完成指令背后所发生的一系列事情,在开始本文之前,请读者务必亲自体验过nuxt.js的使用,并且具备一定的vue.js相关开发经验。
通过查看nuxt.js工程目录下的package.json文件,我们可以看到下列几条指令:
"scripts": {
"dev": "nuxt", // 开启一个监听3000端口的服务器,同时提供hot-reloading功能
"build": "nuxt build", //构建整个应用,压缩合并JS和CSS文件(用于生产环境)
"start": "nuxt start", // 开启一个生产模式的服务器(必须先运行nuxt build命令)
"generate": "nuxt generate" //构建整个应用,并为每一个路由生成一个静态页面(用于静态服务器)
}
咱们还从来没有看过我们的依赖包哈,今天就来看看,打开我们的 node_modules 文件夹下的 nuxt工程文件夹 进入到到bin目录,我们可以看到5个文件:
咱们就说一下 dev 是如何工作的,咱们先找到一个片段,发现基本是执行了以下几个步骤:
try {
nuxt = new Nuxt(options)//实例化一个 nuxt 类
builder = new Builder(nuxt)
instance = { nuxt, builder }
} 。。。。 return (
Promise.resolve()
.then(
() =>
oldInstance && oldInstance.builder
? oldInstance.builder.unwatch()
: Promise.resolve()
)
// Start build 开始执行 build() 方法
.then(() => builder.build())
// Close old nuxt after successful build
.then(
() =>
oldInstance && oldInstance.nuxt
? oldInstance.nuxt.close()
: Promise.resolve()
)
// Start listening 开启监听服务端口
.then(() => nuxt.listen(port, host))
// Pass new nuxt to watch chain
.then(() => instance)
// Handle errors
.catch(err => onError(err, instance))
)
}
3、那什么是 nuxt() 类,它又是执行了什么样的方法呢?
这个时候,我们继续看源码,进入到nuxt/lib目录,我们可以看到如下的文件目录结构:
├── app
├── builder
├── common
└── core
├── middleware
│ ├── index.js
│ ├── meta.js
│ ├── module.js
│ ├── muxt.js
│ └── render.js
└── index.js
大家看这个熟悉不熟悉?!没错,就是和我们上边项目执行的时候生成的临时文件是类似的,请和上边的 .nuxt 临时文件夹做对比。
网上有个很好的总结,如图:
上图中每一步都可以在具体的代码中自行浏览。在用户输入指令并实例化了Nuxt()类以后,实例化出来的nuxt对象就会执行图中打了绿色对勾的几个方法:build(), render(), renderRoute(), renderAndGetWindow()以及generate()方法。
同时,Nuxt()类也提供了一个close()公有方法,用于关闭其所开启的服务器。
4、build() 进行编译,生成 .nuxt 临时文件
然后就是执行的 build() 方法:
简单来说,build()方法在判断完运行条件后,会先初始化产出目录 .nuxt ,然后通过不同目录下的文件结构来生成一系列的配置,写入模板文件后输出到.nuxt目录。接下来,则会根据不同的开发环境来调用不同的webpack 配置,运行不同的 webpack 构建方案。
5、render.js文件 打包输出渲染
在 nuxt/lib/core 目录下找到 render.js 文件,它包含着我们即将要分析的三个方法:render(), renderRoute(), renderAndGetWindow()。
通过这张图片,我们可以知道nuxt对于处理“客户端渲染”与“服务端渲染”的逻辑其实是非常清晰的。
首先,在render()方法在处理完一系列的路径问题后,会调用renderRoute()方法,获取响应所需内容并完成响应。
其中renderRoute()方法会判断当前响应是否应执行服务端渲染。如果是,则调用vue提供的bundleRenderer()方法,把html内容渲染完毕以后再整体输出;如果不是,则直接输出一个<div></div>字符串,交由客户端渲染。
// Call renderToString from the bundleRenderer and generate the HTML (will update the context as well)
let APP = await this.bundleRenderer.renderToString(context) if (!context.nuxt.serverRendered) {
APP = '<div id="__nuxt"></div>'
}最后,通过renderAndGetWindow()来检查输出的html是否存在问题,然后发出通知,表明html可用。
四、结语
好啦,今天因为时间的问题,暂时就说到这里吧,其实这里还有很多知识点没有说到,那我们就在之后的项目中,慢慢给大家说吧,请持续关注哟,可以点个赞
从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二八║ Nuxt 基础:面向源码研究Nuxt.js的更多相关文章
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二九║ Nuxt实战:异步实现数据双端渲染
回顾 哈喽大家好!又是元气满满的周~~~二哈哈,不知道大家中秋节过的如何,马上又是国庆节了,博主我将通过三天的时间,给大家把项目二的数据添上(这里强调下,填充数据不是最重要的,最重要的是要配合着让大家 ...
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 二七║ Nuxt 基础:框架初探
缘起 哈喽大家好,又是周四了,俗话说周四来了,周末还远么哈哈,老张我也想下周请假,来个16天的大长假哟,不知道大家是怎么请假的,近来发现文章下边已经没有人评论了,赶脚比较凄凉了,大家看到的麻烦点个赞呀 ...
- 从壹开始前后端分离 [ vue + .netcore 补充教程 ] 三十║ Nuxt实战:动态路由+同构
上期回顾 说接上文<二九║ Nuxt实战:异步实现数据双端渲染>,昨天咱们通过项目二的首页数据处理,简单了解到了 nuxt 异步数据获取的作用,以及亲身体验了几个重要文件夹的意义,整篇文章 ...
- 从壹开始前后端分离 [ vue + .netcore 补程 ] 三十一║ Nuxt终篇:基于Vuex的权限验证探究
缘起 哈喽大家好,今天周四啦,楼主明天要正式放假了,这里先祝大家节日快乐咯,希望在家里能继续研究点儿东西吧,今天呢是 nuxt 的最后一篇,主要是对权限登录进行研究,这一块咱们之前在说第一个项目的时候 ...
- 采用异步来实现重新连接服务器或者重新启动服务 C#中类的属性的获取 SignalR2简易数据看板演示 C#动态调用泛型类、泛型方法 asp .net core Get raw request. 从壹开始前后端分离[.NetCore 不定期更新] 38 ║自动初始化数据库
采用异步来实现重新连接服务器或者重新启动服务 开启异步监听,不会导致主线程的堵塞,在服务异常断开后一直检测重新连接服务,成功连接服务后通知各个注册的客户端! #region 检测断线并重连OPC服务 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║Vue基础:JS面向对象&字面量& this字
缘起 书接上文<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史>,昨天咱们说到了以我的经历说明的web开发经历的 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十六 ║Vue基础:ES6初体验 & 模块化编程
缘起 昨天说到了<从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十五 ║ Vue前篇:JS对象&字面量&this>,通过总体来看,好像大家对这一块不是很 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十八║Vue基础: 指令(下)+计算属性+watch
回顾 今天来晚辣,给公司做了一个小项目,一个瀑布流+动态视频控制的DEMO,有需要的可以联系我,公司的项目就不对外展示了(一个后端程序员真的要干前端了哈哈哈). 书接上文,昨天正式的开始了Vue的代码 ...
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十三║Vue实战:Vuex 其实很简单
前言 哈喽大家周五好,马上又是一个周末了,下周就是中秋了,下下周就是国庆啦,这里先祝福大家一个比一个假日嗨皮啦~~转眼我们的专题已经写了第 23 篇了,好几次都坚持不下去想要中断,不过每当看到群里的交 ...
随机推荐
- Nagios安装、配置、问题记录
http://youyizhimen.blog.163.com/blog/static/170917267201201745523276/ 本文描述了我在使用Nagios的过程中遇到的一些问题.解决办 ...
- jdbc 链接数据库步骤 7步
JDBC连接数据库 •创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), ...
- Dreamweaver无法启动:xml parsing fatal error..Designer.xml错误解决方法
xml parsing fatal error:Invalid document structure,line:1,file:C:\Documents and Settings\Administrat ...
- 在centos上面安装phantomjs
在opt目录下创建phantomjs文件夹 mkdir -p /opt/phantomjs 把phantomjs解压出来的的文件放到/opt/phantomjs下面 建立软链接 ln -s /opt/ ...
- Evensgn 剪树枝 树规
f[x][0]表示与其父边相连的连通块内没有黑苹果的方案数, f[x][1]则表示有黑苹果, 如果父边被切断,相当于没有黑苹果 初始化时,假设切掉父边,f[x][0]=1,f[x][1]=0; 递归回 ...
- POJ_1066_Treasure Hunt_判断线段相交
POJ_1066_Treasure Hunt_判断线段相交 Description Archeologists from the Antiquities and Curios Museum (ACM) ...
- 【SAP S/4 1511之变】:主数据之变
本博文主要讲述SAP S/4 1511版本的变化,主要是跟ECC版本的对比.变化还是挺多的,相当一部分是后勤,但绝大部分还是财务成本这一块.作为从事S/4版本的从业者,了解1511版本的变化还是挺有必 ...
- Android LayoutInflater源码解析:你真的能正确使用吗?
版权声明:本文出自汪磊的博客,未经作者允许禁止转载. 好久没写博客了,最近忙着换工作,没时间写,工作刚定下来.稍后有时间会写一下换工作经历.接下来进入本篇主题,本来没想写LayoutInflater的 ...
- Netty实现高性能IOT服务器(Groza)之手撕MQTT协议篇上
前言 诞生及优势 MQTT由Andy Stanford-Clark(IBM)和Arlen Nipper(Eurotech,现为Cirrus Link)于1999年开发,用于监测穿越沙漠的石油管道.目标 ...
- Boosting(提升方法)之GBDT
一.GBDT的通俗理解 提升方法采用的是加法模型和前向分步算法来解决分类和回归问题,而以决策树作为基函数的提升方法称为提升树(boosting tree).GBDT(Gradient Boosting ...