本文首发于政采云前端团队博客:手把手教你打造属于自己团队的前端小报系统
https://www.zoo.team/article/building-a-tabloid-system
前言
经常关注我们政采云前端团队的同学, 对下面这张图应该不陌生~
![ce27a180bada26f6821730c052d2985f.png](https://i-blog.csdnimg.cn/blog_migrate/1d807eecb5b5c42f8d8448be28b9a476.png)
每周五下午我们会定时推送一期前端小报,里面汇集了一些精选的前端文章~
下面这张图就是 政采云前端小报 (https://weekly.zoo.team/ )的官方站点的截图,这个站点里面有我们历史每期的汇总~![b1619cdf52ba5e6f55b52ab44a731bfb.png](https://i-blog.csdnimg.cn/blog_migrate/29f176077410cb356c404ea22cc5dda7.png)
至今前端小报已经 93 期,汇聚了 1000+ 文章,覆盖了 50+ 大小分类,可谓是一个非常好的知识库了~
前端小报的由来
持续学习是每个工程师必备的素养,一个成长性的团队也同样需要这样一个持续学习的氛围。那么如何通过技术的手段来帮助团队培养持续学习的氛围呢?
政采云前端小报因此应运而生,它主要包含投稿、汇总沉淀、定时投递三大核心模块,这样的一个系统可以让大家轻松的将自己喜欢的文章分享到团队内部,并且将文章进行分类沉淀,营造团队的知识库,方便大家查阅,同时小报系统也会在每周五进行定时推送,方便大家了解最新的技术动向,前端小报系统是一个帮助我们营造团队内部分享和学习氛围的得力帮手~
那么这样的一个小报系统是如何实现的呢?
如何设计一个小报系统
投稿
相信大家看到好的文章的时候,总会有忍不住想分享给别人的冲动,一个简单易用的投递功能可以很方便的满足大家的分享欲望,将好的文章输入到团队,帮助其他同学~
一个简单容易的投稿功能,我们需要解决两件事情:
1、如何能在看到好文章时,满足分享的冲动
2、如何对投稿的文章进行归类收集,方便沉淀与查找
如果是一个单独的录入系统,手动录入,这种方式操作繁琐,很容易打消大家的热情,平时在浏览器看文章的时候,我们经常将好的文章加入书签收藏,一键操作,方便快捷。那么如何能像浏览器书签收藏文章一样方便的去投稿呢?
很容易想到通过浏览器的扩展能力去做这个事情,Chrome 插件就提供了这样的能力
什么是 Chrome 插件
官方解释 (https://developer.chrome.com/extensions):谷歌插件是一种小型的用于定制浏览器体验的程序。它可以使用户根据个人需要或偏好来定制 Chrome 的功能和行为,它们基于 Web 技术(HTML,JavaScript 和 CSS)构建。
说人话:开发一个 Web 项目,能够嵌入到 Chrome 浏览器中,同时能够通过一些特定的 Api 获取到一些能力,从而订制自己的插件功能
如何开发一个一键投稿的 Chrome 插件
首先创建一个项目,开发一个投稿功能页面 。
此项目和普通 Vue 项目唯一的区别是根目录多了一个manifest.json
文件。
![22bbb77f9512aa4e410c1e5d41b7f6c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5d3afbdc5eb527707e00ed9bda9c93.png)
创建
manifest.json
:Chrome 通过识别项目根目录是否有manifest.json
文件来识别是否为 Chrome 插件。
{
// 核心代码
"name": "Zoo!", // 扩展名
"browser_action": {
"default_popup": "./popup.html" // 点击浏览器右上方插件小图标弹出的内容 html
},
"content_scripts": [ // 能够在 Web 页面内运行的 javascript 脚本
{
"matches": [
// 满足什么协议下进行调用
"http://*/*",
"https://*/*"
],
"js": [
"./contentScripts/zdata.js" // 插入到网页的 JS 文件路径
],
"run_at": "document_start" // 在document 加载时执行
}
]
}
这样插件被打开时会默认加载 popup.html
页面的内容,效果如图:
![176b5ec354dd0ba835611d8f7dc7de36.gif](https://i-blog.csdnimg.cn/blog_migrate/99b4b00b76327dd34c44df459d8d66de.gif)
- 如何获取文章标题、简介、URL
let host = this;
// 获取当前窗口 id
chrome.tabs.query({
active: true,
currentWindow: true
}, function (tabs) {
let tabId = tabs.length ? tabs[0].id : null;
// 向当前页面注入 JavaScript 脚本
chrome.tabs.executeScript(tabId || null, {
file: './contentScripts/recommend.js'
}, function () {
// 向目标网页进行通信,向 recommend.js 发送一个消息
chrome.tabs.sendMessage(tabId, {
message: 'GET_TOPIC_INFO',
}, function (response) {
// 获取到返回的文章 title 、url、description
host.article.title = response.title;
host.article.link = response.link;
host.article.description = response.description;
});
});
});
recommend.js
监听消息 ,通过 addListener 我们可以监听来自 sendMessage 发出的消息,在 sendMessage 中定义 message 常量让我们可以在接收消息时对消息进行区分。
let doc = document;
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
if (request.message === 'GET_TOPIC_INFO') {
// 获取 title
let title = document.getElementsByTagName('title')[0].textContent;
let descriptionEl = doc.querySelectorAll('meta[name=description]')[0];
// 获取 描述
let description = descriptionEl ? descriptionEl.getAttribute('content') : title;
// 发送数据
sendResponse({
title: title.trim(),
link: location.href,
description: description.trim()
});
} else if (request.message === 'SIGN_RELOAD') {
console.log('request, sender', request, sender);
}
});
- 点击投稿时,需要将数据发送到服务端做存储
// 投稿按钮点击事件
handleRecommendArticle: function () {
let request;
request = ajax({
method: 'post',
url: 'https://XXX/api/post', // 后端接口
data: {
'title': this.article.title,
'desc': this.article.description,
'category': this.article.category[1] || '默认分类',
'link': this.article.link,
'referrer': this.article.reporter
}
});
}
效果图:
![8c3585da3d16910dfcf4ca6432dd7ea1.png](https://i-blog.csdnimg.cn/blog_migrate/fb27ef040307d36419281092dad20e33.png)
上面就是一个很轻量的 Chrome 插件的实现了,基于这样的一个 Chrome 插件,当我们看到喜欢的文章时,就可以一键分享给团队的小伙伴了~
当文章多了之后,如果没有有效的管理,文章会堆积杂乱,反而让大家失去了去学习的欲望,那么我们如何对投稿的文章进行归类收集,方便同学们有查找自己需要的知识体系呢?
标签设计
![39132d853114c6dfbe99a942cc189f52.png](https://i-blog.csdnimg.cn/blog_migrate/da0303546238513eb90763d4af0978bf.png)
- 标签分类
在标签分类上当时花了一些时间去设计,难点主要是什么样的分类维度能够让投稿人快速找到对应的分类,让查看人能够快速根据分类找到自己想要的文章, 以及如何能够快速找到往期文章等 。
这就要求我们的分类需通俗易懂,且能够涵盖业务大部分文章的类型,最后我们是从基础、语言、架构、选型、工具、总结等多维度进行分类。
![f8609086b4d2eaebb04ad27cf8994252.gif](https://i-blog.csdnimg.cn/blog_migrate/add7e9d9b500aa2408a12ab87f6f758a.gif)
安装插件
插件制作完成之后,其他同学就可以将你的插件安装包安装到浏览器中。因为墙的原因,这里没有选择将插件上传到 Chrome 应用商店,我们是直接安装到本地, 下图为打包后的项目目录结构:![22bbb77f9512aa4e410c1e5d41b7f6c6.png](https://i-blog.csdnimg.cn/blog_migrate/0b5d3afbdc5eb527707e00ed9bda9c93.png)
![192845b63c4e9a5f32a8ac61444c7a84.png](https://i-blog.csdnimg.cn/blog_migrate/f8410c811a7abe196aced3cecc11fd5f.png)
关于 Chrome 扩展 插件的官方 详细文档请移步链接(https://developer.chrome.com/extensions) 查看
汇总沉淀
很普通一个前端项目,这里不再过多陈述,主要是能够看到每一期文章和按照分类进行快速查找,并统一收录文章入口。其中,前端页面采用 SSR 服务端渲染实现。![b1619cdf52ba5e6f55b52ab44a731bfb.png](https://i-blog.csdnimg.cn/blog_migrate/29f176077410cb356c404ea22cc5dda7.png)
![fbbb7dde48eb9a2d3a588a60472c436b.png](https://i-blog.csdnimg.cn/blog_migrate/588ad849404b385ab6b295fd23c42187.png)
定时投递
到这里小报系统的前台展示页面已经完成,那么如何将每一期的优质文章更及时且方便的让同学能够阅读到呢,让大家及时的去了解新技术,扩充视野。后来我们想可以通过主动触达,定时提醒等方式将期刊主动发送给团队同学。因此在上述基础上单独设计 了一个推送服务,定时将每一周的小报推送到钉钉群和前端邮件组。
通过钉钉群机器人,每周五将期刊发送到前端群里。详情见官方开发手册 (https://ding-doc.dingtalk.com/doc#/serverapi2/ye8tup/7ae8ebf3)
![3dfca7b5f36177fefd4f2d5a565ce487.png](https://i-blog.csdnimg.cn/blog_migrate/8377706800d25c6f7b1cd388636e6219.png)
const pushToRobot = async ({ data, title, nums }) => {
// 组装发送数据格式
const links = wrapperFeedcard({ data, nums });
// 发送数据到指定群
return axios("https://oapi.dingtalk.com/robot/send?", {
method: "post",
params: {
access_token: "XXXX" //前端群
},
data: {
feedCard: {
links
},
msgtype: "feedCard"
}
})
};
通过邮件发送, 每周定时发送邮件到团队邮件组。
![19924305da5047d72460f92a72149fe8.png](https://i-blog.csdnimg.cn/blog_migrate/ce1dcdbbb82301ce2db7111c686fb044.png)
// 创建邮件链接
const nodemailer = require("nodemailer");
let transporter = nodemailer.createTransport({
service: "qiye.aliyun",
port: 25, // SMTP 端口
host: "smtp.mxhichina.com",
secureConnection: true, // 使用了 SSL
auth: {
user: "xxx@cai-inc.com",
pass: "xxx"
}
});
// 组装发送内容
let mailOptions = {
from: '"政采云前端小报" ', // sender address
to: "ZooTeam@cai-inc.com", // list of receivers
cc: ["ZooTeam@cai-inc.com"],
html: '邮件内容' // html body
};
// 邮件发送
transporter.sendMail(mailOptions);
定时发布掘金
有一天我们的掘金运营小姐姐和我说,每周五快下班时都要进行文章发布,太痛苦了,耽误我下班约会,掘金为啥没有定时发送功能?我说好吧,那咱们自己开发个定时发布功能吧,想知道如何实现掘金定时发布功能,可在评论区留言讨论。
整体设计
![d41bd32af4e4c251e16a2cfa6fe8db27.png](https://i-blog.csdnimg.cn/blog_migrate/4504ba16702766e4979b0de8882177d5.png)
总结
前端小报系统虽然是个小系统 ,但是不论从功能设计,还是系统设计方面都奔着一个目标,努力推动团队的学习氛围,让团队同学持续的成长。希望通过本文分享能够给大家一些启发,如何从一个目标出发去拆解落地,去思考如何让工具的去更好的服务于人。
包邮送书
web前端性能优化 * 2本
方式很简单
每日留言说说你的学习心得以及经历(点赞最高者,联系我获得一本书籍)结束时间,2020.8.2,18:00点整哦!
《Web前端性能优化》通过三大优化思维+八处优化落点+40多个典型案例,教你轻松学会“大厂”的优化套路!
扫码关注公众号,订阅更多精彩内容。
给个[在看],是对达达最大的支持!