内容简介:「何遇」是一款Chrome扩展程序,其主要的功能是当你在 Chrome 浏览器中打开一个新的Tab页面时,空白页会展示出一些有趣的插图、句子、电影截图等,给苦涩的搬砖生活增添一丝乐趣,效果如下:实现方案很简单,页面就是一个普通的前端页面,配置少许的假如你科学上网,便可以访问该链接 下载体验,或者在应用市场 搜索“何遇”下载。
「何遇」是一款Chrome扩展程序,其主要的功能是当你在 Chrome 浏览器中打开一个新的Tab页面时,空白页会展示出一些有趣的插图、句子、电影截图等,给苦涩的搬砖生活增添一丝乐趣,效果如下:
实现方案很简单,页面就是一个普通的前端页面,配置少许的 manifest.json
便可以直接转换为 Chrome 扩展程序,而后端服务是一个 HTTP 接口,返回页面展示的内容,该接口使用了阿里云的 Faas 服务,是一种 Serverless 概念的实现方式,总之该接口无须部署在自己的服务器上,而是直接放在阿里云平台上,具体见下文。
假如你科学上网,便可以访问该链接 下载体验,或者在应用市场 搜索“何遇”下载。
项目前后端源代码已经上传到 Github ,欢迎一起交流,传送门: heyu
什么是 Serverless
简单介绍
Serverless 是最近一个非常火热的话题,在文章的开始,我们必须澄清 Serverless 并不是按照字面理解上的“无服务器”,其准确含义是表示对于开发者而言,不再需要关注大部分与服务器相关的事物,比如服务器的选购、服务器系统环境、日志收集、系统监控、负载均衡等琐事,这些重复且复杂的活都交给 Serverless 平台即可,开发者只需要专注业务逻辑的开发。
初识 Serverless
最早接触到 Serverless 概念时,是在我2017年大二暑假,那时候需要实现一个招聘类的小程序,当时苦于后端经验不足,只会写一些简单 CURD 的 java 代码,而对于服务的部署、域名解析、https 证书部署、日志、监控、负载均衡等知识了解甚微,当我快要放弃时,遇到了当时国内最早一批 Serverless 服务商leancloud,leancloud 提供一套完整的小程序后端解决方案,只需要在平台上建立数据库,便可以直接在前端操控 API 来对数据库进行 curd 操作,其他的一切都不需要操心,除了小程序外,leancloud 还提供 APP 上类似的服务,在我结识的一些独立开发者,已经有一部分项目已经完全使用该服务,其便捷性和稳定性已经得到大家的认可,当然,需要切身体验才能确定其是否真正适合你所开发的业务。
这是我开源的一个使用 Serverless 概念开发的微信小程序: 基于LeanCloud为后端的 “云校招” 微信小程序 ,假如你是一个不熟悉后端的前端开发者,却又想开发一个完整的项目,可以参考该项目。
分类
Serverless应用可以细分为BaaS和FaaS两类:
-
BaaS: Backend as a Service,这里的Backend可以指代任何第三方提供的应用和服务,比如提供云数据库服务的Firebase和Parse,提供统一用户身份验证服务的Auth0和Amazon Cognito等。
-
FaaS: Functions as a Service,应用以函数的形式存在,并由第三方云平台托管运行,比如之前提到的Amazon Lambda,Google Cloud Functions等。
本篇实战,主要用到了阿里云提供的 FaaS 服务,并且大部分内容都是围绕者 FaaS 来论述。
Serverless 其他优势
除了上述说到的“无需运维”的优势外,Serverless 还有哪些优势值得我们去实践呢?
按需付费成本低
每一个 Faas 只会在触发的情况下,才会进行计费,而不是像传统部署在服务器上的服务无时无刻都在收费。Faas的费用由调用次数费用、执行时间决定的,简单来说,一个函数执行设置内存为128MB,执行时间是200ms,则一次执行所消耗的资源为 0.128GB * 0.2s = 0.0256GB-S,假设调用了100万次,只消耗大概4元人民币,因此换算过来,假如一个用户每天调用20次该函数,你有5万活跃用户,则该函数一天只需要4元人民币的成本。
详情:计费计算器
弹性伸缩
当该 Faas 触发频率猛增的时候,服务商能够毫秒级别弹性伸缩,快速实现底层扩容以应对峰值压力,提升了服务在特殊情况下的稳定性。
事件驱动
上文我们说到的 Faas 触发,那么怎样触发一个 Faas 呢?阿里云的 Faas 提供了多种触发器,如HTPP触发器、对象存储触发器、日志服务触发器、定时触发器等,这里的便捷在于:假如你使用了大部分阿里云的其他云服务,这些服务便能与 Faas 无缝对接,不得不说阿里云的生态在这几年里发展很迅速。
Faas(函数计算)实践
Hello Word Demo
我们先来实现一个简单的 Faas,使用HTTP触发器,当我向一个接口发送请求后,返回一个"hello word"字段。
访问阿里云Faas 当用户第一次使用阿里云 Faas 时,需要开通一系列的服务,当然都是免费的,开通函数计算(Faas)服务后,便可以在控制台中新建函数。
- 选择函数模版,这里我们选择NodeJs8
- 选择函数触发器,这里我们选择HTTP触发器,认证方式这里我们先用不到,选择anonymous。
- 编写 Faas 函数
这里的函数的代码如下:
module.exports.handler = function(req, resp, context) { console.log('hello world'); var params = { path: req.path, queries: req.queries, headers: req.headers, method : req.method, requestURI : req.url, clientIP : req.clientIP, } console.log(params); resp.send(JSON.stringify({content: 'hello word'})); } 复制代码
这里我们通过req来获取请求信息,resp用来返回数据,context 可以获取到函数上下文。
-
权限选择,这里我们先不选择,因为没用用到与权限相关的功能。
-
调用函数,创建完函数后,对于HTTP为触发器的 Faas,会默认一个url来调用该函数,当然,也可以指定域名和路径。
这里,我们只需要几步,就完成了一个公网下可以调用的api,试想,我们还能用 Faas 做些什么呢,能不能做一些复杂的逻辑,比如爬取某个网站上的数据,将数据放入body返回给调用者。
爬虫服务
之前我写过一篇关于爬虫的博客,使用现有的轮子实现起来也很简单,具体见我另外一篇博客 NodeMail ,我们以实现一个获取随机获取One上的每日推荐函数为例,创建一个含有自定义包的 Faas 函数。
遇到的问题:我们上面的 demo 中,没有用到任何外部 npm 包,为了实现该需求,我们需要调用 npm 上的包,因此,在 Faas 平台上无法在线编辑,这时需要在本地创建一个 node 项目,安装所需要的包,编写业务代码,具体步骤:
- 在pc本地创建一个文件夹
FaasTest
,初始化项目,然后使用npm或者yarn安装所需包
npm init npm i superagent cheerio moment 复制代码
- 创建
index.js
,编写爬虫代码
const superagent = require("superagent"); // 发送网络请求获取DOM const cheerio = require("cheerio"); // 能够像Jquery一样方便获取DOM节点 const moment = require("moment"); // function getOneContent() { return new Promise(function(resolve, reject) { let min = 1800; let max = moment().diff(moment("2017-08-14"), 'days') + 1800; // 获取2017-08-14开始的内容 let target = Math.floor(Math.random()*(max-min+1)+min); // 获取随机数 superagent.get(`http://wufazhuce.com/one/${target}`).end(function(err, res) { if (err) { console.log(err); } let $ = cheerio.load(res.text); let selectItem = $("#main-container .tab-content")[0]; let data = { imgUrl: $(selectItem).find('.one-imagen img').attr("src"), tag: $(selectItem).find('.one-imagen-footer .one-imagen-leyenda').text().replace(/(^\s*)|(\s*$)/g, ""), content: $(selectItem).find('.one-cita-wrapper .one-cita').text().replace(/(^\s*)|(\s*$)/g, ""), } resolve(data); }); }) } getOneContent().then(res=>{ console.log(res) }) 复制代码
我们可以在本地测试该项目,再改造成 Faas 需要的代码规范。
- 改造为 Faas 规范
我们从第一个 hello word 的 demo 中看到,以HTTP为触发器的 Faas 函数有以下代码包裹着:
module.exports.handler = function(req, resp, context) { // other code } 复制代码
使用 resp 来返回爬取的数据,改造后的代码如下:
const superagent = require("superagent"); //发送网络请求获取DOM const cheerio = require("cheerio"); //能够像Jquery一样方便获取DOM节点 const moment = require("moment"); module.exports.handler = function(req, resp, context) { getOneContent().then(res=>{ resp.send(JSON.stringify(res)); }) } function getOneContent() { return new Promise(function(resolve, reject) { let min = 1800; let max = moment().diff(moment("2017-08-14"), 'days') + 1800; let target = Math.floor(Math.random()*(max-min+1)+min); superagent.get(`http://wufazhuce.com/one/${target}`).end(function(err, res) { if (err) { console.log(err); } let $ = cheerio.load(res.text); let selectItem = $("#main-container .tab-content")[0]; let data = { imgUrl: $(selectItem).find('.one-imagen img').attr("src"), tag: $(selectItem).find('.one-imagen-footer .one-imagen-leyenda').text().replace(/(^\s*)|(\s*$)/g, ""), content: $(selectItem).find('.one-cita-wrapper .one-cita').text().replace(/(^\s*)|(\s*$)/g, ""), } resolve(data); }); }) } 复制代码
以上代码已经上传到 Github ,传送门: Faas
- 使用 fcli 将项目部署到 Faas 平台
这一步原本可以直接打包成 zip 进行代码包上传,但是在我的本地系统下会出 bug,文档中有另外一种方法,使用阿里云的 Faas shell 工具:fcli.
下载 fcli 初始化后,进入 fcli 所在目录,输入 ./fcli shell
进入交互模式,输入 ls
查看服务列表,进入列表 cd xxx
,更新函数的代码包:
upf hello -d /Users/vince/Desktop/FaasTes 复制代码
- upf hello :更新 hello 函数
- -d /Users/vince/Desktop/FaasTes :-d 表示需要上传代码包所在的目录
- 测试接口,使用 postman 测试接口,简单的后端服务即完成。
开发一个简单的 Chrome 扩展程序
Chrome 扩展程序并不是什么新奇的技术,简单来说就是一个 web 应用,根据 Chrome 扩展程序的规范,按照给出的接口定制开发部分代码,更改一些配置,这里有一篇很好的指南推荐给大家 《Chrome插件开发全攻略》 。
需求描述
具体需求是每次打开一个新的 tab,都展示一个 web 页面,web 页面上的内容从 Faas 中获取,为了优化体验,保证每次打开 Tab 页面能马上展示内容,这里我们提前将获取到的内容保存在 localStorage 供下次展示,因此我们每次看到的内容其实是上一次获取到的,这样就能保证内容能立即现实。
具体实现
逻辑实现
这里我们选用 React 简单创建一个项目,在 App.js
中编写以下代码:
import React from 'react' import axios from 'axios' import './App.scss' // 第一次运行时,加载初始内容 const initData = { imgUrl: 'http://image.wufazhuce.com/Fj7Xcw1A0EICyyVSYDnU7FEL8l3H', tag: '插画', content: '喜欢和讨厌是自己无法选择的,所以一旦喜欢上了,不管你是什么样子,我都喜欢你。', } class App extends React.Component { constructor(props) { super(props) this.state = { content: null, } } componentDidMount() { // 假如localStorage中无数据,则加载initData const data = localStorage.getItem('content') ? JSON.parse(localStorage.getItem('content')) : initData this.setState({ content: data, }) this.getContentAndSave() } getContentAndSave() { axios({ method: 'get', url: 'https://1556981199176880.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/test/hello/', }).then((res) => { // 保存数据到localStorage localStorage.setItem('content', JSON.stringify(res.data)) // 预加载img if (res.data.imgUrl) { const img = new Image() img.src = res.data.imgUrl } }) } render() { const { content } = this.state return ( <div className="app"> <If condition={content}> <div className="content"> <img src={content.imgUrl} alt="" /> <div className="tag">{content.tag}</div> <div className="slogan">{content.content}</div> </div> </If> </div> ) } } export default App 复制代码
这里只是一个简单的 web 应用,那么如何将其转换为 Chrome 拓展程序呢?
转换为 Chrome 拓展程序
首先,我们将该 React 项目 build 后,在 dist 文件下添加一系列文件,这里有个关键的文件 manifest.json
,这里描述的是Chrome 拓展程序的信息:
{ "manifest_version": 2, "name": "heyu", "version": "1.0", "description": "每一次的New Tab,都是一场最美好的相遇。", "author": "vince", "omnibox": { "keyword" : "heyu" }, "icons": { "48": "icon.png", "128": "icon.png" }, "background": { "scripts": ["background.js"], "persistent": false }, "browser_action": { "default_icon": "icon.png" }, "chrome_url_overrides": { "newtab": "index.html" } } 复制代码
我们来讲解一下该项目中比较重要的几个参数
-
chrome_url_overrides: 表示覆盖特定页面,使用override页可以将Chrome默认的一些特定页面替换掉,改为使用扩展提供的页面,这里我们就使用打包后的主页
index.html
。 -
background:后台,,它随着浏览器的打开而打开,随着浏览器的关闭而关闭,这里我们使用到了
scripts
参数,表示打开页面时即运行background.js
脚本:
chrome.browserAction.onClicked.addListener(() => { chrome.tabs.create({ 'url': 'chrome://newtab' }) }) 复制代码
该段代码表示当触发 browserAction 时,打开一个 newtab 页面,那么怎样触发 browserAction 呢?也就是当你下载该拓展程序后,在浏览器右上角点击该 icon 时,即触发 browserAction 事件。
其他的配置具体表示什么,在我上面分享的开发指南中有具体讲解。
现在我们 dist 文件夹下有以下文件:
├── background.js ├── favicon.ico ├── icon.png ├── index.html ├── js │ └── bundle.js └── manifest.json 复制代码
以上源码已经上传到 Github ,传送门: ChromeExtension
测试拓展程序
一切就绪后,我们打开网页,输入 chrome://extensions/
,右上角开启开发者模式,直接拖入 dist
文件夹自动安装拓展程序。
试试打开一个新的 Tab 页面后,展现了我们开发的 web 页,或者我们直接点击右上角的 icon ,也能打开一个新的页面。
总结
对于 Serverless ,本篇文章所讲解的实践只是其很小的一部分,而对于 Faas ,我们还能用它来实现更多业务场景,比如部署定时任务、图片处理(转码、水印)、音频转换、文字处理等“一次性”的计算,这类计算往往不需要复杂的鉴权操作,功能单一,无状态,非常适合将其完全剥离出来,单独进行维护与部署。
以上所述就是小编给大家介绍的《使用 Serverless 为后端服务开发一个有趣的 Chrome 扩展程序》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- flask通过配置文件实现程序可扩展
- 算法 – 如何使我的应用程序扩展良好?
- Linux 端 Firefox 63 扩展程序将默认独立进程
- Google 禁止从第三方网站安装 Chrome 扩展程序
- AMDVLK驱动程序采用了几个新的Vulkan扩展
- 图形 API 规范 Vulkan 1.1.97 发布:新增5个扩展程序
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Struts 2 in Action
Don Brown、Chad Davis、Scott Stanlick / Manning Publications / 2008.3 / $44.99
The original Struts project revolutionized Java web development and its rapid adoption resulted in the thousands of Struts-based applications deployed worldwide. Keeping pace with new ideas and trends......一起来看看 《Struts 2 in Action》 这本书的介绍吧!