使用node+vue.js实现SPA应用,解决了SPA应用的最大缺点SEO

news/2024/4/28 11:56:55/文章来源:https://blog.csdn.net/weixin_34409822/article/details/89438499

业务需求

最近公司要求开发web版的app,由于app是偏向内容方面,而且带了一个聊天模块,所以一般的多页开发不是很适合,而且主要是手机浏览,对加载速度或者用户体验来说都比较苛刻。调研了很多框架和模式,最后自己东拼西凑搞出来了这么一个玩意。

UI框架 :淘宝SUI

服务端

毫无疑问使用node,使用typescript可以有效的在编码同时查错,强类型语言写服务端毫无压力。


#app.ts 只贴重要代码var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var WebpackConfig = require('./webpack.config')import * as index from "./server/routes/index";
import * as cookbook from "./server/routes/cookbook";
import * as cookbookDetail from './server/routes/cookbookDetail'var app = express();//启动服务的时候 打包并监听客户端用到的文件,webpackDevMiddleware是开发模式,他会打包js在内存里面,你改了文件,它也会重新打包
app.use(webpackDevMiddleware(webpack(WebpackConfig), {publicPath: '/__build__/',stats: {colors: true}
}));//一般的配置项
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.set('view options', { layout: false });
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(express.static(__dirname + '/public'));var env = process.env.NODE_ENV || 'development';
if (env === 'development') {app.use(errorHandler());
}//路由配置
app.get('/cookbook', index.index);
app.get('/cookbook/:id', cookbook.index);
app.get('/cookbookDetail/:id', cookbookDetail.index);app.listen(3000, function(){console.log("Demo Express server listening on port %d in %s mode", 3000, app.settings.env);
});export var App = app;

服务端渲染页面

#index.ts
import express = require("express")
import vueServer = require("vue-server") //服务端渲染vue的插件
import request = require('request'); //第3方http请求的插件
import queryString = require('querystring'); //转换get参数的插件var Vue = new vueServer.renderer(); //创建一个服务端的vueexport function index(req: express.Request, res: express.Response) {let vm:vueServer,b:Object,options:Object;options = {method: 'GET',//随便用了一个免费的API,是查询菜谱的url: 'http://apis.baidu.com/tngou/cook/classify?'+queryString.stringify({id : 0,}),headers: {//百度API的开放接口凭证'apikey': 'a369f43a6392605426433831e10765ec'}};request(options,function(err,resp,body){if (!err && resp.statusCode == 200) {b = JSON.parse(body);vm = new Vue({replace : false,template : `<div><!-- 标题栏 --><header class="bar bar-nav"><a class="icon icon-me pull-left open-panel"></a><h1 class="title">{{title}}</h1></header><!-- 这里是页面内容区 --><div class="content"><div class="list-block"><ul><li class="item-content" v-for="item in cookbookClasses"><div class="item-media"><i class="icon icon-f7"></i></div><div class="item-inner"><div class="item-title">{{item.title}}</div></div></li></ul></div></div></div>`,data : {title : '菜谱首页',cookbookClasses: b.tngou,}});}//等待html渲染完成,再返回给浏览器 vueServer.htmlReady是vue-server的自带事件vm.$on('vueServer.htmlReady', function(html:string) {//这里用的是ejs模板 可以把需要用到的数据设置成window下的全局变量,方便客户端的js访问。res.render('layout',{server_html:html,server_data:`window.cm_cookbookClasses = {title : '菜谱首页',cookbookClasses: ${JSON.stringify(b.tngou)}}`})});});
}
#layout.ejs  访问这个SPA的所有url返回的都是这个页面 <meta>标签都可以动态设置,只要传参数进来就可以
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,initial-scale=1.0,user-scalable=no"><title>Vue Router Example</title><link rel="stylesheet" href="//g.alicdn.com/msui/sm/0.6.2/css/??sm.min.css,sm-extend.min.css"><style type="text/css">//注释掉的是vue-router切换的动画, 通过transition,transition-mode设置/*.test-transition {*//*transition: all .5s ease;*//*}*//*.test-enter, .test-leave {*//*opacity: 0;*//*transform: translate3d(10px, 0, 0);*//*}*/h2{font-size: 1rem;}p{font-size: .8rem;}img{max-width: 100%;}</style><script>//定义一些前端需要用到的全局属性,文章ID或用户信息什么的//index.ts中传过来的是 window.cm_data = {name:"张三"}//前端就能访问到了<%-server_data%></script>
</head>
//这里的id是前端需要用到的一个标识
<body id="app">
<div class="page-group"><div class="page page-current">//router-view是客户端vue-router需要解析的dom//server_html是根据访问url地址生成的html,是做SEO的重点,不加载下面的js也可以看到内容<router-view transition="test" transition-mode="out-in"><%-server_html%></router-view></div>
</div>//这里用到了淘宝团队的UI框架SUI,各种组件都有。它依赖zepto
<script type='text/javascript' src='//g.alicdn.com/sj/lib/zepto/zepto.min.js' charset='utf-8'></script>
<script type='text/javascript' src='//g.alicdn.com/msui/sm/0.6.2/js/??sm.min.js,sm-extend.min.js' charset='utf-8'></script>//webpack打包好的js,主要是路由配置
<script src="/__build__/app.js"></script>
</body>
</html>

客户端

#app.js 这个是/__build__/app.js,可以用es6编写,webpack会转换的import Vue from './vue.min' //客户端的vue.js
import VueRouter from './vue-router.min' //vue的路由插件,配合webpack可以很简单实现懒加载
import VueResource from './lib/vue-resource.min'    //懒加载路由 只有访问这个路由才会加载jsimport Index from 'bundle?lazy!./routes/index' //配合webpack的bundle-loader,轻松实现懒加载
import Cookbook from 'bundle?lazy!./routes/Cookbook'
import CookbookDetail from 'bundle?lazy!./routes/cookbookDetail'var App = Vue.extend({})Vue.use(VueResource)
Vue.use(VueRouter)//百度API需要用到的参数
Vue.http.headers.common['apikey'] = 'a369f43a6392605426433831e10765ec';var router = new VueRouter({//这里要好好说一下,一定要设置html5模式,不然前后端URL不统一会发生问题//比如访问 http://localhost:3000/ 服务端定义是访问index.ts这个路由文件//如果不是html5模式的话,经过客户端js运行之后会变成http://localhost:3000/#!///在比如直接浏览器输入 http://localhost:3000/foo 服务端定义是访问.ts这个路由文件//如果不是html5模式的话,经过客户端js运行之后会变成 http://localhost:3000/foo/#!///设置了html5模式后,加载完js后不会加上#!这2个类似锚点的字符,实现前后端路由统一如果用户刷新浏览器的话,服务端也能渲染出相应的页面。history: true, //html5模式 去掉锚点 saveScrollPosition: true //记住页面的滚动位置 html5模式适用,实际使用下来没用
})//定义路由,要和服务端路由路径定义的一样
router.map({'/'   : {component: Index //前端路由定义,},'/cookbook/:id': {component: Cookbook},'/cookbookDetail/:id': {component: CookbookDetail}
})
router.redirect({'*': '/cookbook'
})
//启动APP
router.start(App, '#app')

客户端路由

#index.js  这里的模板和服务端的差不多,就增加了@click操作
'use strict';
import Vue from '../lib/vue.min'let Index = Vue.extend({//replace : false, //必须注释掉 不然动画失效template : `<div><!-- 标题栏 --><header class="bar bar-nav"><a class="icon icon-me pull-left open-panel"></a><h1 class="title">{{title}}</h1></header><!-- 这里是页面内容区 --><div class="content"><div class="list-block"><ul><li class="item-content" v-for="item in cookbookClasses" @click="goCookbook(item.id)"><div class="item-media"><i class="icon icon-f7"></i></div><div class="item-inner"><div class="item-title">{{item.title}}</div></div></li></ul></div></div></div>`,data : ()=>{return {title : '菜谱首页',cookbookClasses : []}},methods: {goCookbook(id){//vue-router 路由跳转this.$router.go('/cookbook/'+id);}},//vue-router的属性,可以设置路由的生命周期,具体请查文档route : {//应该是在渲染DOM之前获取数据data : function(transition) {//如果是服务端渲染的,应该设置全局变量,那么客户端就不用异步请求数据了if(window.cm_cookbookClasses){this.$data = window.cm_cookbookClasses;transition.next();}else{let qa_id = 0;//使用vue-resource来获取数据var resource = this.$resource('http://apis.baidu.com/tngou/cook/classify');$.showPreloader(); //这个是显示SUI的加载遮罩层resource.get({id: qa_id}).then((response)=>{$.hidePreloader();if(response.status == 200){this.$data = {title : '菜谱首页',cookbookClasses : response.data.tngou}transition.next();}else{transition.abort();}});}},canActivate: function(){},// 激活状态 把上一次记录的数据,获取出来,需要deactivate状态配合。activate: function (transition) {this.$data = window.cm_cookbookClasses;transition.next()},// 禁用状态 记录这一次的数据,方便以后再进入激活状态可以不用访问网络请求数据deactivate: function (transition) {window.cm_cookbookClasses = this.$data;transition.next()}}
})export default Index

需要完善的地方

  1. 前后端统一模板,已经找到方法了把html分离出来,node端用fs.readFileSync方法获取,客户端用webpack的raw-loader获取html内容

  2. 安卓微信浏览器 vue-resource 设置了headers的apikey,但请求的时候没有带上,导致获取不到数据。

  3. IOS safari浏览器 渲染页面有问题,渲染20条数据,只显示10条左右,监听不到SUI无限滚动到底部的事件

不放源码都是瞎扯。

源码地址 最新的是分支V0.0.1 是个简单的菜谱DEMO

https://github.com/yjj5855/node-vue-server-webpack

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_767796.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux下的php网站放到Windows服务器IIS下导入 .htaccess文件伪静态规则转换 (wordpress)...

需要特别注意的是&#xff1a; 1. .htacdess文件在 wordpress中 是可以生成的 安装 WP Super Cache后&#xff0c;开启该插件>>设置>>高级>>找到并点击"更新Mod_Rewrite 规则"按钮&#xff0c;这是会在网站根目录生成 .htaccess文件 将该文件导入到…

hviewer添加新站点_新站点如何快速的被百度SEO收录

关于新站点如何快速的被百度SEO收录&#xff0c;是很多网站优化人员在网站刚刚上线时为关注和烦恼的一个问题。并且收录的快慢可能会导致排名上线快慢&#xff0c;也成了领导或者客服频繁追问的一件事&#xff0c;那如何通过使用百度链接提交工具快速的收录我们的新站呢?1.验证…

网站上传服务器一直404,vue打包上传服务器刷新404问题的两种方案

一&#xff1a;nginx服务器解决方案&#xff0c;修改 .conf 配置文件有两种解决方案1&#xff1a;location / {try_files $uri $uri/ router;index index.html;}location router {rewrite ^.*$ /index.html last;}2&#xff1a;location / {error_page 404 /index.html;#try…

asp抓取网页某个标签内的_做好站内SEO优化,关键词排名更稳定

很多优化师抱怨SEO不好做&#xff0c;关键词排名上不去、不稳定或不持续等&#xff0c;认为这一切都和搜索引擎本身有关。但云优化认为&#xff0c;这些都和你的SEO站内优化策略有关。关键词排名确实存在很多不确定因素&#xff0c;即使再牛的SEO大拿也无法保证关键词百分百上首…

php 503解决办法,宝塔linux面板 切换PHP版本后,网站访问报错503 Service Unavailable解决...

切换PHP版本后&#xff0c;网站访问报错503503 Service UnavailableService UnavailableThe server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.1.检查网站对应的php版本进程是否已经启动。(这…

快速生成网站

实验条件&#xff1a; 已经搭建好LAMP 环境 &#xff08;使用一键安装lamp&#xff09;关闭selinux 关闭防火墙 下载依赖包 gcc gcc-c make 具体步骤 &#xff1a; 下载 lnmp安装包 解压 ./install.sh lamp安装完毕后登入&#xff1a;http://服务器ip/phpcms 直接…

佳速互联教您在深圳如何才能找到合适的网站设计公司

网站建设公司鱼龙混杂&#xff0c;在网建行业中&#xff0c;深圳公司相对较多&#xff0c;建站水平相差也甚远&#xff0c;从公司规模看&#xff0c;有三五个人小公司&#xff0c;也有上百人公司。从设计师月薪资看&#xff0c;有3K多&#xff0c;也有几W。办公场所有的很偏僻&…

github怎么自动更新被人更新过的项目_github + hexo 小白超快搭建功能强大的个人博客网站(1)...

1. 一些必备软件1.1 github 账户1.2 下载nodejs2 按照Hexo3. 将hexo本地博客 推送到github 仓库里1. 一些必备软件1.1 github 账户如果没有到话&#xff0c;首先去github官网[1]去注册一个账户(有的话&#xff0c;相信你懂这个网站&#xff0c;这部分你可以跳过)按部就班地填写…

php网站更新流程,【PHP开辟框架】thinkphp5升级步骤

ThinkPHP5.0升级5.1全纪录thinkphp5升级步骤并拆分为app.php、cache.php 等自力设置文件&#xff0c;体系默许的设置文件清单以下&#xff1a;由于项目是用tp5.1开辟的&#xff0c;网上找了一个不错的商城体系&#xff0c;然则倒是5.0开辟的&#xff0c;因而将5这个商城升级成了…

剑网三哪个网站服务器人多,《剑网3缘起》这么火?服务器快挤爆了!

怎么会这样&#xff1f;各位玩家朋友们&#xff0c;研游酱不得不说知道《剑网3缘起》会火&#xff0c;但是真的是没有想到&#xff0c;居然会有这么多人&#xff0c;各种排队&#xff0c;是大家都回来了吗&#xff1f;讲真&#xff0c;各位玩家朋友们&#xff0c;研游酱我是真的…

与虫子尾交3d动画网站_三维动画制作学什么_合肥迪维数字科技有限公司_技术引进...

合肥迪维数字科技有限公司指出&#xff1b;展厅序厅区在展厅设计中&#xff0c;序厅的设计是重中之重&#xff0c;因为序厅是企业展厅的门面&#xff0c;这马虎不得。相应地预算的一部分比例也花在序厅之上&#xff0c;当然&#xff0c;从设计的角度来说&#xff0c;序厅设计很…

seo技术_基础知识_网站pr值的意义_白杨SEO:一文告诉你网站权重是什么、意义以及如何提升网站权重?...

序言&#xff1a;这是白杨公众号第53篇。为什么想到写这个&#xff0c;一是上次写如何让百度收录网页和提高排序时有说到写写权重&#xff0c;二是昨晚上海一个SEO朋友问我百家号收录因素是什么时我也提了百度号权重&#xff0c;索性来写写这个哈~网站权重是什么&#xff1f;咱…

cookie代码加时间多久出现一次_Python爬虫:设置Cookie解决网站拦截并爬取蚂蚁短租...

前言文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。作者&#xff1a; EastmountPS&#xff1a;如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http://note.youdao.com/noteshare?id3054cce4…

p图软件pⅰc_社交网站上的P图翻车集锦……

社交网站上的照片经过PS&#xff0c;这是人所周知的&#xff0c;但有些....确实P得太过分了&#xff01;来看网友们搜集的最新案例&#xff1a;只要我会P图&#xff0c;人脸识别就奈何不了我魔镜魔镜&#xff0c;谁是世界上最假的人&#xff1f;事实证明&#xff0c;10头身什么…

php实现网站查询功能实现,php如何实现查询功能实现

php实现查询功能的方法&#xff1a;首先创建好前端文件以及PHP代码文件&#xff1b;然后通过所引用的封装类“DBDA”来实现查询功能即可。分享php实现查询功能的具体代码输入关键字效果代码&#xff1a;汽车信息require"DBDA.class1.php";//$type 代表SQL语句的类型&…

扫一扫 移动端_做移动端网站建设要注意什么?

网站制作一年350元&#xff0c;五站合一&#xff0c;快速建站 &#xff0c;www.sxjcwzjs.com,只需进入网站右上角注册快速建站即可(需要电脑登录注册)&#xff0c;需要联系我吧&#xff01;电话&#xff1a;13752214574&#xff0c;微信号&#xff1a;m1078582894屏幕适应做移动…

自制网站服务器主机,自制服务器主机迷你

自制服务器主机迷你 内容精选换一换为了方便用户在管理控制台上进行裸金属服务器实例管理&#xff0c;可快速辨别出每台服务器的名字&#xff0c;华为云支持给每台服务器命名&#xff0c;并且可以随时更改&#xff0c;重启生效。Windows裸金属服务器不支持修改主机名。登录管理…

关于网站运营的研究_关于网站运营,提升收录与排名相关问题的解答和建议

用什么工具查看谷歌收录量呢&#xff1f;你们应该能访问谷歌网站吧,在谷歌搜索输入 site&#xff1a;www.cctss.org 就可以看到收录量&#xff0c;站长工具&#xff0c;现在都查不到谷歌的收录&#xff0c;国内是屏蔽谷歌的。上面有一个相关结果&#xff0c;那个显示多少。有19…

python小程序框架,Python开源Web, CMF,可做微信小程序后端, 网站后端等.Restful Api...

dev(开放更新中,可在Tag中可以选择以往的其他版本)当前更新比较多&#xff0c;请及时更新新版本低版本更新到v2.2后&#xff0c;如果出现ROOT用户权限问题&#xff0c;[注销登录]后再次登录** 注意&#xff1a;更新到v2.2的童鞋请先看这篇文章 **VersionStatusOther开发...v1.x…

金昌搜索引擎优化网络推广_推广增加网站流量:搜索引擎优化必备六大方法

作为一个站长&#xff0c;想要去长久的运营一个网站&#xff0c;就要不断的增加网站流量和询盘&#xff0c;想要做好这些&#xff0c;就要懂得一些网站推广方法&#xff0c;那么网站的推广方法有哪些&#xff1f;创新营销思维小编觉得&#xff0c;这几个常用&#xff0c;但是效…