首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用 Nuxt.js 搭建一个服务端渲染(SSR)应用

用 Nuxt.js 搭建一个服务端渲染(SSR)应用

作者头像
用户4456933
发布2021-06-01 15:36:58
7.3K0
发布2021-06-01 15:36:58
举报

客户端渲染(CSR)的含义

客户端渲染模式下,服务端把渲染的静态文件给到客户端,客户端拿到服务端发送过来的文件自己跑一遍 JS,根据 JS运行结果,生成相应 DOM,然后渲染给用户。

前端渲染的方式起源于 JavaScript 的兴起,ajax 的大热更是让前端渲染更加成熟,前端渲染真正意义上的实现了前后端分离,前端只专注于 UI 的开发,后端只专注于逻辑的开发,前后端交互只通过约定好的API来交互,后端提供 json 数据,前端循环 json 生成 DOM 插入到页面中去。

大多数平台采用的是客户端渲染,查看首页的源代码会发现代码里的 html 结构只有简单的几句。当请求首页面时,返回的 body 为空,之后执行 js 将 html 结构注入到 body 里,结合 css 显示出来;

<body>
    <div id=app></div>
    <script type=text/javascript src=/static/js/manifest.9476fbe0d0f0fe7c5038.js></script>
</body>

客户端渲染(CSR)的优缺点

  • 优点:网络传输数据量小、减少了服务器压力、前后端分离、局部刷新,无需每次请求完整页面、交互好可实现各种效果
  • 缺点:不利于SEO、爬虫看不到完整的程序源码、首屏渲染慢(渲染前需要下载一堆js和css等)

服务端渲染(SSR)的含义

服务端渲染: 当用户第一次请求页面时,由服务器把需要的组件或页面渲染成 HTML 字符串,然后把它返回给客户端。客户端拿到手的,是可以直接渲染然后呈现给用户的 HTML 内容,不需要为了生成 DOM 内容自己再去跑一遍 JS 代码。使用服务端渲染的网站,可以说是“所见即所得”,页面上呈现的内容,我们在 html 源文件里也能找到。如下,我们查看网页源码的时候,可以看到全部内容。

服务端渲染(SSR)的优缺点

  • 优点:首屏渲染快、利于SEO、可以生成缓存片段,生成静态化文件、节能(对比客户端渲染的耗电)
  • 缺点:服务端压力较大

什么情况下使用服务端渲染

通过服务端渲染的概念以及它的两个特点:首屏加载速度快SEO优化。我们知道,服务端渲染其实就是由浏览器做的一些事情,我们放到了服务端去做。关于在 server 端还是在 browser 端渲染的选择,更多的是要看业务场景。

常用框架介绍

服务端渲染框架应用有Nuxt.jsBeidou(北斗) 等。

Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。

Beidou(北斗) 是 NodeJS & React 同构框架,基于Egg.js开发。

尝试了这两个框架,对比觉得Nuxt.js更简单易上手,下面就用Nuxt.js搭建一个服务端渲染应用来介绍下 Nuxt.js 的用法。

创建一个 SSR 项目

为了快速入门,Nuxt.js团队创建了脚手架工具 create-nuxt-app

npx create-nuxt-app nuxtdemo

它会让你进行一些选择,比如集成的服务器端框架、喜欢的UI框架、测试框架、添加 axios、Eslint、 Prettier 等。根据项目需求进行选择就好了。这里以服务器框架选择None (Nuxt默认服务器),UI框架选择Element UI为例进行讲解。

勾选完毕后,它将安装所有依赖项,因此下一步是直接启动项目:

cd nuxtdemo
npm run dev

这时候我们可以看到一个默认简易的项目搭建完成啦,如下所示:

接下来,我们来看下整个项目的目录结构

├── assets               未编译的静态资源如 LESS、SASS 或 JavaScript
├── components           组件,不会像页面组件那样有 asyncData 方法的特性
├── layouts              布局目录 layouts 用于组织应用的布局组件
├── middleware           用于存放应用的中间件
├── nuxt.config.js       用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置
├── package.json         用于描述应用的依赖关系和对外暴露的脚本接口
├── pages                用于组织应用的路由及视图
├── plugins              存放需要在根vue.js应用实例化之前需要运行的JS插件
├── static               用于存放应用的静态文件(不会被webpack编译处理)
├── store                应用的 Vuex 状态树

了解了每个文件的作用,我们来用Nuxt.js搭一个简单的网站吧。用一个简单的网站,讲解下 Nuxt.js 的基础用法。

Nuxt.js 入门

我们用 Nuxt.js 来搭一个常用的网页框架,包括公共头部、底部、动态路由、嵌套路由,错误页面,以及在 Nuxt.js 框架下如何引用公共样式、公共方法、路由校验等。先放上网站成品图

下载链接:

git clone git@code.aliyun.com:echomaps/nuxtdemo.git

这是个简易的网站,包括公共头部跟尾部。首页是一个文章列表,采用了动态路由,点进去可以跳到对应的文章。人员介绍页面采用了嵌套路由。在左侧点击人员,右侧可以相应出来人员的信息。好,让我们来开始吧。

布局

一般网站都有公共的头部、底部。在之前的项目中,我们都得手动去引入头部、尾部组件。如下:

import header from '@/publicResource/components/header.vue'
import footer from '@/publicResource/components/footer.vue'

export default {
    components: {
        'v-header': header,
        'v-footer': footer
    }
}

但在 Nuxt.js 中就不用这么麻烦。我们直接在 layout 目录下创建自定义的布局。修改 layouts/default.vue 文件来扩展应用的默认布局

<template>
    <div>
        <v-header></v-header>
        <nuxt />
        <v-footer></v-footer>
    </div>
</template>

<script>
import Header from '~/components/Header.vue'
import Footer from '~/components/Footer.vue'
export default {
    components: {
        'v-header': Header,
        'v-footer': Footer
    },
    data () {
        return { }
    }
}
</script>

<nuxt/> 组件用于显示页面的主体内容。这样所有的页面都会自动带上头部、尾部,不用特意声明与引入。如果有些页面布局不需要头部、尾部,这也很简单,我们只需要告诉页面使用哪个自定义布局即可。

<template>
<!-- Your template -->
</template>
<script>
export default {
    layout: 'blog'
    // page component definitions
}
</script>

错误页面

我们也可以通过编辑 layouts/error.vue 文件来定制化错误页面。这个布局文件不需要包含 <nuxt/> 标签。可以把这个布局文件当成是显示应用错误(404,500等)的组件。

<template>
    <div class="error-wrap">
        <p v-if="error.statusCode === 404" class="info">页面不存在</p>
        <p class="info" v-else>应用发生错误异常</p>
        <p><nuxt-link to="/">首 页</nuxt-link></p>
    </div>
</template>
    
<script>
    export default {
        props: ['error'],
    }
</script>

基础路由

Nuxt.js中不用编写路由配置文件,只需要按照API规定命名与存放文件,即可自动生成路由配置文件。例如,我们需要新增一个人员介绍页面users. 只需要在pages下新增users页面,就可以自动生成路由。假设 pages 的目录结构如下:

pages/
--| users.vue
--| index.vue

那么,Nuxt.js 自动生成的路由配置如下:

router: {
    routes: [
        {
            name: 'index',
            path: '/',
            component: 'pages/index.vue'
        },
        {
            name: 'users',
            path: '/users',
            component: 'pages/users.vue'
        }
    ]
}

其它页面引用的时候,直接用nuxt-link即可

<nuxt-link to="/users">人员介绍</nuxt-link>

同样地,我们也可以通过框架规定的命名、存放文件。无需配置路由,可生成动态路由、嵌套路由的配置文件。

动态路由

在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。如下所示:

├── pages
├────── blogs
│         └─── _blog.vue  博客的详情页
├────── index.vue         首页

假如我们在index.vue中编写一个文章列表并链接到对应的文章页面,如下:

<template>
    <div class="container">
        <div class="bm-sider">
            {{content}}
        </div>
        <div class="bm-con">
            <ul>
                <li><nuxt-link to="blogs/1">这是文章1</nuxt-link></li>
                <li><nuxt-link to="blogs/2">这是文章2</nuxt-link></li>
                <li><nuxt-link to="blogs/3">这是文章3</nuxt-link></li>
            </ul>
        </div>
    </div>
</template>

pages/blogs/_blog.vue

<template>
    <div class="container">
        这是内容{{$route.params.blog}}
    </div>
</template>

<script>
    export default {
        components: {},
        data () {
            return { }
        },
        validate ({ params }) {
            return !isNaN(+params.blog)
        }
    }
</script>

这样,默认首页的展示如下:

当点击具体文章时候,展示如下:

我们还可以添加 validate 配置一个校验方法用于校验动态路由参数的有效性。如果校验方法返回的值不为 true 或 Promise 中 resolve 解析为 false 或抛出 Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。这里我们设置只有数字可以正常访问,其它路由将跳到错误页面。如下所示:

嵌套路由

创建内嵌子路由,需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。在父组件(.vue文件) 内增加用于显示子视图内容。

人员介绍页面采用了嵌套路由。点击左侧的人员名单,将出现对应的人员信息,效果如下:

实现这一效果,我们需要在 pages下添加人员介绍页面 users.vue

<template>
    <div class="container">
        <div class="bm-sider">
            <ul class="players">
                <li v-for="user in users" :key="user.id">
                    <NuxtLink :to="'/users/'+user.id">
                        {{ user.name }}
                    </NuxtLink>
                </li>
            </ul>
        </div>
        <div class="bm-con">
            <NuxtChild :key="$route.params.id" />
        </div>
    </div>
</template>

同时添加一个与该文件同名的目录用来存放子视图组件。文件如下命名:

├── users
│   ├── _id.vue   点击人员后对应的人员信息组件 
│   └── index.vue 默认的视图组件    
└── users.vue   人员介绍页面

users/index.vue

<template>
    <h2>Please select an user.</h2>
</template>

users/_id.vue

<template>
    <div class="player">
        <h1>#{{ number }}</h1>
        <h2>{{ name }}</h2>
    </div>
</template>

<script>
export default {
    validate ({ params }) {
        return !isNaN(+params.id)
    },
    asyncData ({ params, env, error }) {
        const user = env.users.find(user => String(user.id) === params.id)
        if (!user) {
            return error({ message: 'User not found', statusCode: 404 })
        }
        return user
    },
    head () {
        return {
            title: this.name
        }
    }
}
</script>

这样,当我们未点击人员时候,人员介绍默认页面是这样的:

点击人员后,人员介绍页面将展示对应的人员信息内容:

全局 css

在 Nuxt 中添加全局 css 也是非常简单的。我们在 assets 下新建一个 css 文件 base.css 。然后在 nuxt.config.js 中引用即可。

css: [
    '~assets/base.css',
],

全局方法

将内容注入 Vue 实例,避免重复引入,在 Vue 原型上挂载注入一个函数,所有组件内都可以访问。

plugins/vue-inject.js:

import Vue from 'vue'

Vue.prototype.$myInjectedFunction = (string) => console.log("This is an example", string)

这样,我们就可以在所有Vue组件中使用该函数。

example-component.vue:

export default {
    mounted(){
        this.$myInjectedFunction('test')
    }
}

总结

Nuxt.js 是使用 Webpack 和 Node.js 进行封装的基于 Vue 的 SSR 框架,使用它,你可以不需要自己搭建一套 SSR 程序,而是通过其约定好的文件结构和API就可以实现一个首屏渲染的 Web 应用。整体上,Nuxt.js 通过各个文件夹和配置文件的约束来管理我们的程序,而又不失扩展性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 大海我来了 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 客户端渲染(CSR)的含义
    • 客户端渲染(CSR)的优缺点
    • 服务端渲染(SSR)的含义
      • 服务端渲染(SSR)的优缺点
        • 什么情况下使用服务端渲染
        • 常用框架介绍
        • 创建一个 SSR 项目
        • Nuxt.js 入门
          • 布局
            • 错误页面
              • 基础路由
                • 动态路由
                  • 嵌套路由
                    • 全局 css
                      • 全局方法
                      • 总结
                      相关产品与服务
                      消息队列 TDMQ
                      消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档