# 前言

作为一名程序猿经常会逛 github ,也会关注一些科技类资讯,自然就发现了阮一峰老师的科技爱好者周刊,每到周五经常会打开这个开源杂志看看有没有新奇好玩的东西。这个周刊是个开源杂志,目前可以从多个地方查看,除了 github 之外还有阮一峰老师的博客、云加专栏、语雀等地方,但是感觉不如小程序这个形态来的方便快捷,然后发现语雀有小程序但是打开路径还是略长,需要登录后点击【我】再进入【我的收藏】,再从列表中选择收藏的周刊进行查看(而且右上角胶囊菜单没有分享功能)......。所以就想到利用小程序的云开发能力来实现这么一个开源杂志的小程序版。

# 界面效果

小程序首页及详情页

# 与语雀的界面对比

语雀小程序中周刊的列表页及详情页

  • 以下是使用方式上的一些差异,仅供参考
使用上的差异 入口层级 分享 订阅
语雀内的 层级较深 支持分享海报及发送给朋友(右上角胶囊菜单不支持分享给朋友及朋友圈) 关注后开启推送
本小程序 点击即用 支持右上角胶囊菜单分享给朋友及朋友圈 功能已增加,暂未开放

# 技术选型

# 小程序端

  • 主框架使用 mpvue
  • UI框架采用 Lin-ui
  • 渲染插件使用 wemark

# 服务端

  • 小程序云开发部署若干云函数

    • weeklies:获取周刊列表
    • weekly:获取周刊 markdown 数据
  • 服务器部署基于 koa 框架开发的接口

# 架构方案

主体采用服务器加云开发混合部署,如下图所示:

  • 服务器定期从 github 拉取最新文章的 markdown 文件,并进行基础的数据处理,生成文章的 json 缓存文件
  • 小程序内调用云函数后从独立服务器获取文章数据进行展示
  • 文章内页的数据为markdown类型故采用开源插件 wemark 进行渲染

# 重点问题

1.文章内容渲染的问题。小程序内的 markdown 渲染插件有几种解决方案,最终选择了 wemark 来渲染(当然也可以选其它的) markdown 文件

<wemark :md="content" link highlight type="wemark"></wemark>

2.每期周刊并没有在文件中标注说明创建时间,但是文件是从 github 同步过来的,所以可以通过执行 git log 命令来获取日志从而大致确定文章的更新时间

核心实现示例如下:

// 需要借助 child_process 及 moment 模块
...
var data = fs.readFileSync(row, 'utf-8') // row 为markdown文件本地路径// 最后更新时间
let dateGit = execSync(
'cd ' + config.base_path + ' && git log -n 1 -s --format=%cd ' + row
).toString() // config.base_path 为本地周刊仓库地址
let lastdate = moment(new Date(dateGit)).format('YYYY-MM-DD')

3.接口数据格式。前期的文章格式并不居有明显的规律性,在文章配图及概要获取上存在一定问题,为了使首页的最终显示效果更加美观,最终确定取封面图及其描述作为每期的介绍。

最终确定的周刊列表 json 格式示例:

{"code": 0,"data": [{"title": "科技爱好者周刊(第125期):数字人民币要取代谁","seq": "125","desc": "西班牙加纳利岛的人们,在火山灰上挖坑种葡萄。火山灰排水快,种出来的葡萄更适合酿酒。([via](https://www.instagram.com/p/CFMtHr3jOtR/))","lastdate": "2020-09-18","file_name": "issue-125.md","img": "https://www.wangbase.com/blogimg/asset/202009/bg2020091705.jpg"}]
}

4.markdown 数据的处理,需要匹配 markdown 文件内部引用的图片

markdown 文件内部引用图片不一定完全契合标题,但是一篇文章没有配图也太丑了,所以这里权衡之后决定使用第一张图及其描述作为周刊文章封面及概要

获取图片的方式为正则匹配 markdown 文件内容中的所有图片,然后获取第一张图,并把图片之后的固定 90 个字符作为该期周刊的描述文字

// 获取第一张图
let imgReg = /!\[.*\]((.+))/ //匹配img
let cnt = data
let imgArr = cnt.match(imgReg) //筛选出所有的img// 图后的内容截取作为描述
let desc = cnt.substr(cnt.indexOf(imgArr[0]) + imgArr[0].length + 2, 90)let imgUrl = ''
if (imgArr && imgArr.length > 0) {let url = imgArr[0]imgUrl = url.substring(url.indexOf('(') + 1, url.indexOf(')'))
}

5.数据同步问题。目前基于koa写了一个 webhook 部署在独立服务器上,每周定期拉取最新周刊的 markdown 文件并生成缓存。

示例代码:

router.get('/weeklies/init', async (ctx, next) => {// 拉取最新markdown文件const { stdout, stderr } = await exec('cd ' + config.base_path + ' && cd ../ && git pull')if (stderr == '') {// 读取md文件列表let blog_routes = await fg(blog_md_path, {onlyFiles: true,cwd: __dirname,deep: 1,})ctx.data = '仓库更新成功->' + stdout + (await initTitle(blog_routes))} else {ctx.data = stderr}await next()
})

# 项目总结

项目整体上比较简单,极简风格,发现了有意思的东西可以方便地分享给朋友或者到朋友圈。目前 markdown 文件内容并没有使用云数据库,而是直接读取的文件,可能会对服务器 IO 有一定考验,后期会采取迁移到云数据库的方式。

# 体验方法

小程序目前已上线,欢迎扫码体验
或者也可以微信搜索『科技爱好者周刊』

# 参考资料

# 致谢

再次致谢阮一峰老师

小程序云开发实战:从零搭建科技爱好者周刊小程序相关推荐

  1. 小程序·云开发实战:SCRM社交化客户管理小程序

    点击观看大咖分享 随着微信小程序不断发展壮大,传统的 CRM 厂商也在不断向微信上迁移,毕竟微信的背后是巨大的用户和流量,还有极其方便的移动支付渠道.用微信小程序来做CRM,和以前的做法存在一些比较明 ...

  2. 名片识别 php,小程序云开发实战:实现 AI 智能名片识别小程序

    本次分享是针对对小程序·云开发感兴趣的朋友推出的入门课程,内容以基础+实战的方式呈现,通过实战"名片小程序"开发,讲解云开发的功能与开发优势,为开发者提供提高开发效率的方法与灵感. ...

  3. 小程序·云开发实战:实现 AI 智能名片识别小程序

    开发者在开发小程序时往往需要花费精力进行后端基础设施建设及维护,但利用小程序·云开发开发,则可以跳开这一环节,无需再搭建服务器. 本次分享是针对对小程序·云开发感兴趣的朋友推出的入门课程,内容以基础+ ...

  4. 【系】微信小程序云开发实战坚果商城-商城项目搭建

    第 2-1 课:商城项目搭建 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 [系]微 ...

  5. 【系】微信小程序云开发实战坚果商城-云开发开篇

    第 3-2 课:云开发开篇 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 [系]微信 ...

  6. 【系】微信小程序云开发实战坚果商城-开篇

    开篇:无服务开发是未来? 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 [系]微信小 ...

  7. 【小程序云开发】30分钟搭建个人相册小程序

    文章目录 前言 最终效果 准备工作 小程序架构 创建小程序云开发环境 创建数据库 搭建个人相册 写在最后 前言 图片存储,是所有应用开发里最常见的场景之一. 本文将通过实战"个人相册小程序& ...

  8. 【系】微信小程序云开发实战坚果商城-扩展篇

    第 5-1 课:扩展篇 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 [系]微信小程 ...

  9. 【系】微信小程序云开发实战坚果商城-弹性盒子

    第 1-1 课:微信小程序实操弹性盒子 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 ...

  10. 【系】微信小程序云开发实战坚果商城-前端之订单实现

    第 2-7 课:前端之订单实现 目录 开篇 [系]微信小程序云开发实战坚果商城-开篇 基础篇 [系]微信小程序云开发实战坚果商城-弹性盒子 [系]微信小程序云开发实战坚果商城-ES6 简单入门 [系] ...

最新文章

  1. 使用LVS实现负载均衡原理及安装配置详解
  2. STL中算法锦集(四)
  3. Linux命令速查(带参数说明)
  4. java的一段排序代码_Java常见排序算法——快速排序
  5. mysql unique 锁_mysql 行锁排查
  6. 假期周进度总计(四)
  7. 为github帐号添加SSH keys
  8. 用C语言操作MySQL数据库
  9. 揭秘《英雄联盟》的游戏自动化测试
  10. 中职学校计算机教学中,中职学校计算机教学方式
  11. 《C语言》课程设计——学生成绩统计
  12. python编程期末试题_大学moocPython编程基础期末考试答案
  13. c语言中begin用法,C++ set cbegin() 使用方法及示例
  14. 听不够的三国,淡淡的乡愁
  15. 【汇编与接口】ADA转换器
  16. JS - 利用performance.timing进行性能分析
  17. 【2.Delphi语法基础】2.Object Pascal数据类型
  18. 162天,100期Java项目终于更完了!
  19. Python实现图片和视频的相互转换
  20. STM32的QSPI通信(学习笔记)

热门文章

  1. JK触发器波形图分析
  2. 误差逆传播算法(BP算法)
  3. 支付宝android 10.0.8,分享10.0.8版支付宝开启和关闭小额免密支付功能方法
  4. 浏览器清理缓存的几种方法
  5. python中的ln函数_python3中涉及数字的各种函数
  6. 解决Word文档被锁,无法复制的问题
  7. 【Transformer论文模型细致讲解】
  8. 神经网络:ResNet 论文学习总结(二)-- 模型微调
  9. 移动硬盘安装Linux后无引导,移动固态硬盘安装Ubuntu启动盘后按F12根本就没有该系统启动项...
  10. 大学生活这样过,等着 Offer 飞来找 | 程序员有话说