关于前端spa项目seo优化改造方案(预渲染,ssr,nuxt比较)
目前的的前端项目为基于vuecli3搭建的spa项目,由于需求提出需要对首页,部分内容页面做seo优化,涉及到前端项目的框架和部分页面的改造。
目录
SEO简介
SEO(Search Engine Optimization):汉译为搜索引擎优化。利用搜索引擎的规则提高网站在有关搜索引擎内的自然排名。目的是让其在行业内占据领先地位,获得品牌收益。
搜索引擎判断一个网站权重高低的尺度无非两个:收录和链接。
目前百度spider抓取新链接的途径有两个:
一是主动出击发现抓取
二就是从百度站长平台的链接提交工具中获取数据,其中通过主动推送功能“收”上来的数据最受百度spider的欢迎。
关于收录
- 完整的head信息
<head> <title>PKS信创产业生态平台-为PKS生态建设赋能</title> <meta name="description" content="PKS信创产业生态平台是国内第一个PKS线上适配平台、第一个基于飞腾2000+ cpu的公有云服务、第一个以PKS为核心的知识内容平台,能为PKS生态合作伙伴、开发者和终端用户提供多样性PKS生态支撑性服务,提升生态服务能力。"> <meta name="keyword" content="PKS信创产业生态平台,信创,飞腾云主机,麒麟操作系统,自主云服务器,PKS适配迁移,飞腾处理器"> </head>
- 良好的页面语义化
<header id="header" class="web"> <h1 id="logo"> <a href="/" target="_blank" title="鹏翔书画装裱培训">书画字画装裱培训_裱字裱画学习 - 山东曹州(菏泽)鹏翔书画装裱培训中心</a> </h1> </header> <nav id="nav" class="web_"> <ul class="web"> <li class="nav_home"><a href="/" class="nav_on">网站首页</a></li> <li><a href="/single_About_1.html">中心简介</a></li> <li><a href="/article_ZhuangBiaoZhiShi_2.html">装裱知识</a></li> <li><a href="/article_ZhuangBiaoZaTan_3.html">装裱杂谈</a></li> <li><a href="/article_ZhuangBiaoZhaoSheng_4.html">招生信息</a></li> <li><a href="/ZhuangBiao_ZhuangBiaoZuoPin_5.html">装裱作品</a> </li><li><a href="/video_ZhuangBiao_6.html">装裱视频</a></li> <li><a href="/ZhuangBiao_ZhuangBiaoJiaoXue_7.html">现场教学</a></li> <li><a href="/article_zhuanyejieshao_10.html">专业介绍</a></li> <li><a href="/single_contact_8.html">联系我们</a></li> </ul> </nav> <section id="banner" class="cf"> <ul> <li> <img src="/image/banner1.jpg" alt="三分画,七分裱——书画字画装裱的艺术魅力"> </li> <li> <img src="/image/banner2.jpg" alt="继承传统技法,发扬中华文化——鹏翔书画装裱培训"> </li> </ul> </section>
- 内容 [ol] 有固定的更新频率。最起码也要一周一篇内容的更新。否则,搜索引擎会判断你的网站是死站,权重就会下降的。这里需要注意的是频率,不要一次性更新很多,然后很长时间不更新。
- 内容一定要有原创性。
- 坚持更新。每一条都要设置关键词和描述,并且不雷同。
- 如果是图片类内容的添加,一定要附注一些图片相关的文字内容。搜索引擎自己识别图片内容的效率非常低下,因此文字是不可缺少的。
- 视频或者其他媒体内容,比照图片处理。
关于链接
链接分为三种,一种是网站内部的链接,简称内链。比如从首页进入栏目页面,从栏目页面进入内容页面。第二种是网站外部链接,简称外站链接。第三种是别人的网站给你的网站的链接,简称外链。下面我逐一阐述。
- 网站内链设计
在网站内,尽量让网页形成交叉的网状链接设计。很多企业网站在设计得时候,到达了内容页面之后,只能返回到列表页面再进入另外一条内容,这样的树状链接设计是低效的。
简单的做法是在内容页面加上“上一篇”、“下一篇”这样的链接,可以让蜘蛛从一个内容页面直接进入另一个内容页面。从而达到网状内链的目的。
但是仅仅是如此是不够的。我个人建议在内容页面下面最好加上一个“相关内容”的模块,里面可以罗列一些与内容相关的其他的内容链接,十条还是二十条随便,根据排版来即可。
有条件的话,可以让这部分内容是活的,也就是随机的。这样爬虫进来的时候,会不断的得到不同的内容,从而抓取到更多的内容。 - 外站链接设计
一句话总结,尽可能的少。尽量让蜘蛛来到你的网站后,就在你的网站里面转圈,走不出去才好。 - 外链设计
一句话总结,尽可能的多! 基础做法是和其他站长交换友情链接,进阶做法是花钱买一些外链。但要注意的是,要找同类型的网站或者相关的站点来做。 - 这里有一个误区是将所有的外链都指向你的网站的首页。这也不是不可以,但是我们还可以做得更好一些,就是有针对的链接到你的特定内容的内页,效果会更好。比如,你提供某服务项目,你有一个内页是专门介绍这个项目的,那么在其他站点增加一个链接到你这个内页,效果也是很好的。
- 如果你有较强的内容生产能力,可以写一些优秀的文章,然后让其他网站转载你的文章,并标注首发地址是你的这个文章的网址,这样效果会很好的。
- 还有就是找大型网站做软文,比如写一些公司的创办理念,创始人的介绍等等,全部都链接到你的网站,效果也是很好的。
目前前端所面临的的问题是内容无法被爬虫获取,页面的title,keyword,descriptions等无法动态变化
经过调研后,目前有以下几种解决方案提供:
一、预渲染
构建阶段生成匹配预渲染路径的 html 文件(注意:每个需要预渲染的路由都有一个对应的 html)。构建出来的 html 文件已经有静态数据,需要ajax数据的部分未构建。
如果你调研服务器端渲染 (SSR) 只是用来改善少数营销页面(例如首页,关于我们,联系我们 等)的 SEO,那么你可能需要预渲染。
- 增加prerender-spa-plugin puppeteer两个依赖
npm install prerender-spa-plugin puppeteer
- 修改vue.config.js
config.plugins.push( new PrerenderSPAPlugin({ // 生成文件的路径,也可以与webpakc打包的一致。 // 下面这句话非常重要!!! // 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。 staticDir: path.join(__dirname, 'dist'), // Optional - The location of index.html // indexPath: path.join(__dirname, '../dist', 'index.html'), // 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。 routes: ['/', '/school'], // 预渲染代理接口 // server: { // proxy: { // '/api': { // target: 'http://localhost:9018', // secure: false // } // } // }, // 这个很重要,如果没有配置这段,也不会进行预编译 renderer: new Renderer({ // headless: false, renderAfterDocumentEvent: 'render-event', // 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。 args: ['--no-sandbox', '--disable-setuid-sandbox'] }) }) )
- 在入口main.js中添加
new Vue({ router, store, // 添加mounted,不然不会执行预编译 mounted() { document.dispatchEvent(new Event('render-event')) }, render: h => h(App) }).$mount('#app')
- 运行打包命令npm run build后根据配置出现文件
- 放到nginx中进行测试,效果如图
总结:
- 配合vue-meta-info可以针对spa的vue项目配置单独的title,meta,keyword,descriptions等
- 预渲染无法渲染异步加载的数据
- 配置简单,开箱即用,对原有框架基本没有影响
- 需要路由为history模式
二、ssr服务端渲染
在 2.3 发布后我们发布了一份完整的构建 Vue 服务端渲染应用的指南。这份指南非常深入,适合已经熟悉 Vue、webpack 和 Node.js 开发的开发者阅读。请移步 ssr.vuejs.org
与传统 SPA (单页应用程序 (Single-Page Application)) 相比,服务器端渲染 (SSR) 的优势主要在于:
- 更好的 SEO,由于搜索引擎爬虫抓取工具可以直接查看完全渲染的页面。
请注意,截至目前,Google 和 Bing 可以很好对同步 JavaScript
应用程序进行索引。在这里,同步是关键。如果你的应用程序初始展示 loading 菊花图,然后通过 Ajax
获取内容,抓取工具并不会等待异步完成后再行抓取页面内容。也就是说,如果 SEO
对你的站点至关重要,而你的页面又是异步获取内容,则你可能需要服务器端渲染(SSR)解决此问题。
- 更快的内容到达时间 (time-to-content),特别是对于缓慢的网络情况或运行缓慢的设备。无需等待所有的 JavaScript 都完成下载并执行,才显示服务器渲染的标记,所以你的用户将会更快速地看到完整渲染的页面。通常可以产生更好的用户体验,并且对于那些「内容到达时间(time-to-content) 与转化率直接相关」的应用程序而言,服务器端渲染 (SSR) 至关重要。
针对spa项目的修改(vue-cli3):
- 引入相关依赖
npm install vue-server-renderer lodash.merge webpack-node-externals cross-env --registry=https://registry.npm.taobao.org --save-dev
- 在根目录下新建server.js
服务端使用koa2
npm install koa koa-static --save --registry=https://registry.npm.taobao.org
// server.js // 第 1 步:创建一个 Vue 实例 const Vue = require("vue"); const Koa = require("koa"); const app = new Koa(); // 第 2 步:创建一个 renderer const renderer = require("vue-server-renderer").createRenderer(); // 第 3 步:添加一个中间件来处理所有请求 app.use(async (ctx, next) => { const vm = new Vue({ data: { title: "ssr example", url: ctx.url }, template: `<div>访问的 URL 是: {{ url }}</div>` }); // 将 Vue 实例渲染为 HTML renderer.renderToString(vm, (err, html) => { if(err){ ctx.res.status(500).end('Internal Server Error') return } ctx.body = html }); }); const port = 3000; app.listen(port, function() { console.log(`server started at localhost:${port}`); });
- 新增template.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>Document</title> </head> <body> <!--vue-ssr-outlet--> </body> </html>
修改main.js
// main.js import Vue from 'vue' import App from './App.vue' import { createRouter } from "./router"; // 导出一个工厂函数,用于创建新的 // 应用程序、router 和 store 实例 export function createApp () { const router = createRouter(); const app = new Vue({ router, // 根实例简单的渲染应用程序组件。 render: h => h(App) }) return { app,router } }
创建entry-client.js文件
import { createApp } from './main' // 客户端特定引导逻辑…… const { app } = createApp() // 这里假定 App.vue 模板中根元素具有 `id="app"` app.$mount('#app')
创建entry-server.js文件
import { createApp } from "./main"; export default context => { // 因为有可能会是异步路由钩子函数或组件,所以我们将返回一个 Promise, // 以便服务器能够等待所有的内容在渲染前, // 就已经准备就绪。 return new Promise((resolve, reject) => { const { app, router } = createApp(); // 设置服务器端 router 的位置 router.push(context.url); // 等到 router 将可能的异步组件和钩子函数解析完 router.onReady(() => { const matchedComponents = router.getMatchedComponents(); // 匹配不到的路由,执行 reject 函数,并返回 404 if (!matchedComponents.length) { return reject({ code: 404 }); } // Promise 应该 resolve 应用程序实例,以便它可以渲染 resolve(app); }, reject); }); };
- 修改router.js
import Vue from 'vue' import Router from 'vue-router' import Home from './views/Home.vue' Vue.use(Router) export function createRouter(){ return new Router({ mode: 'history', //一定要是history模式 routes: [ { path: '/', name: 'home', component: Home }, { path: '/about', name: 'about', component: () => import(/* webpackChunkName: "about" */ './views/About.vue') } ] }) }
- 修改vue.config.js,增加服务端渲染相关配置
// vue.config.js const VueSSRServerPlugin = require("vue-server-renderer/server-plugin"); const VueSSRClientPlugin = require("vue-server-renderer/client-plugin"); const nodeExternals = require("webpack-node-externals"); const merge = require("lodash.merge"); const TARGET_NODE = process.env.WEBPACK_TARGET === "node"; const target = TARGET_NODE ? "server" : "client"; module.exports = { css: { extract: process.env.NODE_ENV === 'production' }, configureWebpack: () => ({ // 将 entry 指向应用程序的 server / client 文件 entry: `./src/entry-${target}.js`, // 对 bundle renderer 提供 source map 支持 devtool: 'source-map', target: TARGET_NODE ? "node" : "web", node: TARGET_NODE ? undefined : false, output: { libraryTarget: TARGET_NODE ? "commonjs2" : undefined }, // https://webpack.js.org/configuration/externals/#function // https://github.com/liady/webpack-node-externals // 外置化应用程序依赖模块。可以使服务器构建速度更快, // 并生成较小的 bundle 文件。 externals: TARGET_NODE ? nodeExternals({ // 不要外置化 webpack 需要处理的依赖模块。 // 你可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件, // 你还应该将修改 `global`(例如 polyfill)的依赖模块列入白名单 whitelist: [/\.css$/] }) : undefined, optimization: { splitChunks: undefined }, plugins: [TARGET_NODE ? new VueSSRServerPlugin() : new VueSSRClientPlugin()] }), chainWebpack: config => { config.module .rule("vue") .use("vue-loader") .tap(options => { merge(options, { optimizeSSR: false }); }); // fix ssr hot update bug if (TARGET_NODE) { config.plugins.delete("hmr"); } } };
- 修改package.json,增加三个脚本
"build:client": "vue-cli-service build", "build:server": "cross-env WEBPACK_TARGET=node vue-cli-service build --mode server", "build:win": "npm run build:server && move dist\\vue-ssr-server-bundle.json bundle && npm run build:client && move bundle dist\\vue-ssr-server-bundle.json",
- 运行打包命令和启动服务
npm run build:win
node server.js
- store的引入和router基本一致,导出createStore方法并在main.js中引入即可
参考文章:
https://juejin.im/post/5b98e5875188255c8320f88a
总结:
- 对原有框架变动较大,路由,store,请求方式,打包方式均需修改
- 涉及较多nodejs知识,对不熟悉node.js的同学可能比较吃力
三、nuxt
从头搭建一个服务端渲染的应用是相当复杂的。幸运的是,我们有一个优秀的社区项目 Nuxt.js
让这一切变得非常简单。Nuxt 是一个基于 Vue 生态的更高层的框架,为开发服务端渲染的 Vue 应用提供了极其便利的开发体验。更酷的是,你甚至可以用它来做为静态站生成器。推荐尝试。
原理图:
1、用户打开浏览器,输入网址请求到Node.js
2、部署在Node.js的应用Nuxt.js接收浏览器请求,并请求服务端获取数据
3、Nuxt.js获取到数据后进行服务端渲染
4、Nuxt.js将html网页响应给浏览器
- 修改思路
- 路由直接放在pages文件夹下,相当于做了多入口配置
- 异步数据的获取通过asyncData方法获得
- 页面布局放在layouts文件夹下
- 每个页面都需要的js放在plugins下
- 区别
- 相较于预渲染,nuxt可以处理异步数据的获取
- 相较于ssr改造,框架搭建更加简便,社区资源更加丰富,开发中遇到困难更容易找到解决办法
- 将seo优化的页面单独抽离成项目,独立部署,和其余项目并行开发,实现解耦
样例效果图,返回的文件已经有了动态数据,更有利于seo爬虫的获取
- 公共组件的处理(构建自己的包管理仓库,组件打成npm包进行引用)
- 在公司内部服务器上搭建npm代码仓库(sinopia,pm2)
- 将一些公共组件如头部,尾部以及基本框架(包含登录,权限逻辑)直接以组件形式打成npm包和脚手架并发布至内部仓库中
- 在项目中运行
npm i xxx
安装依赖,避免了大量的重复代码和合并过程中的繁琐操作(只需修改依赖版本号即可)
- 公共依赖的处理(webpack打lib包)
- 将所有项目中共同用到的第三方依赖库通过webpack的library打成一个js,放在内部服务器中
- 之后如果有做cdn加速将大幅提高页面加载速度和打包构建速度
- 基于vue现有项目的服务器端渲染SSR改造
- 前端框架Vue(17)——基于 Vue.js 的服务端渲染 (ssr) 通用应用框架 Nuxt.js
- 自己动手搭建react-ssr服务器端渲染项目架构
- 网络改造项目方案规划与实践报告
- 关于前端vue项目设置请求头权限问题
- 关于baosteel 1800改造项目
- XX行关于联机交易(OLTP)系统类项目的性能测试技术方案
- XX行关于联机交易(OLTP)系统类项目的性能测试技术方案(2)
- 收录了一篇关于项目管理九大知识领域的比较详细的教程~
- 关于Jeecg互联网化dubbo改造方案(下)
- 关于前端页面js和jqery的一些比较常用的小知识点
- WEB前端:关于项目管理的思考
- 关于开源项目管理软件的比较:Basecamp vs Trac vs Redmine,Redmine胜出
- 前端架构之路(9) - 服务器端渲染(SSR)与 node 中间层
- Vue 爬坑之路(十一)—— 基于 Nuxt.js 实现服务端渲染(SSR)
- 对比分析--浅析SSR(服务端渲染)和SPA(客户端渲染)
- 关于四种XML解析方案的比较:DOM,SAX,JDOM,DOM4J
- 服务器用户权限管理改造方案及项目实施
- 两个关于前端开发的比较不错的PPT
- nuxt的使用(一款vue基于服务器SSR渲染工具)