活动运营知识分享

活动运营一般是企业对不同形式、不同性质的活动来进行运营 ,包括了活动的策划、实施和相关的业务串联结合。

如何去做好活动运营呢?活动运营日常所包含的工作可分为文案策划、经费估算、设计流,以及效果统计、规则制定、效果统计等。

严格地来说,活动策划方案流程是整个活动的根本思路,必须要对主题、时间、对象、描述、投放渠道、成本预估、规则详情、监测指标、效果预测等去进行详细合理的分析和安排。

具体细节

营销创意——做活动有新意对新用户更具有吸引力。

活动工具——活动工具能提高活动的丰富程度。

文案策划——可涉及到文案、活动流程、多媒体媒介等。

渠道运营——通过多种渠道来进行推广,与其它渠道进行合作,增加活动的曝光量。

团队执行——拉新引流、用户留存、转化成交、计划总结。

用户分析——从用户的心理行为进行出发,挖掘用户需求。

解决痛点——通过对用户痛需求的挖掘,营造热点来进行吸引。

数据分析——通过对数据进行实时监测,及时做好活动调整。

用户留存——运营者要做好沟通专业的工作,引导活动运营。

活动运营不仅仅能够起到用户拉新的作用,还能够促活用户活跃,提升用户留存的效果,好的活动运营能大大提高品牌和产品的名气和影响力。

发表在 产品 | 标签为 | 留下评论

程序员必备的项目时间估算指南

有位 PM 最近告诉我她面临的一个难题:“软件工程师永远不能估算出他们的项目需要多长时间。我该怎么办?”还有两位 CEO 最近也告诉我同样的事情。

《为什么程序员总是不能准确估测项目时间?》(http://blog.jobbole.com/24924/),我们都深有体会。我曾经遇到过一个项目,预计需要两天完成,结果做了四个月。在这种情况下,即使用“时间翻倍”的经验估算,也依然差出了一个数量级之多。这样真的非常影响业务。我曾见过整个公司为了举办一个发布活动费尽心力,结果却不得不推迟数月。

从高级层面上讲,这个问题在于在时间估算的时候,工程师、PM、经理、公关以及其他所有人的看法存在不同。大多数工程师本能考虑的是,如果一切都按照计划进行,写出一个可用的原型需要的最短时间。但下游的人想知道的是项目何时准备发布——这完全是另外一回事了。

image.png

对于工程师而言,把握估算项目所需时间是一段终身的旅程。忽视这个问题,会给你以及与你直接或间接接触的每个人带来困扰。精准把握估算项目所需时间会让你脱颖而出,同事们将会把这些和你的专业精神,稳定性和工作质量相关联。

为什么我们要时间估算

首先我来回答一下工程师经常问到的问题:“为什么要估算时间?”许多工程师抱怨(有一定道理)这是一份间接成本。“如果我开足马力去做,会更快地完成项目!”

主要有两个原因:外部依赖和优先次序。

外部依赖

没有任何有效活动会在真空中运作。项目通常有外部依赖,例如与非工程团队(通讯,金融,公关,客服)、其他工程团队甚至最终用户本身的协作。协调这些外部依赖关系通常是经理、PM或CEO的职责。这意味着最有资格做时间估算的人(工程师)不是最需要估算时间信息的人。这种不对称导致了根本的矛盾。

优先次序

时间估算也是确定工作优先级的关键。“钱花的值不值”是项目中的重要指标,没有真正的估算,也就无法确定钱花的值不值。即使你正在做的功能是世界上最棒的,如果花时间做一个全面的估计,你可能会意识到这将需要花费很长时间才能完成。

假设你正在做一个项目,这将使网站的速度提升50%,但在相同的时间内,可以完成两个项目,每个项目将使网站快40%。如果没有花时间做一个初步的估计,你永远不会知道你可以做出一个访问速度更快的网站!

时间估算入门

现在大家都同意绝大多数时候都需要时间估算,我们来谈谈技巧。

我们低估时间是因为我们考虑的是“我需要多长时间才能写出这个基本版本?”

但交付的东西不仅仅是基础版。还需要考虑到编写,测试,调试和润色所需的时间。不要忘了开会、访谈、做代码审查以及发送电子邮件等事情也需要时间。

低估时间的另一个原因是我们几乎总是在编码过程中遇到“未知数”,这些未知数是不可能完全预测和考虑周全的。也许IDE会更新,中断了项目,你花费一天的时间去修复它。在时间估算中无法考虑到这一点。

但是,我们仍然可以比最初的直觉做的更好。以下是我的做法:

第一步:制定技术计划

在着手开始工作前,你应该已经有了一份技术规划或设计文件,可以为任何重要的项目提供帮助。可以用这个让别人知道你在做什么,并获得反馈。制定技术计划是启动时间估算的理想阶段。当完成技术细节设计时,会发现未知问题,你将会神奇地修改估算时间。也许你会意识到,可能需要把一个正在使用的库升级到新版本,这可能会增加一天的时间。甚至可能意识到计划使用的库实际上并不存在,需要自己写。

颗粒度在这里很重要。如果任何一步感到模糊或者不清楚,或许你会跳过这个步骤(应该学习更多),或者需要将其分解成更小的步骤。同时如果某个步骤粒度太细,那么在实践中可能会不堪一击使整个计划无效。

有关技术计划里应该考虑哪些方面,请参阅 Alicia Chen 的这篇文章《What do you mean ‘we need more time’?》。其中一个关键点是消除与 PM 或其他利益相关方之间的任何潜在歧义,这样最终你就不会因做错了某些事而不得不重新开始。

第二步:为每个步骤增加时间预算

估算一下技术方案中的每一步将执行多长时间。这通常会涉及对细节的研究(“有没有已经有人实现了这个库的功能?”)。根据项目的性质,罗列一个简单原型,可能会有助于暴露出许多未来潜在的痛点。

第三步:添加大量的额外时间

现在你已经有一个初步的估计,但是我们之前提到的所有的点还需要考虑。

  • 随时调试:总是会有Bug。调试很大程度上取决于你对特定代码库的经验和代码库的成熟度。
  • 会议、访谈、假期等:可能你不会在工位一直编码。你真正会有多少个小时进行编码?估算时应该至少看看你的日历。
  • 最终测试和bug清理:通常你在编码的同时应该也在写测试,但是很多团队在发布前,需要进行一轮润色工作或集成测试。在估算中要给予这些工作足够的预算。如果分阶段进行推出,最初推出的1%内容,可能会暴露需要修复的bug,需要考虑到这一点。
  • 代码审查:项目需要做几轮代码审查?通常需要多长时间?一定要确保有充足的评审人员(也可以确认一下他们的日程安排)。如果这是只有一个评审人员的项目,应该提前征求他们同意,要求他们安排一名候补人员,以防评审人员会休假或者在关键节点太忙。

一旦开始将所有这些时间开销添加到项目中,就会开始看到自己的时间估算值与项目实际启动时匹配地多了。是的,实际情况可能会比估计的更长,你可能会倍感压力去缩短工期。但是当大家知道他们可以依靠你时,他们会欣赏你的估算。

第四步:项目发布后,对时间估算做回顾总结

在项目完成之后回顾一下所做的工作,这听起来很痛苦。但是这种审查回顾会让你从中学到很多,下次做的更好。

哪个过程结果与预期的时间不同?如果集成测试花费了比预期两倍的时间,记下来,下次给测试留下更多的时间。或者尝试改进集成测试系统。

你一定会看到自己的估算随着时间的推移而不断改善。甚至可以在这个过程中提出一些很好的见解,来帮助整个团队。

最后,一切都与沟通有关

你的时间表和其他变动事宜,应该提前告知其他人。如果在发布前一个月让经理知道你正在使用的库中存在新的安全漏洞,不得不从头开始,他们会有时间相应的通知公关,财务或用户,需要推迟发布。

和其他协作方沟通得来的重要反馈,有助于调整时间估算。设计师可能会说:“哦,如果这个花哨的动画将要花一整周的时间,我们可以完全剪掉它。”PM可能会补充说:“这只是用户研究中的一个原型实验。我们不需要为这个迭代做太多的bug清理。”经理可能会说,“你把一半的时间用在了开会?我来解决这个事情!”

对于工程师来说,不要为了取悦上级,向不切实际的时间表妥协。坦诚地说出你的估算时间和变更方式,这样更专业。

对于其他所有人来说,尊重估算的时间是很难的,而且这需要一个过程。你只能坐下来砍掉实际上不需要发布的功能或阶段,来缩短预计的时间,而不是通过唠叨把时间缩短。

我们永远无法完美估算项目所需的时间。唯一的办法就是保持开放、多沟通、有同理心,并果断地确定优先次序。

发表在 研发 | 标签为 , | 留下评论

前端需要了解的计算机网络知识

概述

  • 七层网路协议
    • 物理层 -> 数据链路层 -> 网络层 -> 传输层 -> 会话层 -> 表示层 -> 应用层
  • http和tcp
    • http是应用层协议,tcp是传输层协议
    • 常见的应用层协议还包括:telnet,ssh,smtp,pop,ssl/tls,mime 常见传输层协议还有:udp,sctp

Web和HTTP

HTTP概况

  • HTTP服务器并不保存关于客户的任何信息,因此HTTP是一个无状态协议(stateless protocol)

非持续连接和持续连接

  • 采用非持续连接的http是每个tcp最多允许传输一个对象

HTTP报文格式

  • HTTP请求报文
    • 请求行=方法+sp+URL+sp+版本+cr+lf
    • GET /somedir/page.html HTTP/1.1
    • 首部行=首部字段名+sp+值+cr+lf
    • Host:www.someschool.edu
    • Connection:close
    • User-agent:Mozilla/5.0
    • Accept-language:fr
    • 空行=cr+lf
    • 实体主体
  • HTTP响应报文
    • 状态行=版本+sp+状态码+sp+短语+cr+lf
    • HTTP/1.1 200 OK
    • 首部行=首部字段名+sp+值+cr+lf
    • Connection:close
    • Date:Tue,09 Aug 2011 15:44:04 GMT
    • Server:Apache/2.2.3 (CentOS)
    • Last-Modified:Tue,09 Aug 2011 15:11:03 GMT
    • Content-Length:6821
    • Content-Type:text/html
    • 空行=cr+lf
    • 实体主体

http 状态码

  • 101 websocket 双向通信
  • 200 成功
  • 204 没有响应体
  • 206 断点续传
  • 301 永久重定向
  • 302 临时重定向
  • 304 缓存 只能服务端设置
  • 401 没登录没有权限
  • 403 登录后没有权限
  • 404 没有资源
  • 405 请求方法不存在或不支持
  • 502 负载均衡

发送请求的方式

  • 浏览器 默认get请求
  • postman
  • 命令行 mac curl

管线化

  • 管线化不需要等待上一次请求得到响应就可以执行下一次请求,实现并行发送请求。只有GET和HEAD请求可以进行管线化,而POST有所限制

请求方法 RestfulApi 根据不同的动作 做对应的处理

  • get 获取资源
  • post 新增资源
  • put 上传文件 修改(restful)
  • delete 删除资源
  • options 跨域出现 复杂请求时出现 仅是get/post都是简单请求 但加上自定义头header就会变成复杂请求

用户与服务器交互:cookie

  • cookie组件
    • 在http响应报文中的一个cookie首部行
    • 在http请求报文中的一个cookie首部行
    • 在用户端系统中保留有一个cookie文件,并由用户的浏览器进行管理
    • 位于Web站点的一个后端数据库
  • cookie安全性
    • cookie 是存放在浏览器上的 服务器可以设置 每次请求时都会带上cookie
    • cookie 不安全 不能存放敏感信息
    • session 服务端 (基于cookie) 服务器的内存中,存到redis数据库

Web缓存

  • Web缓存器(Web cache)也叫代理服务器(proxy server),它能够代表初始web服务器来满足http请求的网络实体
  • http缓存
    • 强制缓存

    • Cache-Control && Expires

    • 对比缓存

    • Last-Modified & If-Modified-Since

    • ETag & If-None-Match
  • Cache-Control – private 客户端可以缓存 – public 客户端和代理服务器都可以缓存 – max-age=60 缓存内容将在60s后失效 – no-cache 需要使用对比缓存验证数据,强制向源服务器再次验证(没有强制缓存) – no-store 所有内容都不会缓存,强制缓存和对比缓存都不会触发(不缓存)

DNS

  • DNS是域名解析系统 Domain Name System
  • DNS工作原理
    • 分布式层次数据库
    • 根DNS服务器
    • TLD顶级域(DNS)服务器 com org edu
    • 权威DNS服务器
    • 本地DNS服务器与三个服务器的查询关系 从请求主机向本地DNS服务器发出的查询是递归查询,从本地DNS服务器向其他三种服务器查询为迭代查询
    • DNS缓存
    • 在一个请求链中,当DNS服务器缓存了一台主机名/IP地址对,另一个对相同主机名的查询就能够提供所要求的IP地址,本地域名服务器一般会缓存顶级域名服务器的映射
  • DNS记录和报文
    • 资源记录(Resource Record,RR)是一个包含了(Name,Value,Type,TTL)的四元组
    • DNS报文
    • 12字节
      • 标识符
      • 标志
      • 问题数
      • 回答RR数
      • 权威RR数
      • 附加RR数
    • 查询的名字和类型自窜
      • 问题(问题的变量数)
    • 对查询的响应中的RR
      • 回答(资源记录的变量数)
    • 权威服务器的记录
      • 权威(资源记录的变量数)
    • 可被使用的附加”有帮助”的信息
      • 附加信息(资源记录的变量数)
  • DDos攻击
    • 分布式拒绝服务(DDos)带宽洪泛攻击

TCP连接

TCP报文段结构

  • 源端口号+目的端口号
  • 序号
  • 确认号
  • 首部长度+保留未用+URG+ACK+PSH+RST+SYN+FIN+接收窗口
  • 因特网校验和+紧急数据指针
  • 选项
  • 数据

TCP连接管理(三次握手)

  • 第一步:客户端的TCP首先向服务器端的TCP发送一个特殊的TCP报文段
  • 第二步:一旦包含TCP SYN报文段的IP数据报到达服务器主机(假设它的确到达了),服务器会从该数据包中提取出TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段
  • 第三步:在收到SYNACK报文段后,客户也要给该连接分配缓存和变量

IP地址

IPv4 vs IPv6

  • IPv4数据报格式
    • 版本(0-4)+首部长度(4-8)+服务类型(8-16)+数据报长度(16-31)
    • 16比特标识(0-16)+标志(16-19)+13比特片偏移(19-31)
    • 寿命TTL(0-8)+上层协议(8-16)+首部检验和(16-31)
    • 32比特源IP地址
    • 32比特目的IP地址
    • 选项(如果有的话)
    • 数据
  • IPv6数据报格式
    • 版本(0-4)+流量类型(4-12)+流标签(12-31)
    • 有效载荷长度(0-16)+下一个首部(16-24)+跳限制(24-31)
    • 源地址(128比特)
    • 目的地址(128比特)
    • 数据

IPV4编址

  • 子网:不跨越路由器的路由器接口和主机接口就形成一个子网
  • 子网掩码:IP地址为某个子网分配的一个223.1.1.0/24的地址,这种/24的记法,称为子网掩码(network mask),指示了32比特中的最左侧24比特定义了子网地址

class NetIDs Blocks A 10 1 B 172.16-172.31 16 C 192.168.0-192.168.255 256

CDN

  • CDN操作
    • 当用户主机中的一个浏览器指令检索一个特定的视频(由URL标识)时,CDN必须截获该请求,以便能够确定此时是混合用于该客户的CDN服务器集群以及将客户的请求重定向到该集群的某台服务器
  • 集群选择策略
    • 任何CDN部署,其核心是集群选择策略(cluster selection strategy),即动态地将客户定向到CDN中服务器集群或数据中心的机制。
    • 常见策略:
    • 周期性实时测量;IP任播(客户与CDN服务器匹配)

网络安全

密码学基础

  • 对称密钥密码机制
    • 对称密钥系统(symmetric key system) 双方密钥是相同的并且是秘密的
    • 块密码 将要加密的报文处理成k比特的块
    • DES(Data Encrypiton Standard) 数据加密标准
    • AES(Advanced Encryption Standard) 高级加密标准
  • 公开密钥系统
    • 公开密钥系统(public key system) 使用一对密钥:一个密钥为双方都知道,另一个密钥只有一方知道
    • RSA算法(Ron、Adi、Leonard三个人名)
    • 大数分解和素性检测
  • 密码散列函数
    • MD5散列算法
    • 填充->添加->初始化累加器->循环
    • SHA-1(Security Hash Algorithm)
  • SSL
    • SSL(Secure Socket Layer) 安全套接字层
    • SSL握手
    • 1)客户发送它支持的密码算法的列表,连通一个客户的不重数
    • 2)从该列表中服务器选择一种对称算法,一种公钥算法和一种MAC算法,并把选择以及证书和一个服务器不重数返回给客户
    • 3)客户验证该证书,提取服务器公钥,生成一个前主密钥(Pre-Master Secret),用服务器的公钥加密该前主密钥,并将加密的PMS发送给服务器
    • 4)使用相同的密钥导出函数,客户和服务器独立地从PMS和不重数中计算主密钥(Master Secret),将该MS切片申城两个密码和两个MAC密钥
    • 5)客户发送所有握手报文的一个MAC
    • 6)服务器发送所有握手报文的一个MAC
发表在 研发 | 标签为 | 一条评论

59条有趣的程序员编程箴言

微信截图_20190722150833.png

下面收集的语录涉及软件开发、代码维护、调试纠错、软件bug、系统设计、文档、代码质量、测试和软件开发团队管理等方面。虽然它们有些搞笑,但却真实无比。只有程序员才能理解这些编程语句里的真正内涵。

程序员编程语录

  1. 一个好的程序员是那种过单行线马路都要往两边看的人。(Doug Linder)
  2. 程序有问题时不要担心。如果所有东西都没问题,你就失业了。(软件工程的Mosher定律)
  3. 程序员的麻烦在于,你无法弄清他在捣腾什么,当你最终弄明白时,也许已经晚了。(超级计算机之父Seymour Cray)
  4. 我想大部分人都知道通常一个程序员会具有的美德。当然了,有三种:懒惰,暴躁,傲慢。(Perl语言发明者Larry Wall)
  5. 编程时要保持这种心态:就好像将来要维护你这些代码的人是一位残暴的精神病患者,而且他知道你住在哪。(Martin Golding)
  6. 一个人写的烂软件将会给另一个人带来一份全职工作。(Jessica Gaston)
  7. 如果建筑工人像程序员写软件那样盖房子,那第一只飞来的啄木鸟就能毁掉人类文明。(Gerald Weinberg)
  8. 这世界最有可能毁灭的方式——大多数专家都同意——是次意外。这就是为什么会有我们,我们是计算机专家,我们创造意外。(Nathaniel Borenstein)
  9. 我们这个行业有个特别奇怪的现象:不仅我们不从失败里吸取教训,同时也不从成功中学习经验。(Keith Braithwaite)
  10. 一种新技术一旦开始流行,你要么坐上压路机,要么成为铺路石。(Stewart Brand)
  11. 如果没能一次成功,那就叫它1.0版吧。(佚名)
  12. 所有的程序员都是编剧,所有的计算机都是烂演员。(佚名)
  13. 工作进度上越早落后,你就会有越充足的时间赶上。(佚名)
  14. 当有这样的一种编程语言出现:它能让程序员用简单的英语编程,你将会发现,程序员都开始不会说英语。(佚名)
  15. 为什么我们没有时间把事情做对,却总有时间把事情做过头?(佚名)
  16. 傻瓜都能写出计算机能理解的程序。优秀的程序员写出的是人类能读懂的代码。
  17. 任何你写的代码,超过6个月不去看它,当你再看时,都像是别人写的。(Eagleson’s law)

编程/软件开发语录

  1. 按代码行数来评估软件开发的进度,就如同按重量来评估飞机建造的进度。(比尔?盖茨)
  2. 软件就像做爱。一次犯错,你需要用余下一生来维护支持。(Michael Sinz)
  3. 在水上行走和按需求文档开发软件都很容易——前提是它们都是冻结状态。(Edward V Berard)
  4. 最初90%的代码用去了最初90%的开发时间……余下10%的代码用去了另外90%的开发时间。(Tom Cargill)
  5. 注释代码很像清洁你的厕所——你不想干,但如果你做了,这绝对会给你和你的客人带来更愉悦的体验。(Ryan Campbell)
  6. 如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。(Rick Cook)
  7. 软件设计最困难的部分……是阻挡新功能的引入。(Donald Norman)
  8. 为了理解递归,我们首先要理解的是递归。(佚名)
  9. 世上只有两类编程语言:那些拥有被人诟病的和那些没人用的。(Bjarne Stroustrup)
  10. 布尔的最优秀之初,就是即使你错了,也仅仅是差了一位而已。(佚名)
  11. 如果Java能实现真的垃圾回收,那大部分的程序都会在执行时删除自己。(Robert Swell)
  12. 理论上,理论和实践是没有差异的。但实践中,是有的。(Jan L. A. van de Snepscheut)
  13. 预备,开火,瞄准:这是最快的软件开发方法。预备,瞄准,瞄准,瞄准,瞄准:这是最慢的软件开发方法。(佚名)
  14. 编程是10%的科学,20%天份,和70%的让这天份符合科学。(佚名)
  15. 评估一个事情要比去理解你评估了什么容易。(佚名)
  16. 测评不会撒谎,但测评的人会。(佚名)
  17. 培养员工,即使他们有跳槽的风险。什么都不做而留他们在公司,这样风险更大。(佚名)
  18. 计算机科学的目标是做出一个东西,并且保证它至少能坚持到我们将它开发完成。(佚名)
  19. Java之于JavaScript,如同Car之于Carpet。 (Chris Heilmann)
  20. 起初就把事情做对是完全没必要的。但最后要把事情做对是绝对必要的。(Andrew Hunt与David Thomas)
  21. 数组的起始索引应该从0开始还是从1开始?我的0.5的折中提议被他们未经认真考虑到拒绝了——我认为是这样的。(Stan Kelly-Bootle)
  22. 程序必须是为了给人看而写,给机器去执行只是附带任务。 (Abelson / Sussman)
  23. 编程可以很有趣,你可以用它做密码学研究,但两者绝对不能合二为一。(Kreitzberg 与 Shneiderman)
  24. “拷贝-粘贴”是一种设计错误。(David Parnas)
  25. 计算机善于遵循指令,但不善于理解你的思维。(Donald Knuth)

软件纠错语录

  1. 删除的代码是没有bug的代码。(Jeff Sickel)
  2. 如果纠错是消除软件bug的过程,那编程一定是把它们放进去的过程。(Edsger Dijkstra)
  3. 代码纠错要比新编写代码困难一倍。因为,如果你写出了最聪明的代码,按此推算,你将没有更大的智慧来调试它。
  4. 想在自己的代码里找出一个错误是十分困难的。而当你认为你的代码没有错误时,那就更难了。(Steve McConnel)

软件bug语录

  1. 这不是个bug——这是一个未注明的功能特征。(佚名)
  2. 没有需求或设计,编程就是一种将bug添加到一个空文本文件里的艺术。(Louis Srygley)
  3. 烂代码并不烂,只是被误解了。(佚名)
  4. 有两种方法能写出没有错误的程序;但只有第三种好用。(Alan J. Perlis)
  5. 小心上面代码中的bug;我只知道这些代码是正确的,但没有试过。(Donald Knuth)

软件产品语录

  1. 软件能够复用前,它必须要可用。(Ralph Johnson)
  2. 软件通常在beta测试完成不久后发布。Beta在拉丁语中是“还不能用”的意思。(佚名)
  3. 最好的性能改进是将软件从不能用的状态变成可用。(J. Osterhout)
  4. 最廉价、最快速、最可信赖的组件是那些还未出现的组件。(Gordon Bell)
  5. 我觉得微软的 .Net,不会显示在 Unix 目录列表。(Oktal)
  6. 软件和教堂非常相似——建成之后我们就在祈祷。(Sam Redwine)
  7. 除非最后一个用户死掉,软件是不会有完工的时候的。(佚名)
  8. 如今的大部分软件都非常像埃及金字塔,由成千上万的石块一个摞一个构成,没有结构上的集成,是由暴力强制和成千上万的奴隶完成。(Alan Kay)
发表在 研发 | 标签为 | 留下评论

了解什么是微前端

作为前端开发人员,这些年来你一直在开发单体应用,即使你已经知道这是一个不好的做法。 您将代码划分为组件,使用 requireimport 并将package.json中定义的npm包或已安装的子git仓库添加到项目中,但最终构建了一个整体。 是时候改变它了。

为什么你的代码是一个单体?

除了已经实现了微前端的应用之外,所有前端应用本质上都是单一的应用。 原因是如果您正在使用 React 库进行开发,并且如果您有两个团队,则两个团队都应该使用相同的React 库,并且两个团队应该在部署时保持同步,并且在代码合并期间始终会发生冲突。 它们没有完全分离,很可能它们维护着相同的仓库并具有相同的构建系统。 单体应用的退出被标志为微服务的出现。 但是它适用于后端!😱

什么是微服务?

对于微服务,一般而言最简单的解释是,它是一种开发技术,允许开发人员为平台的不同部分进行独立部署,而不会损害其他部分。 独立部署的能力允许他们构建孤立或松散耦合的服务。 为了使这个体系结构更稳定,有一些规则要遵循,可以总结如下:每个服务应该只有一个任务,它应该很小。 所以负责这项服务的团队应该很小。 关于团队和项目的规模,James Lewis 和 Martin Fowler 在互联网上做出的最酷解释之一如下:

在我们与微服务从业者的对话中,我们看到了一系列服务规模。 报道的最大规模遵循亚马逊关于Two Pizza Team的概念(即整个团队可以由两个比萨饼供给),意味着不超过十几个人。 在规模较小的规模上,我们已经看到了一个由六人组成的团队支持六项服务的设置。

我画了一个简单的草图,为整体和微服务提供了直观的解释:

从上图可以理解,微服务中的每个服务都是一个独立的应用,除了UI。 UI仍然是一体的! 当一个团队处理所有服务并且公司正在扩展时,前端团队将开始苦苦挣扎并且无法跟上它,这是这种架构的瓶颈。

除了瓶颈之外,这种架构也会导致一些组织问题。 假设公司正在发展并将采用需要 跨职能 小团队的敏捷开发方法。 在这个常见的例子中,产品所有者自然会开始将故事定义为前端和后端任务,而 跨职能 团队将永远不会成为真正的 跨职能 部门。 这将是一个浅薄的泡沫,看起来像一个敏捷的团队,但它将在内部分开。 关于管理这种团队的更多信息将是一项非常重要的工作。 在每个计划中,如果有足够的前端任务或者sprint中有足够的后端任务,则会有一个问题。 为了解决这里描述的所有问题和许多其他问题,几年前出现了微前端的想法并且开始迅速普及。

解决微服务中的瓶颈问题:Micro Frontends🎉

解决方案实际上非常明显,采用了多年来为后端服务工作的相同原则:将前端整体划分为小的UI片段。 但UI与服务并不十分相似,它是最终用户与产品之间的接口,应该是一致且无缝的。 更重要的是,在单页面应用时代,整个应用在客户端的浏览器上运行。 它们不再是简单的HTML文件,相反,它们是复杂的软件,达到了非常复杂的水平。 现在我觉得微型前端的定义是必要的:

Micro Frontends背后的想法是将网站或Web应用视为独立团队拥有的功能组合。 每个团队都有一个独特的业务或任务领域,做他们关注和专注的事情。团队是跨职能的,从数据库到用户界面开发端到端的功能。(> micro-frontends.org> )

根据我迄今为止的经验,对于许多公司来说,直接采用上面提出的架构真的很难。 许多其他人都有巨大的遗留负担,这使他们无法迁移到新的架构。 出于这个原因,更柔软的中间解决方案更加灵活,易于采用和安全迁移至关重要。 在更详细地概述了体系结构后,我将尝试提供一些体系结构的洞察,该体系结构确认了上述提议并允许更灵活的方式。 在深入了解细节之前,我需要建立一些术语。

整体结构和一些术语

让我们假设我们通过业务功能垂直划分整体应用结构。 我们最终会得到几个较小的应用,它们与单体应用具有相同的结构。 但是如果我们在所有这些小型单体应用之上添加一个特殊应用,用户将与这个新应用进行通信,它将把每个小应用的旧单体UI组合成一个。 这个新图层可以命名为拼接图层,因为它从每个微服务中获取生成的UI部件,并为最终用户组合成一个无缝 UI,这将是微前端的最直接实现🤩

为了更好地理解,我将每个小型单体应用称为微应用,因为它们都是独立的应用,而不仅仅是微服务,它们都有UI部件,每个都代表端到端的业务功能。

众所周知,今天的前端生态系统功能多样,而且非常复杂。 因此,当实现真正的产品时,这种直接的解决方案还不够。

要解决的问题

虽然这篇文章只是一个想法,但我开始使用Reddit讨论这个想法。 感谢社区和他们的回复,我可以列出一些需要解决的问题,我将尝试逐一描述。

当我们拥有一个完全独立的独立微应用时,如何创建无缝且一致的UI体验?

好吧,这个问题没有灵丹妙药的答案,但其中一个想法是创建一个共享的UI库,它也是一个独立的微应用。 通过这种方式,所有其他微应用将依赖于共享的UI库微应用。 在这种情况下,我们刚刚创建了一个共享依赖项,我们就杀死了独立微应用的想法。

另一个想法是在根级共享CSS自定义变量( CSS custom variables )。 此解决方案的优势在于应用之间的全局可配置主题。

或者我们可以简单地在应用团队之间共享一些SASS变量和混合。 这种方法的缺点是UI元素的重复实现,并且应该对所有微应用始终检查和验证类似元素的设计的完整性。

我们如何确保一个团队不会覆盖另一个团队编写的CSS?

一种解决方案是通过CSS选择器名称进行CSS定义,这些名称由微应用名称精心选择。 通过将该范围任务放在拼接层上将减少开发开销,但会增加拼接层的责任。

另一种解决方案可以是强制每个微应用成为自定义Web组件(custom web component)。 这个解决方案的优点是浏览器完成了范围设计,但需要付出代价:使用shadow DOM进行服务器端渲染几乎是不可能的。 此外,自定义元素没有100%的浏览器支持,特别是IE。

我们应该如何在微应用之间共享全局信息?

这个问题指出了关于这个主题的最关注的问题之一,但解决方案非常简单:HTML 5具有相当强大的功能,大多数前端开发人员都不知道。 例如,自定义事件(custom events) 就是其中之一,它是在微应用中共享信息的解决方案。

或者,任何共享的pub-sub实现或T39可观察的实现都可以实现。 如果我们想要一个更复杂的全局状态处理程序,我们可以实现共享的微型Redux,通过这种方式我们可以实现更多的相应式架构。

如果所有微应用都是独立应用,我们如何进行客户端路由?

这个问题取决于设计的每个实现, 所有主要的现代框架都通过使用浏览器历史状态在客户端提供强大的路由机制, 问题在于哪个应用负责路由以及何时。

我目前的实用方法是创建一个共享客户端路由器,它只负责顶级路由,其余路由器属于相应的微应用。 假设我们有 /content/:id 路由定义。 共享路由器将解析 /content,已解析的路由将传递到ContentMicroApp。 ContentMicroApp是一个独立的服务器,它将仅使用 /:id 进行调用。

我们必须是服务器端渲染,但是有可能使用微前端吗?

服务器端呈现是一个棘手的问题。 如果你正在考虑iframes缝合微应用然后忘记服务器端渲染。 同样,拼接任务的Web组件也不比iframe强大。 但是,如果每个微应用能够在服务器端呈现其内容,那么拼接层将仅负责连接服务器端的HTML片段。

与传统环境集成至关重要! 但是怎么样?

为了整合遗留系统,我想描述我自己的策略,我称之为“ 渐进式入侵 ”。

首先,我们必须实现拼接层,它应该具有透明代理的功能。 然后我们可以通过声明一个通配符路径将遗留系统定义为微应用LegacyMicroApp 。 因此,所有流量都将到达拼接层,并将透明地代理到旧系统,因为我们还没有任何其他微应用。

下一步将是我们的 第一次逐步入侵 :我们将从LegacyMicroApp中删除主要导航并用依赖项替换它。 这种依赖关系将是一个使用闪亮的新技术实现的微应用NavigationMicroApp

现在,拼接层将每个路径解析为 Legacy Micro App ,它将依赖关系解析为 Navigation MicroApp ,并通过连接这两个来为它们提供服务。

然后通过主导航遵循相同的模式来为引导下一步。

然后我们将继续从Legacy MicroApp中获取逐步重复以上操作,直到没有任何遗漏。

如何编排客户端,这样我们每次都不需要重新加载页面?

拼接层解决了服务器端的问题,但没有解决客户端问题。 在客户端,在将已粘贴的片段作为无缝HTML加载后,我们不需要每次在URL更改时加载所有部分。 因此,我们必须有一些异步加载片段的机制。 但问题是,这些片段可能有一些依赖关系,这些依赖关系需要在客户端解决。 这意味着微前端解决方案应提供加载微应用的机制,以及依赖注入的一些机制。


根据上述问题和可能的解决方案,我可以总结以下主题下的所有内容:

客户端

  • 编排
  • 路由
  • 隔离微应用
  • 应用之间通信
  • 微应用UI之间的一致性

服务端

  • 服务端渲染
  • 路由
  • 依赖管理

灵活、强大而简单的架构

所以,这篇文章还是很值得期待的! 微前端架构的基本要素和要求终于显现!

在这些要求和关注的指导下,我开始开发一种名为microfe的解决方案。 😎在这里,我将通过抽象的方式强调其主要组件来描述该项目的架构目标。

它很容易从客户端开始,它有三个独立的主干结构:_AppsManager,__Loader,__Router_ 和一个额外的_MicroAppStore。_

AppsManager

AppsManager 是客户端微应用编排的核心。 AppsManager的主要功能是创建依赖关系树。 当解决了微应用的所有依赖关系时,它会实例化微应用。

Loader

客户端微应用编排的另一个重要部分是Loader。 加载器的责任是从服务器端获取未解析的微应用。

Router

为了解决客户端路由问题,我将 Router 引入了 microfe。 与常见的客户端路由器不同,microf 的功能有限,它不解析页面而是微应用。 假设我们有一个URL /content/detail/13 和一个ContentMicroApp。 在这种情况下,microfe 将URL解析为 /content/,它将调用ContentMicroApp /detail/13 URL部分。

MicroAppStore

为了解决微应用到微应用客户端的通信,我将MicroAppStore引入了 microfe。 它具有与Redux库类似的功能,区别在于:它对异步数据结构更改和reducer 声明更灵活。


服务器端部分在实现上可能稍微复杂一些,但结构更简单。 它只包含两个主要部分 StitchingServer 和许多MicroAppServer。

MicroAppServer

MicroAppServer 的最小功能可以概括为 initserve。

虽然 MicroAppServer 首先启动它应该做的是使用 微应用声明 调用 SticthingServer 注册端点,该声明定义了 MicroAppServer 的微应用 _依赖关系,__类型_ 和 _URL架构。_ 我认为没有必要提及服务功能,因为没有什么特别之处。

StitchingServer

StitchingServerMicroAppServers 提供注册端点。 当 MicroAppServer 将自己注册到 StichingServer 时,StichingServer 会记录MicroAppServer 的声明。

稍后,StitchingServer 使用声明从请求的URL解析 MicroAppServers。

解析M icroAppServer 及其所有依赖项后,CSS,JS和HTML中的所有相对路径都将以相关的 MicroAppServer 公共URL为前缀。 另外一步是为CSS选择器添加一个唯一的 MicroAppServer 标识符,以防止客户端的微应用之间发生冲突。

然后 StitchingServer 的主要职责就是:从所有收集的部分组成并返回一个无缝的HTML页面。

其他实现一览

甚至在2016年被称为微前端之前,许多大公司都试图通过 BigPipe 来解决Facebook等类似问题。 如今这个想法正在获得验证。 不同规模的公司对该主题感兴趣并投入时间和金钱。 例如,Zalando开源了其名为Project Mosaic的解决方案。 我可以说,微型和 Project Mosaic.遵循类似的方法,但有一些重要的区别。 虽然microfe采用完全分散的路由定义来增强每个微应用的独立性,但Project Mosaic更喜欢每条路径的集中路由定义和布局定义。 通过这种方式,Project Mosaic可以实现轻松的A/B测试和动态布局生成。

对于该主题还有一些其他方法,例如使用iframe作为拼接层,这显然不是在服务器端而是在客户端。 这是一个非常简单的解决方案,不需要太多的服务器结构和DevOps参与。 这项工作只能由前端团队完成,因此可以减轻公司的组织负担,同时降低成本。

已经有一个框架叫做 single-spa 该项目依赖于每个应用的命名约定来解析和加载微应用。 容易掌握想法并遵循模式。 因此,在您自己的本地环境中尝试该想法可能是一个很好的初步介绍。 但是项目的缺点是你必须以特定的方式构建每个微应用,以便他们可以很好地使用框架。

最后的想法

我相信微前端话题会更频繁地讨论。 如果该主题能够引起越来越多公司的关注,它将成为大型团队的事实发展方式。 在不久的将来,任何前端开发人员都可以在这个架构上掌握一些见解和经验,这真的很有用。

考虑贡献

我正在大力尝试微前端,在我的脑海中有一个崇高的目标:创建一个微框架框架,可以解决大多数问题,而不会影响性能,易于开发和可测试性。 如果您有任何明智的想法,请不要犹豫,访问我的repo,打开问题或通过下面的评论或 Twitter DM 与我联系。 我会在那里帮助你!🙂

翻译:Vincent.W
原文:Understanding Micro Frontends

发表在 研发 | 标签为 | 留下评论