当前位置: 首页 > 后端技术 > Node.js

使用Nuxt+Vue+Node构建的SSR博客项目

时间:2023-04-03 21:15:17 Node.js

之前的博客用的是Ghost,结果被攻击,被勒索了几百块钱。忘了它。对了,数据备份很重要!前段时间学过Vue.js,到现在还记得以前看过的一些Node。主要是锻炼自己。本博客没有使用Hexo、Ghost等,是我自己写的。由于SEO的需要,毕竟自己写写看也没什么意思。最终采用的技术方案:Vue.js+Nuxt.js+ES6+Webpack+Mysql+Noyde.js+Express.js。其实还有很多东西在开始之前不是很熟悉,但是总算是完成了。这个项目给了我一个启示:实践是最快的学习方式。真的不如看文档看多遍手写一个项目好。目前流行的前端框架Vue.js和Nuxt.jsVue.js,官网地址:https://cn.vuejs.org/,文档写的不错,点个赞!Nuxt.jsNuxt.js的文档也写的很好。据说Vue.js系列的文档写的很好。我又喜欢了官网是这样介绍自己的:Nuxt.js是一个基于Vue.js的通用应用框架。通过客户端/服务器基础架构的抽象组织,Nuxt.js主要关注应用程序的UI渲染。我们的目标是创建一个灵活的应用程序框架,您可以在此基础上初始化新项目的基础设施代码,或者在现有的Node.js项目中使用Nuxt.js。Nuxt.js预设了使用Vue.js开发服务端渲染应用程序所需的各种配置。此外,我们还提供了一个命令:nuxtgenerate,它提供了为基于Vue.js的应用程序生成相应静态站点的功能。我们相信这个命令提供的功能是开发集成各种微服务(miscroservices)的网络应用程序的新步骤。Nuxt.js作为一个框架,为客户端/服务器的典型应用架构模式提供了很多有用的特性,比如异步数据加载、中间件支持、布局支持等。总结起来,Nuxt.js是一个使用Vue的框架,webpack和Node.js帮助我们简单方便的实现SSR。关于SSR什么是SSRSSR是ServerSideRender的缩写,即服务端渲染。在SPA之前,大部分网页都是通过服务端渲染生成的:用户向服务端发送请求,服务端拿到请求,然后查询数据库,根据查询到的数据动态生成网页,最后返回页面内容网页到浏览器端。现在以Vue为例。一般情况下,Vue.js运行在浏览器中。在浏览器中,你发送请求,然后获取后台返回的数据,最后通过Vue.js片段将数据渲染成需要的HTML。现在,我们把将组件渲染成HTML的工作交给Node去执行。Node可以看作是一个隐形的“浏览器”。在这个“浏览器”中,我们渲染所有的组件,然后将渲染后的HTML直接发送给实际的浏览器(客户端),这就是VueSSR。通过前端框架(Vue、Angular、React)搭建的SSRSPA(Single-PageApplication——单页应用)的好处,因为内容是通过Ajax获取的,有一个天然的缺陷就是搜索引擎无法获取内容里面。右键查看一个SPA网页的源代码,你会发现你里面几乎什么都没有。对于像博客、新闻这样的网站来说,这是不可接受的。总结一下,SSR的好处就是可以做SEO。顺便说一句,因为内容已经在服务器端渲染了,所以也可以减少请求的次数。对于一些较旧的浏览器(Vue.js不支持),你也可以看到基本内容。开发总结开发中遇到的问题很多。这里我就罗列一下,让大家尽量少走弯路。我会尽量使解决方案简洁。有些事情我会单独开一篇博文。Restful项目后台使用RestfulAPI,后台框架使用express。您可以使用vueinitnuxt-community/express-template生成一组基于express的模板文件。后台代码在server目录下。这个目录里面是关于Node和express的内容,这里就不展开了。asyncData多次请求参考如下代码:asyncasyncData({req,error}){constpage=0let[pageRes,countRes]=awaitPromise.all([axios.get(`/api/post/page/${page}?scope=published`),axios.get('/api/post/count/published'),])return{posts:pageRes.data.list,count:countRes.data.result,}}middleware中间件组件允许您定义一个自定义函数以在呈现一个页面或一组页面之前运行。每个中间件都应该放在middleware/目录中。filename的名称将成为中间件名称(middleware/auth.js将成为auth中间件)。这是一个例子:import{isLogin}from'../util/assist'constneedAuth=require('../util/api.config').needAuthexportdefaultfunction({isClient,isServer,route,req,res,redirect}){//服务端判断是否需要登录(如果直接输入地址,客户端无法判断)if(isServer){letcookies=req.cookiesletpath=req.originalUrl;if(path.indexOf('admin')>0&&!cookies.token){redirect('/login')}}//检查客户端是否需要登录if(isClient){if(route.path.indexOf('admin')>0&&!isLogin()){redirect('login')}}}节点循环+异步问题项目中有这样一个需求:显示文章对应的几个标签(Tags)(邮政)。解决方法是获取PostList,然后循环List获取PostId,根据PostId查看对应的Tag。因为获取PostList的异步操作,然后在循环中有很多异步操作(获取Tags),用回调方法写下来是不可能的。最后使用async库,贴出一段代码://获取Post列表letlist=(params,callback)=>{postModel.list(params,(err,posts)=>{if(err){returncallback({code:404,message:'noresult'});}//获取每个帖子的标签async.eachSeries(posts,(post,tagCallback)=>{postTagModel.tagsByPostId(post.id,(err,result)=>{if(err){tagCallback(err)}post.tags=result;tagCallback()});},(err)=>{if(err){callback({code:404,message:'noresult'});returnfalse;}callback({code:404,message:'noresult',list:posts});});});}静态资源在Nuxt中,可以将静态文件放在项目根目录的static文件夹下,然后直接使用根路径/来访问。登录这是第一个我用restful的时候,一直困扰着登录问题我查了很多资料,最后的解决办法是用token。在前端,如果检测到用户没有登录,就会跳转到登录页面。用户发送登录请求后,后台会验证用户名和密码,验证成功后返回一个token。前端收到token后保存在本地,每次发送请求时都带上token,后续请求后台检查token,合法则认为登录成功。以下代码用于生成token(使用jwt-simple),uid为用户ID,exp的值为7天后的时间,jwtSecret为加解密密钥。letauth=(user,callback)=>{if(user.account.trim()==''){returncallback({code:403,message:'用户名不正确'});}if(user.password.trim()==''){returncallback({code:403,message:'密码不正确'});}userModel.auth(user,(err,user)=>{if(err){returncallback({code:404,message:'登录失败'});}if(user.length===1){//设置7天有效期letexpires=moment().add(7,'days').valueOf();lettoken=jwt.encode({uid:user[0].id,exp:expires},jwtSecret)returncallback({code:200,message:'success',token:token});}callback({code:404,message:'登录失败'});});}我用的ajax工具是axios,下面代码的作用是为所有的请求添加一个header。//拦截请求$http.interceptors.request.use(config=>{if(typeofdocument==='object'){lettoken=getCookieInClient('token')if(token){config.headers.Authorization=token;}}returnconfig;},err=>{returnPromise.reject(err);});下面是验证token的中间件,先判断接口是否需要验证身份,如果不需要,直接Next,如果需要,获取并验证token。验证比较粗暴,就是直接判断token是否在有效期内。当然,还有更安全的方法。你可以自己搜索。登录成功的标志是token验证合法,然后进行下一步。验证不通过则直接返回,前端根据响应跳转到登录页面。module.exports=function(req,res,next){letpath=req.originalUrl//接口不需要登录:直接nextif(needAuth.indexOf(path)<0){returnnext();}//接口需要登录vartoken=req.headers['authorization']if(!token){returnres.json({code:401,message:'需要登录:没有token'})}try{//解密得到的tokenletdecoded=jwt.decode(token,jwtSecret);//验证有效期if(decoded.exp<=Date.now()){returnres.json({code:401,message:'你需要登录:token已过期'});}下一个();}catch(err){returnres.json({code:401,message:'youneedlogin:decodetokenfail'})}};nuxt的nuxt.config配置文件,具体的配置项可以参考这个链接。下面是我的配置文件,里面的内容应该很容易看懂。module.exports={//页面的head标签head:{title:'JustYeh的前端博客',meta:[{charset:'utf-8'},{name:'viewport',content:'width=device-width,initial-scale=1,user-scalable=no'},{hid:'description',name:'description',content:'justyeh的前端博客'},{name:'renderer',content:'webkit'},{'http-equiv':'X-UA-Compatible',content:'IE=edge'},{name:'author',content:'justyeh@163.com'},{name:'apple-mobile-web-app-title',content:'justyeh的前端博客'},{name:'apple-mobile-web-app-capable',content:'yes'},{name:'apple-mobile-web-app-status-bar-style',content:'#263238'},{name:'screen-orientation',content:'portrait'},{name:'x5-orientation',content:'portrait'},{name:'full-screen',content:'yes'},{name:'x5-fullscreen',content:'true'},{name:'browsermode',content:'application'},{name:'x5-page-mode',content:'app'},{na我:'主题颜色',内容:'#263238'},],链接:[{rel:'icon',类型:'image/x-icon',href:'/favicon.ico'}]},//全局引用css文件css:['~assets/css/main.css','~assets/css/font-awesome.min.css'],//页面顶部加载效果loading:{color:'#04acf7',height:'4px',failedColor:'red'},//页面过渡效果transition:{name:'page'},//配置路由中间件router:{middleware:'adminAuth'}}deploymentdeployment一直不太擅长,这次确实在上面遇到了很多问题。我不会在这里谈论它。最后使用的是pm2。现在假设你已经安装了node、pm2、vue等包,依次运行以下命令:#进入文件所在目录cdyour_project#安装项目依赖npminsatll#打包npmrunbuild#Run,--name'你的项目名'可选pm2startnpm[--name'你的项目名']--start说到最后上面的东西比较琐碎,如果你碰巧遇到可能会有帮助遇到相关问题。不知如何系统梳理,只能致歉。好吧,所有代码都在这里:https://github.com/justyeh/justyeh.com,你可以在这里查看详细信息。这是最后的结果:http://justyeh.com/,由于是私有项目,上线后台就不公布了,大家可以直接clone我的项目,数据库都在,本地运行即可.水平有限,如有错误请指正。如果你喜欢它,你可以给它一个星。如果您有什么好的建议和意见,欢迎与我联系!