来源:SegmentFault 思否
近期公司成立了一个新项目,需要做SEO。做过前后端半分离(部分数据是后端模板渲染,部分用AJAX获取)项目的同学都知道跟后端人员把代码写在同一个页面有多难受,项目不易维护且开发体验很差,因此采用了Nuxt.js
SEO
大家都知道,网页在搜索引擎中能被搜索出来是因为他们有自己的爬虫,可以爬取网页中的内容并保存下来,但是它们只会保存网页中的第一个请求返回的内容,即HTML文档。
在传统的前后端不分离网站中,在浏览器上查看源代码,可以看到网页上有什么内容,源代码中就有与之对应的代码。随着前后端分离开发越来越流行,也衍生了越来越多的单页面应用(SPA),在浏览器中打开一个SPA的源代码,往往只能看到寥寥无几的几个标签,其余内容全都是由JS渲染的,也就是客户端渲染。因此单页面应用的一大痛点就是搜索引擎无法收录,有痛点就会有相应的方案产生,出现了SSR。
SSR
SSR意思是服务端渲染,乍一看会以为是回到以前的前后不分离开发模式,实际上相比以前,客户端与服务端之间多了一个中间层,用于接收数据并渲染页面返回到客户端。
有了中间层帮客户端渲染页面,在搜索引擎爬到页面时,就解决了前后端分离页面不收录的的痛点。不仅如此,由于中间层也是一个服务端,前端工程师可以做更多事儿了,比如简单处理数据、做代理等等。
Nuxt.js
Vue官方提供了vue-server-renderer模块实现SSR,而Nuxt.js是对其封装后的框架,用于提供一个开箱即用的NodeJS SSR服务。
生命周期
通过在地址栏输入链接,或者从其他网站点击链接跳转到Nuxt站点的页面时(首屏访问),呈现的第一个页面的数据会由中间层向服务端发起请求,然后渲染Vue组件,再将渲染完成后生成的HTML文档返回到客户端。随后点击页面的
组件或者通过vue-router的push,replace等方法跳转页面都是在客户端完成的,除非刷新浏览器,否则不会再次访问中间层服务器。因此在页面中请求服务端的数据有可能是中间层发起的,也有可能是客户端发起的。
访问Nuxt站点的页面时,会经历以下几个生命周期,我们可以在不同的节点对站点的行为做处理
按照nuxt.config.js中的plugins配置顺序执行插件。
nuxtServerInit: 如果Nuxt应用中使用了Vuex,会运行actions中的nuxtServerInit函数,用于在进入页面之前将数据填充到Vuex中。
Middleware: 按顺序执行nuxt.config.js中配置的router中间件、layout中间件、page中间件,可以用来对用户做权限验证。
validate(): 返回true、false或者Promise,返回false时,将会跳转到错误页面,主要用于验证动态路由的参数。
asyncData(): 返回一个对象,执行完毕之后Nuxt会将返回的对象合并到Vue实例的data属性中,用于在访问到页面之前调用接口获取数据,这个钩子取代了SPA中常用的created钩子。
beforeCreate: Vue组件生命周期钩子。
created: Vue组件生命周期钩子。
fetch(): 与asyncData一样,也是用于调用接口获取数据,不同的是它不会将返回值合并到data,一般用于对本地数据处理,比如Vuex,值得一提的是,这个钩子在Vue实例创建之后执行,因此可以用this访问Vue实例。
执行beforeMount、mounted等其他Vue的生命周期钩子。
以上生命周期中,只有前两个是完全在中间层执行的,其余的有可能在中间层执行,也有可能在客户端执行,这主要取决于页面是首屏渲染还是站内跳转,因此搞懂哪些代码什么时候在什么环境运行非常重要。
插件
vant-ui
项目中使用了vant ui作为组件库,Nuxt项目中没有类似main.js的入口文件,如果需要安装依赖,需要在plugins中声明。
每次访问Nuxt站点的首屏时,都会将nuxt.config.js中声明的plugins执行一遍,从而让开发这可以把自己所需的插件注册到应用中
'@/plugins/vant-ui'
在根目录的plugins目录下需要创建一个对应的文件
'vue'
'vant'
为了按需引入,还需要安装babel-plugin-import和进行相关配置
true
'import'
'vant'
${name}
'vant'
'@button-primary-background-color'
'#000'
axios
Nuxt官方提供了专门封装的@nuxtjs/axios模块,看过文档后发现与平常的用法略有不同,闲麻烦就还是用了原汁原味的axios,毕竟此前也做了进一步的封装(官方强烈推荐的模块尽量能用就用,像我这种不听话的就会默默踩坑,经过探索才悟出了下面这段话)。但是与SPA不同的是,axios发起的请求可能是在中间层服务端,也可能是在客户端,这取决于是否是首屏渲染(在上面生命周期有提到),因此需要在代码中利用process.client和process.server对相应的环境做出判断和处理。
'axios'
'vant'
'../nuxt.config'
export
source
return
return
function
createAxios
'/api'
if
return
return
if
if
''
else
return
return
if
if
case
'请先登录'
break
case
'您的操作被拒绝'
break
case
'未找到资源'
break
case
'系统出错了'
break
return
if
'请求取消'
return
if
'timeout'
'网络超时,请重试'
return
if
'请检查网络'
return
else
'未知错误'
return
else
''
return
export
添加一个插件将nuxt context挂载到axios实例上,用于出错时跳转到错误页面,此外需要记得在nuxt.config.js中声明此插件。
'@/utils/request'
export
Vuex持久化
在SPA中,通常会将token存储在localStorage中,但是访问SSR站点首屏时,需要在中间层做登录等权限验证,无法获取到客户端存在localStorage中的数据。但是可以将其存在cookie中,利用cookie的特性,在访问站点时将其带到中间层,于是中间层就可以获取cookie中的数据做权限验证,并且将其填充进Vuex供客户端使用。
首先安装vuex-persistedstate和js-cookie,把Vuex中的数据同步到cookie,然后写一个插件将vuex-persistedstate注入到Vuex中(别忘了在nuxt.config.js中声明)。
'vuex-persistedstate'
'js-cookie'
export
if
return
return
然后在nuxtServerInit()这个生命周期钩子中读取访问时的cookie。
'./mutation-types'
export
''
export
export
if
return
这样一来,就可以在后续的Middleware、validate() 等钩子通过context.store获取到所需的数据了。
此外,为了方便管理,我在文件中引入了/store/mutation-types.js,默认情况下Nuxt会将/store目录下的.js文件当作一个Vuex的模块,因此需要配置一下Nuxt的忽略文件,让它忽略掉mutation-types.js。
# /.nuxtignore
# ignore store mutation types
使用SCSS
为了更舒服地编写CSS,当然需要一个CSS预处理器!为了能让通用的.scss(变量、mixin等)能够用在任何组件中使用,需要借助@nuxtjs/style-resources模块实现,第一步安装,第二步配置。
'@nuxtjs/style-resources'
function
'@/assets/scss/_variables.scss'
'@/assets/scss/_functions.scss'
'@/assets/scss/_mixins.scss'
代理
由于浏览器的安全机制,会拦截跨域的AJAX请求,为了解决跨域问题,可以设置代理,而这次的代理可以不是Nginx了,可以直接用中间层作为代理,为客户端请求数据。安装完@nuxtjs/proxy之后进行配置即可。
'@nuxtjs/proxy'
'/api'
'https://xxx.com'
'^/api'
'/'
自定义入口文件
入口文件的主要作用是启动服务和初始化Nuxt核心类,Nuxt已经将入口文件封装好并隐藏了,看不到也改不了,不过我们可以自己把这两件事情做了,让入口文件在自己掌控之下,变得更具有扩展性。
'nuxt'
'express'
'cookie-parser'
'./nuxt.config'
'production'
function
start
'dev'
'start'
in
if
'Server listening on `localhost:'
'`.'
然后在package.json中修改一下启动命令。
"scripts"
"start"
"node server.js"
结语
由于项目还处在初期阶段,能不能继续做下去还不知道,所以项目规模非常有限,还有许多没有涉及到的点,如果大家有补充或者发现有误的地方,可以点击阅读原文去作者文章下面纠正,谢谢观看。
点击左下角阅读原文,到
SegmentFault 思否社区
和文章作者展开更多互动和交流。
- END -
原文链接
出品 | 深度学习这件小事公众号 如需转载,请联系后台授权 月18日更新版) [1] Reconstructing Hand-Object Interactions in the Wild 作者 | Zhe Cao, Ilija Radosavovic, Angjoo Kanazawa, Jitendra Malik 链接 | https://arxiv.org/abs/2012.09856 项目链接 | https://people.eecs.berkeley.edu/~zhecao/rhoi/ [2] Infinite Nature: Perpetual View Generation of Natural
作者 | Nadiya Dubyna 译者 | Sambodhi 策划 | 刘燕 本文探讨了 IT 项目经理的角色和挑战。 项目经理的角色和职责是什么 就像管弦乐队中的指挥一样,项目经理要确保一切都计划好、执行好、结束好,一切都正常。这种人是团队和利益相关者之间的桥梁。职责范围包括项目团队、资源分配和业务成果。制定目标、选择正确的方法、进度控制,并根据变化做出调整是项目经理执行的主要职责。从 Web 和 移动应用程序 开发到网络配置和安全,IT 领域的项目多种多样。 几乎所有领域都涉及到信息技术:制造业、娱乐业、医疗业、教育业等等,这就增加了软件项目管理的复杂性,因为它需要掌握特定于行业的知识。在本文中,我们将概述 IT 项目经理的角色和挑战。 基本要素 无论从哪个角度来看,这个职位都是非常苛刻的: