随着互联网的快速发展,越来越多的网站开始采用 SPA(Single Page Application)单页面应用架构,这种架构需要大量的 JavaScript 代码来实现前端交互和数据处理。但是 SPA 应用对搜索引擎优化存在一定的挑战,因为搜索引擎爬虫无法解析 JavaScript 代码和 AJAX 异步请求,这就导致了 SPA 应用的 SEO 不尽如人意。为了解决这个问题,我们可以使用服务器端渲染(SSR)来实现在服务端生成 HTML 内容,以提高网站的 SEO 效果。
Vue.js 是当今最流行的前端框架之一,其具有轻量、易用、灵活等优点,并且它也支持服务器端渲染。下面我们将详细介绍如何在 Vue.js 中实现服务器端渲染。
搭建 Vue.js 项目
首先,我们需要搭建一个 Vue.js 项目,如果已经有一个现成的项目可以忽略这一步。
我们可以通过 Vue CLI 来创建一个新项目,执行以下命令:
vue create my-project
然后我们选择 Manually select features,使用空格键选择需要的 feature,这里选择了 Babel、Vuex 和 Router。创建完成后,我们可以启动项目并在浏览器中查看效果:
cd my-project npm run serve
这里只是简单介绍如何创建一个 Vue.js 项目,后续的实现均在这个项目中进行。
安装相关依赖
在项目中安装以下依赖:
npm install vue-server-renderer npm install express
其中:
- vue-server-renderer:Vue.js 提供了一个服务器端渲染的插件,我们可以通过该插件生成 HTML 内容并返回给客户端。
- express:是 Node.js 中一个常用的轻量级框架,它可以帮助我们搭建一个简单的 Node.js 服务器,供客户端访问。
创建服务器端渲染中间件
在项目根目录下创建一个新文件 server.js
,并在该文件中实现服务器端渲染中间件。
// javascriptcn.com 代码示例 const fs = require('fs') const path = require('path') const express = require('express') const serverBundle = require('./dist/server/vue-ssr-server-bundle.json') const clientManifest = require('./dist/client/vue-ssr-client-manifest.json') const renderer = require('vue-server-renderer').createBundleRenderer(serverBundle, { runInNewContext: false, template: fs.readFileSync('./public/index.html', 'utf-8'), clientManifest }) const server = express() server.use('/dist', express.static(path.join(__dirname, 'dist'))) server.get('*', (req, res) => { const context = { url: req.url } renderer.renderToString(context, (error, html) => { if (error) { console.error(error) res.status(500).end('Internal Server Error') return } res.end(html) }) }) server.listen(8080, () => { console.log('SSR server is running at port 8080') })
该中间件文件主要做了以下几件事:
- 引入必要的模块:
fs
、path
、express
和vue-server-renderer
。 - 使用
fs
模块读取public/index.html
内容,并将其作为 Vue.js 生成页面的模板。 - 使用
vue-server-renderer
模块中的createBundleRenderer
方法创建一个渲染器,该方法需要传入两个参数,一个是打包后在服务端生成的 JavaScript 资源文件(vue-ssr-server-bundle.json
),另一个是打包后在客户端使用的 JavaScript 资源文件(vue-ssr-client-manifest.json
)。 - 创建一个 Express 服务器,并将打包后的静态资源文件
dist
目录挂载到/dist
路径上。 - 使用
server.get
方法注册一个路由中间件,该路由中间件使用renderer.renderToString
方法将 Vue.js 应用渲染为 HTML,并返回给客户端。
到此为止,我们已经创建了一个用于服务端渲染的 Node.js 中间件,该中间件监听 8080 端口,任何客户端发起的请求都将返回经过 Vue.js 服务器端渲染生成的 HTML。
修改客户端入口
在上一步中,我们通过 createBundleRenderer
方法创建了一个渲染器,其中传入的客户端渲染资源是从 vue-ssr-client-manifest.json
文件中读取的。因此,我们需要将 public/index.html
中的客户端 JavaScript 引用修改为使用打包后的资源。
打开 public/index.html
,将 <script>
标签的 src
属性改为 src="<%=process.env.NODE_ENV==='production'?'/dist/client/':'http://localhost:8080'/}js/app.js"
:
// javascriptcn.com 代码示例 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Vue SSR</title> </head> <body> <div id="app"></div> <script src="<%=process.env.NODE_ENV==='production'?'/dist/client/':'http://localhost:8080'/}js/app.js"></script> </body> </html>
该更改表示,根据当前环境选择加载客户端渲染资源,如果是在生产环境中,则使用 /dist/client/js/app.js
中的打包的资源;如果是在开发环境中,则使用 http://localhost:8080/js/app.js
中的资源。
构建项目
现在我们已经实现了一个用于服务端渲染的中间件,下一步就是对项目进行打包构建。
执行以下命令:
npm run build
该命令将会对项目进行打包构建,生成一个 dist
目录下的客户端打包资源和服务器端打包资源,其中服务器端打包资源是 vue-ssr-server-bundle.json
文件。
启动服务
执行以下命令启动服务:
node server.js
该命令将会启动一个服务器,监听 8080 端口,并在客户端发起请求时返回经过 Vue.js 服务器端渲染生成的 HTML。
总结
本文详细介绍了如何在 Vue.js 中使用服务器端渲染,步骤包括:
- 创建 Vue.js 项目
- 安装相关依赖
- 创建服务器端渲染中间件
- 修改客户端入口
- 构建项目
- 启动服务
相信经过这些步骤的实践,我们已经掌握了使用 Vue.js 实现服务器端渲染的方法,可以将服务端渲染应用到实际项目中,从而提高网站的 SEO 效果,并为用户带来更好的使用体验。
示例代码
Vue.js 项目地址:https://github.com/vuejs-templates/webpack-simple 服务器端代码:
// javascriptcn.com 代码示例 const fs = require('fs') const path = require('path') const express = require('express') const serverBundle = require('./dist/server/vue-ssr-server-bundle.json') const clientManifest = require('./dist/client/vue-ssr-client-manifest.json') const renderer = require('vue-server-renderer').createBundleRenderer(serverBundle, { runInNewContext: false, template: fs.readFileSync('./public/index.html', 'utf-8'), clientManifest }) const server = express() server.use('/dist', express.static(path.join(__dirname, 'dist'))) server.get('*', (req, res) => { const context = { url: req.url } renderer.renderToString(context, (error, html) => { if (error) { console.error(error) res.status(500).end('Internal Server Error') return } res.end(html) }) }) server.listen(8080, () => { console.log('SSR server is running at port 8080') })
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654b03d67d4982a6eb4f67b7