详解Vue SSR服务端渲染

Vue SSR介绍

SSR Github Demo

什么是服务器端渲染?

Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记"激活"为客户端上完全可交互的应用程序。

为什么使用服务器端渲染 (SSR)?

与传统 SPA (单页应用程序 (Single-Page Application)) 相比,服务器端渲染 (SSR) 的优势主要在于:

更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记,所以你的用户将会更快速地看到完整渲染的页面。

SSR渲染过程

image.png

我们可以看到,左侧Source部分就是我们所编写的源代码,所有代码有一个公共入口,就是app.js,紧接着就是服务端的入口
(entry-server.js)和客户端的入口(entry-client.js)。当完成所有源代码的编写之后,我们通过webpack的构建,打包出两个bundle,分别是server bundle和client bundle;当用户进行页面访问的时候,先是经过服务端的入口,将vue组建组装为html字符串,并混入客户端所访问的html模板中,最终就完成了整个ssr渲染的过程。

Nuxt框架

Nuxt 是一个基于 Vue 生态的更高层的框架,为开发服务端渲染的 Vue 应用提供了极其便利的开发体验。更酷的是,你甚至可以用它来做为静态站生成器。

nuxt官网介绍

安装

// init过程中根据提示安装用到的插件灯
npm init nuxt-app <project-name>

cd <project-name>
npm run dev

配置

nuxt.config.js

const path = require('path')
export default {
  // 允许你在`Javascript`和`Css`中使用别名访问自定义目录
  alias: {
    '~~': `<rootDir>`,
    '@@': `<rootDir>`,
    '~': `<srcDir>`,
    '@': `<srcDir>`,
    'assets': `<srcDir>/assets`, // (unless you have set a custom `dir.assets`)
    'static': `<srcDir>/static`, // (unless you have set a custom `dir.static`)
    'style': path.resolve(__dirname, './assets/style')
  },

  // 定义应用程序的工作区目录,默认值process.cwd()
  rootDir: '',

  // 定义应用程序的source目录,默认值同rootDir
  srcDir: '',

  // server连接配置
  server: {
    port: 3000, // default: 3000
    host: '0.0.0.0', // default: localhost,
    timing: false
  },

  // npm run generate时执行,构建部署静态应用程序
  generate: {
    // 目录名
    dir: 'dist'
  },

  // true启动服务器端渲染,false只启动客户端渲染
  ssr: true,

  // headers设置,Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    title: 'ssr-demo',
    htmlAttrs: {
      lang: 'en'
    },
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      { hid: 'description', name: 'description', content: '' }
    ],
    link: [
      { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
    ]
  },

  // 全局css,Global CSS: https://go.nuxtjs.dev/config-css
  css: [
    // 'ant-design-vue/dist/antd.css'
    // css后缀可以省略
    'assets/style/common'
  ],

  // 添加plugins目录下的js文件到应用程序中,Plugins to run before rendering page: https://go.nuxtjs.dev/config-plugins
  plugins: [
    '@/plugins/antd-ui',
    '@/plugins/veui'
  ],

  // 自动扫描和导入组件,无需在使用时import组件,可直接使用,Auto import components: https://go.nuxtjs.dev/config-components
  components: true,

  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
    // 是否提取css至独立文件中
    // extractCSS: true,
    // babel相关配置
    babel: {
      plugins: [
        'veui',
        ['import', {
          'libraryName': 'ant-design-vue',
          'libraryDirectory': 'es',
          'style': true
            // customStyleName: name => {
            //   return `assets/${name}.css`
            // }
          }
        ] // `style: true` 会加载 less 文件
      ]
    },
    // 可省略的扩展名
    resolve: {
      extensions: ['.js', '.vue', '.json']
    },
    // 需要进行babel编译的包
    transpile: ['veui', 'vue-awesome', 'ant-design-vue'],
    // loader配置
    loaders: {
      vue: {
        extractCSS: true
      },
      less: {
        javascriptEnabled: true
      }
    },
    // 手动扩展客户端和服务端的webpack配置
    extend(config, context){
        //添加loader规则
          config.module.rules.push({
              test: /\.vue$/, //匹配.svg
              include: [path.resolve(__dirname, 'node_modules/veui')], //将存放svg的目录加入到loader处理目录
              use: [{ loader: 'veui-loader', options: {
                modules: [
                  {
                    package: 'veui-theme-blue',
                    fileName: '${module}.less'
                  },
                  {
                    package: 'veui-theme-blue',
                    fileName: '${module}.js',
                    transform: false
                  }
                ]
              }}]
          })
    }
  }
}

Demo示例

1. ssr: true,服务端渲染

服务端渲染时,可以看到入口返回的Preview就是在服务端生成好的页面,这种方式更利于SEO和快速展示页面。


image.png

2. ssr: false,客户端渲染

客户端渲染时,可以看到入口返回的Preview是一个空白页面,页面的Dom是由提取的其他js在浏览器端动态生成的。


image.png

3. BundleRenderer自动内联关键CSS(critical css)

关于critical css的介绍,可以看另一篇文章:https://juejin.cn/post/6946475178188603429/
pages/index.vue为首屏渲染页面

<template>
    <div class="index">首页</div>
</template>
<style>
.index {
    color: red;
}
</style>

新建pages/test.vue页面,验证SSR是否会自动注入关键css(critical css

<template>
    <div class="test">测试</div>
</template>
<style>
.test {
    color: red;
}
</style>
  • index.vue中引入test.vue,服务启动后,test.vue样式也以style形式内嵌在页面中
    image.png
  • 不在index.vue中引入test.vue,服务启动后,test.vue样式则没有内嵌在首屏渲染页面中
    image.png

    只有在访问test路由时才显示test.vue相关样式
    image.png

总结:SSR服务端会自动注入首屏渲染关键css,无需引入其他插件。

4. extract提取css

启用extract提取css后,样式被提取到单独的css文件中,以外链的形式引入。

image.png

以上就是Vue SSR nuxt框架相关的整理,每天都有学不完的新知识,加油!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,312评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,578评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,337评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,134评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,161评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,303评论 1 280
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,761评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,421评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,609评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,450评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,504评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,194评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,760评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,836评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,066评论 1 257
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,612评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,178评论 2 341

推荐阅读更多精彩内容