[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图1

这篇文章旨在通过一个小的 demo, 来回答三个问题:

  1. 什么是 Nuxt.js。
  2. 如何启用一个Nuxt.js 项目。
  3. 如何构建一个通用的 ssr 项目。

一、什么是 Nuxt.js

如果你在用 React ,那么你一定知道 React 的服务端渲染应用框架 Next.js 。同样的基于 Vue.js 的 Nuxt.js 也是用于服务端渲染。
我们知道现在非常流行的客户端渲染的 web 开发方式,SPA(single page web application)单页应用。我们打包上线,只需要一个 index.html 和一个包含了各种静态资源的 static 文件夹,页面跳转靠路由,所有的东西全在一个 app.js 文件中。
这导致了单页面也存在着缺点:1、首屏加载慢,白屏。2、不利于 SEO。
这里我们就引出了,为什么需要有 Nuxt.js 这样的服务端渲染框架。Nuxt 的出现有效的解决了客户端渲染的单页面上述的两个问题。
详细介绍请参考官方文档


我们来看看客户端/服务端渲染的直观差异吧:

  1. URL:
  2. 客户端:http://localhost:8080/#/findMusicComponent
  3. 服务端:http://localhost:3000/recipes/2
  4. 路径的差距体现在,#上。

推荐文章:https://segmentfault.com/a/11…

  1. 源代码:
  2. 客户端:
  3. <body><div id="app"></div><!-- built files will be auto injected --><script type="text/javascript" src="/app.js"></script></body>
  4. 服务端:
  5. <body data-n-head=""><div data-server-rendered="true" id="__nuxt"><div class="nuxt-progress" style="width:0%;height:2px;background-color:#3B8070;opacity:0;"></div><div id="__layout"><div><header data-v-46cf1d15><nav data-v-46cf1d15><ul data-v-46cf1d15><li data-v-46cf1d15><a href="/" class="nuxt-link-active" data-v-46cf1d15>Starting Page</a></li><li data-v-46cf1d15><a href="/recipes" class="nuxt-link-active" data-v-46cf1d15>Recipes</a></li><li data-v-46cf1d15><a href="/About" data-v-46cf1d15>About</a></li></ul></nav></header><section class="single-recipe"><h1>Delicious vigetable</h1><div class="recipe-image"><img src="https://images.pexels.com/photos/5938/food-salad-healthy-lunch.jpg" alt="Awesome vigetable"></div><p>This is a awesome vigetable</p></section></div></div></div><script type="text/javascript">window.__NUXT__={"layout":"default","data":[{"recipe":{"id":"2","title":"Delicious vigetable","previewText":"Awesome vigetable","descriptionText":"This is a awesome vigetable","thumbnail":"https:\u002F\u002Fimages.pexels.com\u002Fphotos\u002F5938\u002Ffood-salad-healthy-lunch.jpg"}}],"error":null,"state":{},"serverRendered":true};</script><script src="/_nuxt/manifest.js" defer></script><script src="/_nuxt/layouts_default.js" defer></script><script src="/_nuxt/pages_recipes__id_index.js" defer></script><script src="/_nuxt/vendor.js" defer></script><script src="/_nuxt/app.js" defer></script></body>
  6. 从源代码 body 的差异,就能知道为什么客户端渲染模式的单页面不利于 SEO,内容极少,对浏览器爬虫不友好。

推荐文章:https://segmentfault.com/q/10…

三、如何启用一个Nuxt.js 项目

首先,在看这篇文章之前,我认为您已经安装了 Node 和 NPM, 并且有了一定的 Vue 基础。

第一种

  1. 1npm install create-nuxt-app
  2. 2create-nuxt-app your-app-name

[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图2
可一路回车。
3、初始化完成后,我们会得到这样的目录结构:
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图3
每一个文件夹代表的什么,可参考官方文档。
4、package.json 中记录着我们需要的信息,npm run dev 开始我们的 demo 吧

  1. {
  2. "name": "recipes",
  3. "version": "1.0.0",
  4. "description": "My outstanding Nuxt.js project",
  5. "author": "allen",
  6. "private": true,
  7. "scripts": {
  8. "dev": "nuxt",
  9. "build": "nuxt build",
  10. "start": "nuxt start",
  11. "generate": "nuxt generate"
  12. },
  13. "dependencies": {
  14. "nuxt": "^1.0.0"
  15. },
  16. "devDependencies": {
  17. "cross-env": "^5.0.1"
  18. }
  19. }

第二种

需要你安装过 vue-cli 官方脚手架,比较懒方法文档中已给出,截图参考。
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图4
打开localhost:3000,如果你进行到一下截图的阶段,那么恭喜你,可以正式开发了!
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图5

三、如何构建一个通用的 ssr 项目

先来看一下 demo 的截图吧:
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图6
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图7
大体的结构:三个一级栏目(开始页、菜单栏、关于页),一个二级菜单(每道菜的详情页)。
在这边主要想讲一下,动态路由实现根据菜品的 id 参数跳转详情页。这和我们平时想法是一致的:首先在菜单栏中,点击某一个菜品,拿到对应的 id,然后跳转到详情页,向服务端进行异步请求,获取对应的 id 的菜品详情资料,最后在前端进行数据渲染。

  1. 我们需要实现的效果可以在 URL 上体现:
  2. 菜单栏:http://localhost:3000/recipes
  3. Vigetablehttp://localhost:3000/recipes/2
  4. Pizaahttp://localhost:3000/recipes/1

官网上对于动态路由有这样的一段:
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图8
ok,现在我建一个以下划线为开头的详情的目录:
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图9
_id 为详情目录,所有目录中的 index.vue 都是默认首页。
*详情页源码:

  1. /**
  2. * @Description: recipe
  3. */
  4. <template>
  5. <section class="single-recipe">
  6. <h1>{{ recipe.title }}</h1>
  7. <div class="recipe-image">
  8. <img :src="recipe.thumbnail" :alt="recipe.previewText">
  9. </div>
  10. <p>{{ recipe.descriptionText }}</p>
  11. </section>
  12. </template>
  13. <script>
  14. export default {
  15. /**
  16. * @description data from server
  17. */
  18. asyncData (context) {
  19. return new Promise((resolve, reject) => {
  20. setTimeout(() => {
  21. resolve({
  22. recipe: [{
  23. id: '1',
  24. title: 'Delicious Pizza',
  25. previewText: 'Awesome Pizza',
  26. descriptionText: 'This is a nice Pizza',
  27. thumbnail: 'https://static.pexels.com/photos/326278/pexels-photo-326278.jpeg'
  28. },
  29. {
  30. id: '2',
  31. title: 'Delicious vigetable',
  32. previewText: 'Awesome vigetable',
  33. descriptionText: 'This is a awesome vigetable',
  34. thumbnail: 'https://images.pexels.com/photos/5938/food-salad-healthy-lunch.jpg'
  35. }].find(el => el.id === context.params.id)
  36. });
  37. }, 1500)
  38. })
  39. }
  40. }
  41. </script>
  42. <style>
  43. .single-recipe
  44. {
  45. display: flex;
  46. flex-flow: column;
  47. justify-content: center;
  48. align-items: center;
  49. text-align: center;
  50. padding: 30px;
  51. }
  52. .recipe-image img
  53. {
  54. width: 80%;
  55. }
  56. </style>

关键点就是 context.params.id,这就是每个菜品的 id,我这边是 new Promise 异步请求数据,正式的你是通过拿到 id,请求后台该 id 下唯一的详情数据。
看一下动态路由下 build 出来的 router.js 部分:
[VUE 应用] 服务端渲染 (ssr) 通用应用框架 Nuxt.js - 图10
结论:只要根据 Nuxt.js 提供的路由规范,会让页面路由切换很轻松。
最后在发一下 Github 上的完整 Demo:可参考 Demo (nuxt-demo)
结语:希望我的文章能让你了解一些关于 Nuxt.js 的内容,或者开始认识 Nuxt.js。文章比较浅,如果你在未来想将服务端渲染应用到项目中,官方文档你需要详看。

参考

  1. Nuxt.js 官网
  2. Github(Nuxt.js)
  3. 可参考 Demo (nuxt-demo)
  4. 学习视频(YouTube 需翻墙)