vuecli项目构建SSR服务端渲染的实现

下面是关于“vuecli项目构建SSR服务端渲染的实现”的完整攻略:

1. 什么是SSR?

SSR全称Server Side Rendering(服务端渲染),意思是将页面在服务器端进行渲染,然后再将已渲染的页面传输给客户端展示出来。

SSR的好处:

  • 更快的页面渲染速度,减少白屏时间
  • 更好的SEO(搜索引擎优化)
  • 更好的用户体验

2. Vue CLI 3 如何构建 SSR 服务端渲染应用?

Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供了项目的创建、编译、运行、构建等一系列功能的工具。

如果你想要构建一个 SSR 应用,可以使用Vue CLI脚手架提供的插件和配置进行构建。

2.1 安装 Vue CLI 3

首先,你需要安装 Vue CLI 3。在命令行中输入:

npm install -g @vue/cli

安装成功后,可以通过输入 vue --version 命令查看版本号,确保安装成功。

2.2 创建一个 SSR 应用

使用 Vue CLI 创建一个 SSR 应用非常简单,只需要在命令行中输入以下命令:

vue create my-ssr-app

其中,my-ssr-app 为创建的项目名称,你可以根据自己的需要进行修改。

在创建项目时,会有一个提示让你选择“需要预安装一些特性吗?”。这里我们选择 Manually select features,然后按下回车键。

在下一步中,除了选择 BabelRouter 这两个基础选项外,我们还需要选择 Server-Side Rendering (SSR)Vuex 这两个选项。

最后,按照提示完成项目的创建。

2.3 配置 SSR

项目创建完成后,需要进一步配置才能使其支持 SSR。

2.3.1 添加服务器文件

首先,在项目的根目录下创建一个 server.js 文件,并添加以下代码:

const fs = require('fs')
const path = require('path')
const express = require('express')
const server = express()

const resolve = file => path.resolve(__dirname, file)

const bundleRenderer = require('vue-server-renderer').createBundleRenderer(
  resolve('./dist/server-bundle/vue-ssr-server-bundle.json'), {
    runInNewContext: false,
    template: fs.readFileSync(resolve('./public/index.html'), 'utf-8')
  }
)

server.use('/dist', express.static(resolve('./dist')))

server.get('*', (req, res) => {
  const context = {
    title: 'Vue SSR Demo',
    url: req.url
  }

  bundleRenderer.renderToString(context, (err, html) => {
    if (err) {
      console.error(err)
      res.status(500).end('Internal Server Error')
      return
    }

    res.end(html)
  })
})

const port = process.env.NODE_ENV === 'production' ? 80 : 8080

server.listen(port, () => {
  console.log(`Server started at http://localhost:${port}`)
})

其中,server.js 文件定义了一个节点服务器,并使用 vue-server-renderer 提供的 createBundleRenderer 创建了一个渲染器实例。在 server.get 里面,通过 vue-server-renderer 提供的 renderToString 进行服务端渲染。

2.3.2 添加打包配置

为了使打包生成的文件可以在服务器上运行,我们需要添加一些打包配置。

打开根目录下的 vue.config.js 文件,添加以下配置:

const path = require('path')

module.exports = {
  configureWebpack: {
    entry: {
      app: './src/entry-server.js'
    },
    output: {
      libraryTarget: 'commonjs2'
    },
    target: 'node',
    resolve: {
      alias: {
        '@': path.join(__dirname, './src')
      }
    }
  },

  chainWebpack: config => {
    config.plugins.delete('html')
    config.plugins.delete('preload')
    config.plugins.delete('prefetch')

    config
      .entry('app')
      .clear()
      .add('./src/entry-client.js')
      .end()

    config.output.filename('assets/js/[name].js')
    config.output.chunkFilename('assets/js/[name].js')

    config.optimization.splitChunks(false)
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        options.optimizeSSR = false
        return options
      })
  }
}

其中,configureWebpack 中的配置项用于配置 Webpack,chainWebpack 是链式操作,可以修改 Webpack 中的默认配置。配置项的具体含义可以查看 Vue SSR 文档。

2.3.3 修改入口文件

src 目录下分别创建 entry-client.jsentry-server.js 文件,其中 entry-client.js 的内容默认已经生成,不需要修改。而 entry-server.js 需要添加以下内容:

import { createApp } from './main'

export default context => {
  const app = createApp()

  // 设置服务器端 router 的位置
  const router = app.$router
  router.push(context.url)

  context.meta = app.$meta()

  return new Promise((resolve, reject) => {
    router.onReady(() => {
      const matchedComponents = router.getMatchedComponents()

      if (!matchedComponents.length) {
        return reject({ code: 404 })
      }

      Promise.all(matchedComponents.map(Component => {
        if (Component.asyncData) {
          return Component.asyncData({
            store: app.$store,
            route: router.currentRoute
          })
        }
      })).then(() => {
        context.state = app.$store.state
        resolve(app)
      }).catch(reject)
    }, reject)
  })
}

3. 示例说明

接下来给出两个示例说明:

3.1 实例1

假设你需要从服务器获取一些数据,然后在页面中进行展示。你可以在组件生命周期函数中通过 axios 库发起请求,获取数据,然后在渲染函数中使用该数据。

在服务器端渲染中,由于没有浏览器环境,页面组件不会像在浏览器中一样被实例化和挂载到页面中,所以在服务器端需要在渲染函数执行之前先获取数据,并将这些数据提供给组件。

// Home.vue

<script>
export default {
  name: 'Home',

  asyncData ({ store }) {
    return store.dispatch('fetchData') // 从服务器获取数据
  },

  computed: {
    items () {
      return this.$store.state.items // 获取数据
    }
  },

  template: `<div>{{ items }}</div>`
}
</script>

其中,asyncData 是一个静态方法,它会在组件被实例化之前调用,从服务器获取数据后,将数据存储到 Vuex store 中,然后在组件的 computed 中以数据的形式注入到组件中。

3.2 实例2

假设你需要在服务器端进行一些路由控制,比如根据用户的权限判断是否能够访问某个页面。你可以在渲染函数执行之前先验证路由信息,然后再渲染页面。

// Auth.vue

<script>
export default {
  name: 'Auth',

  asyncData ({ store, route }) {
    if (route.path === '/admin' && !store.state.isAuthenticated) { // 判断用户是否已登录
      return Promise.reject({ code: 401, message: 'Unauthorized' }) // 如果用户未登录,跳转到401页面
    }
  },

  template: `<div>Welcome, Admin!</div>`
}
</script>

asyncData 函数中,获取用户的登录状态,并根据登录状态判断用户是否有权限访问此页面。如果用户未登录,我们可以返回一个 promise,然后在渲染函数执行之后,将 promise.reject 返回的错误对象交给错误处理程序处理,最终跳转到相应的错误页面。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vuecli项目构建SSR服务端渲染的实现 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • 详解使用vuex进行菜单管理

    对于“详解使用Vuex进行菜单管理”的完整攻略,以下是步骤和示例说明: 1. 确定Vuex的状态管理 在使用Vuex进行菜单管理之前,需要确定有哪些状态需要在Vuex中进行管理。在本教程中,我们需要管理的状态有: 菜单数据:用于渲染整个菜单。 当前菜单项:用于存储当前选择的菜单项,以便在页面中高亮显示。 打开的菜单项:用于存储当前展开的菜单项。 你可以在Vu…

    Vue 2023年5月27日
    00
  • vue强制刷新组件的方法示例

    下面是对于 “vue强制刷新组件的方法示例” 的详细讲解攻略: Vue 强制刷新组件方法 在 Vue 中,当我们需要对组件进行强制刷新时,可以使用以下两种方式: 使用 key 属性 Vue 中,每个组件都可以设置一个 key 属性,当组件的 key 值改变时,组件会被强制重新渲染。 例如, <template> <div> <b…

    Vue 2023年5月29日
    00
  • 详解vue.js根据不同环境(正式、测试)打包到不同目录

    要根据不同环境(正式、测试)打包到不同目录,我们可以使用webpack进行配置。 首先,在项目根目录下创建一个config文件夹,里面创建三个文件:dev.env.js、prod.env.js、index.js。 dev.env.js文件内容如下: module.exports = { NODE_ENV: ‘"development"’,…

    Vue 2023年5月28日
    00
  • 使用Vue3进行数据绑定及显示列表数据

    下面我将详细讲解使用Vue3进行数据绑定及显示列表数据的完整攻略。 步骤一:创建Vue对象 首先,需要使用createApp方法创建Vue实例,并通过mount方法将Vue实例挂载到页面上。示例代码如下: “`html <div id="app"> <ul> <li v-for="item in …

    Vue 2023年5月28日
    00
  • Flowable中定时器的玩法详解

    Flowable中定时器的玩法详解 在Flowable中,定时器是一个非常有用的机制,通过它可以实现一些定时执行的任务,比如定时发送邮件、自动归档数据等等。本文将详细介绍Flowable中定时器的使用方法。 什么是定时器 定时器是在流程执行的某个节点上设置一个定时器,然后在设定的时间点上自动执行某些动作的机制。比如,我们可以设置一个定时器,在一个任务节点上,…

    Vue 2023年5月28日
    00
  • Vue异步更新DOM及$nextTick执行机制解读

    Vue异步更新DOM及$nextTick执行机制解读 在 Vue 中,DOM 更新并不是同步执行的,除非使用 this.$nextTick 方法,它可以保证在本次 DOM 更新后执行回调函数,下面我就来详细解读这个机制。 异步更新DOM Vue 在进行 DOM 更新时,通常借助浏览器的异步更新机制,将多个数据变更合并为一次更新,以提高更新效率。这个机制体现在…

    Vue 2023年5月29日
    00
  • Vue实现答题功能

    Vue 实现答题功能的完整攻略包含以下步骤: 步骤一:设计数据结构 在 Vue 实现答题功能之前,我们首先需要设计数据结构。数据结构应该包含题目、选项、答案等信息。例如,以下是一个选择题的数据结构: const questions = [ { question: ‘以下哪个不是JavaScript的数据类型?’, options: [‘Undefined’,…

    Vue 2023年5月27日
    00
  • 基于 vue-skeleton-webpack-plugin 的骨架屏实战

    让我来详细讲解“基于 vue-skeleton-webpack-plugin 的骨架屏实战”的完整攻略。 简介 随着客户端应用的普及以及前端性能要求的不断提高,页面骨架屏方案得到了广泛的应用。Vue.js 作为目前最受欢迎的前端框架之一,也有很多骨架屏方案可供选择。在这里,我们以 vue-skeleton-webpack-plugin 为例,介绍使用骨架屏实…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部