Where is JavaScript?

博客升级记录

换工作后利用业余时间将[个人博客](https://littlewin.wang)进行了升级改造,本文为一些总结。

换工作后利用业余时间将个人博客进行了升级改造,本文为一些总结。主要工作是:

  • 采用 Nuxt.js + Koa2 + Mongodb + Nginx 系统的布置了一下前后端
  • 启用新域名littlewin.wang,续费腾讯云服务器
  • 启用腾讯云对象存储 + CDN加速业务,服务器配置Nginx完成各种接口和端口的反带
  • 采用certbot申请免费SSL证书,并在服务器部署定时任务续期(一般免费证书有效期为3个月)

架构

后端 - api.littlewin.wang

https://static.littlewin.wang/blog/25-1.png

Koa2结合Async/Await使用

Express这样的框架很大程度上依赖于回调来执行异步操作,需要具备良好的代码编写能力来编写出简洁和可读性好的代码。一般情况下,大量回调的出现势必让开发和维护过程充满波折。之前Koa使用Promises和Generators的组合摆脱了上述的回调地狱,而Koa2的出现可以让我们使用Node v7版本后中的async / await语法。

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
static async create (ctx) { const category = ctx.request.body // name validate if (!category.name) { ctx.throw(401, '需要提供分类名') return } if (await CategoryModel.findOne({ name: category.name }).exec()) { ctx.status = 401 ctx.body = { success: false, message: "分类已存在" } return } await new CategoryModel(category).save() .then(() => { ctx.status = 200 ctx.body = { success: true, message: "分类创建成功" } // baidu seo push baiduSeoPush(`${config.INFO.site}/category/${category.name}`) }) .catch(() => { ctx.throw(401, '分类创建失败') }) }

代码直接按照同步思维去编写异步逻辑,减小了开发的复杂度。

利用Koa Middleware做集中错误处理和token校验
              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
/** * @file 统一的try/catch错误捕捉入口 * @author littlewin(littlewin.wang@gmail.com) */ module.exports = async (ctx, next) => { try { await next() } catch (err) { // will only respond with JSON ctx.status = err.statusCode || err.status || 500; ctx.body = { success: false, message: err.message } } }

有了这个中间件,我们的业务逻辑 controller 中的代码就可以这样来触发错误:

              
  • 1
  • 2
  • 3
  • 4
  • 5
// 验证comments if (!comments) { ctx.throw(401, '参数不对') return }

同理,可以用中间件完成token验证,分不同的接口加入(本项目中所有非GET请求需加入token)。

              
  • 1
.post('/tag', middleware.verifyToken, Tag.create)
Schema的设计优化

后台数据库中,保存有文章、分类、标签、评论等数据模型。除了常规的namecontentdescription等内容属性和createAtupdateAt等时间戳属性,为了后期扩展,增加了extends属性。

              
  • 1
  • 2
  • 3
  • 4
extends: [{ name: { type: String, validate: /\S+/ }, value: { type: String, validate: /\S+/ } }]

引入了分页和自增ID插件来解决以下问题

  • 数据库自带的_id属性为uuid String,内容过长,不便于前端索引
  • 支持前端的分页加载效果
              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
const autoIncrement = require('mongoose-auto-increment') const paginate = require('mongoose-paginate') ArticleSchema.plugin(paginate); ArticleSchema.plugin(autoIncrement.plugin, { model: 'Article', field: 'id', startAt: 1, incrementBy: 1 })
地理信息的获取

博客留言框内已经有地理位置的显示,这个功能主要由GeoIP-lite完成。

  1. 服务器Nginx反带时proxy_set_header X-Real-IP $remote_addr
  2. 后台获取前端IP地址
  3. 通过GeoIP-lite分析相应的国家和城市信息
评论过滤
  1. 使用akismet过滤
  2. 后台数据库保存黑名单,对比黑名单完成过滤
评论提醒邮件

暂时由nodemailer + QQ邮箱的smtp服务完成

百度SEO推送

参考百度链接提交

启用redis缓存数据

前端 - littlewin.wang

启用Nuxt.js

Nuxt.js的最大特点是预设了利用Vue.js开发服务端渲染的应用所需要的各种配置。
再使用中,也遇到了一些问题:
windowdocument问题 - 有些组件无法支持SSR,需要对原生DOM有所操作。vue-component级别的组件可以采用<no-ssr>标签判断并在客户端再进行渲染;或者自行封装directive类型的插件,通过Nuxt的plugin机制注册并配置ssr: false属性。

响应式设计优化

媒体查询 + 部分客户端渲染的组件(需要操作原生DOM)

部署上线

暂时采用git提交后pm2远程部署

              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
module.exports = { /** * Application configuration section * http://pm2.keymetrics.io/docs/usage/application-declaration/ */ apps: [ // First application { name: 'littlewin.wang', script: 'node_modules/nuxt/bin/nuxt-start', env: { COMMON_VARIABLE: 'true' }, env_production: { NODE_ENV: 'production', PORT: '3100' } } ], /** * Deployment section * http://pm2.keymetrics.io/docs/usage/deployment/ */ deploy: { production: { user: 'littlewin', host: '119.29.68.183', ref: 'origin/master', repo: 'git@github.com:littlewin-wang/littlewin.wang.git', path: '/home/littlewin/littlewin.wang/production', 'post-deploy': 'git pull && npm install && npm run generate && pm2 reload ecosystem.config.js --env production' } } }

管理端 - littlewin.admin

目前管理端用vue-cliEleme UI搭建了一个CMS单页应用,分为概览、站点设置、文章设置和评论设置等部分。

插件

插件方面,主要用到了

数据统计

由于google OAuth 2.0验证被墙,所以google analytics API拿数据也变得很复杂 ~虽然可以加一级代理~
现有的概览简单的统计了发文数、评论数、获赞数和服务器cpu负载和内存可用比等,这些统计一方面是激励自己多加努力,亲身经历数字上涨的过程,二来也是对工作量和服务器状态做监控。

服务器

以上项目均部署在同一台腾讯云服务器,后台开启了多个node进程,通过nginx集中代理到不同的二级域名

二级域名解析

api.littlewin.wangadmin.littlewin.wang分别解析到服务器IP

Nginx配置
              
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
server { listen 443; server_name littlewin.wang; ssl on; ssl_certificate /etc/letsencrypt/live/littlewin.wang/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/littlewin.wang/privkey.pem; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass http://127.0.0.1:3100; proxy_redirect off; } } server { listen 443; server_name api.littlewin.wang; ssl on; ssl_certificate /etc/letsencrypt/live/api.littlewin.wang/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.littlewin.wang/privkey.pem; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass http://127.0.0.1:8090; proxy_redirect off; } } server { listen 80; server_name admin.littlewin.wang; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $http_host; proxy_pass http://127.0.0.1:3010; } }
SSL证书管理

因为博客相对是一个稳定,流量小的站点,所有直接选择certbot申请了对应于二级域名下的免费证书,同时开启定时任务去更新证书,以防过期

静态资源

博客中的静态资源主要为图片,利用腾讯云COS + 腾讯云CDN部署自定义域名来访问静态资源,同时也可以解决静态资源支持https的问题

总结

个人博客经历过wordpress,Hexo等开发过程,这次经过了充分的准备之后将前后端一步步的做下来,现在也只是完成了基本功能 + 一部分的显示优化
后续跟进的路还很长,也希望伴随着这个优化之路写出好的技术文章吧
最后来张大图点题https://raw.githubusercontent.com/littlewin-wang/littlewin.wang/master/static/screenshot.png

本文于 2017-10-26  发布在  编程  分类下, 当前已被围观 1275 次

并被添加「 JavaScript前端Node.js 」标签

本站使用「 署名 4.0 国际」创作共享协议