跟随,学习,进步

如何用网页脚本追踪用户

2019-04-15 00:16:40 阮一峰

本文介绍如何编写 JavaScript 脚本,将用户数据发回服务器。 我做了一个代码仓库,包含了下面所有的例子,可以运行查看效果。 一、同步 AJAX 数据发回服务器的常见做法是,将收集好的用户数据,放在unload事件里面,用 AJAX 请求发回服务器。 但是,异步 AJAX 在unload事件里面不一定能成功,因为网页已经处于卸载中,浏览器可能发送,也可能不发送。所以,要改成同步 AJAX 请求。 window.addEventListener('unload', function (event) { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', false); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); }); 上面代码中,xhr.open()方法的第三个参数是false,表示同步请求。 这种方法最大的问题在于,浏览器逐步将不允许在主线程上面,使用同步 AJAX。所以,上面代码实际上不能用。 二、异步 AJAX 异步 AJAX 其实是能用的。前提是unload事件里面,必须有一些很耗时的同步操作。这样就能留出足够的时间,保证异步 AJAX 能够发送成功。 function log() { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); } window.addEventListener('unload', function(event) { log(); // a time-consuming operation for (let i = 1; i 上面代码中,强制执行了一次双重循环,拖长了unload事件的执行时间,导致异步 AJAX 能够发送成功。 三、追踪用户点击 setTimeout也能拖延页面卸载,保证异步请求发送成功。下面是一个例子,追踪用户点击。 // HTML 代码如下 // click const clickTime = 350; const theLink = document.getElementById('target'); function log() { let xhr = new XMLHttpRequest(); xhr.open('post', '/log', true); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); xhr.send('foo=bar'); } theLink.addEventListener('click', function (event) { event.preventDefault(); log(); setTimeout(function () { window.location.href = theLink.getAttribute('href'); }, clickTime); }); 上面代码使用setTimeout,拖延了350毫秒,才让页面跳转,因此使得异步 AJAX 有时间发出。 四、反弹追踪 追踪用户点击,还可以使用反弹追踪(bounce tracking)。 所谓"反弹追踪",就是网页跳转时,先跳到一个或多个中间网址,以便收集信息,然后再跳转到原来的目标网址。 // HTML 代码如下 // click const theLink = document.getElementById('target'); theLink.addEventListener('click', function (event) { event.preventDefault(); window.location.href = '/jump?url=' + encodeURIComponent(theLink.getAttribute('href')); }); 上面代码中,用户点击的时候,会强制跳到一个中间网址,将信息携带过去,处理完毕以后,再跳到原始的目标网址。 谷歌和百度现在都是这样做,点击搜索结果时,会反弹多次,才跳到目标网址。 五、Beacon API 上面这些做法,都会延缓网页卸载,严重影响用户体验。 为了解决网页卸载时,异步请求无法成功的问题,浏览器特别实现了一个 Beacon API,允许异步请求脱离当前主线程,放到浏览器进程里面发出,这样可以保证一定能发出。 window.addEventListener('unload', function (event) { navigator.sendBeacon('/log', 'foo=bar'); }); 上面代码中,navigator.sendBeacon()方法可以保证,异步请求一定会发出。第一个参数是请求的网址,第二个参数是发送的数据。 注意,Beacon API 发出的是 POST 请求。 六、ping 属性 HTML 的标签有一个ping属性,只要用户点击,就会向该属性指定的网址,发出一个 POST 请求。 click 上面代码中,用户点击跳转时,会向/log这个网址发一个 POST 请求。 ping属性无法指定数据体,似乎只能通过 URL 的查询字符串携带信息。 七、参考链接 Link Click Analytics and Privacy, John Wilander ping Attribute, David Walsh (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月15日


谈谈 panic 和 recover 的原理

2019-04-13 03:40:00 Draveness

这一节中我们将介绍 Go 语言中两个经常成对出现的关键字 panic 和 recover 的实现原理,我们在上一节关注的 defer 与这里介绍的两个关键字其实也有着比较大的关系,我们会在剩下的部分展开介绍相关的内容,没有阅读 上一节 的读者还是需要补充一下相关知识,这样才能更好地了解 panic 和 recover 关键字的原理。


每周分享第 51 期

2019-04-12 02:33:27 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 一个程序员的 Macbook 送修了,他只好重新使用10年前的笔记本电脑(上图)。结果意外地发现,虽然有点慢,但是不影响使用。10年前的电脑依然能够满足日常工作。 如果2009年的时候,让你去使用1999年的电脑,那是不可想象的,根本没有实用性。但是,2019年的时候,去使用2009年的电脑,却是完全可行的。 这说明,过去十年的硬件进展不太大,导致10年前的硬件不是那么过时。过去十年,进展主要体现在软件上面:软件功能更强大、使用更友好、界面更美观。 经济有一个定理,叫做"边际收益递减",意思是,发展到比较成熟的阶段以后,以后每一步的进展会越来越小。硬件就是如此,摩尔定理到了尽头以后,就已经开始慢下来了。我估计,硬件之后就是软件,随着软件开发技术的成熟,以后软件的进展也会放缓,总有一天,我们使用十年以前的软件,也会觉得还可以接受,当然现在还没到这一步。 软件之后的发展重点,我认为将是算法和数据,以后的进步更多会体现在算法优化和数据训练上面。 新闻 1、程序员的专用座椅 美国一家创业公司推出了程序员专用座椅,可以躺着使用三块屏幕,还有按摩功能,可以一边敲代码,一边按摩。由于这个椅子可以140度斜躺,还有脚凳和椅灯,所以也可以在上面睡觉。它的售价是3600美元。 2、世界上最短的高速公路 世界最短的高速公路就在罗马尼亚,长度为1米。当地的一个快餐店老板自费4500欧元,建造了这条1米的四车道高速公路。他是为了抗议政府忽视公路建设,"他们说这个地区不适合建设高速公路,我就造1米给他们看看。"罗马尼亚的面积与英国相当,但是高速公路只有806公里,大约是英国五分之一。 3、海上隔离 美国海军军舰麦克亨利号(US McHenry)在波斯湾执行任务时,全舰700多名官兵中有25人感染了腮腺炎。结果,全舰就被隔离在海上,整整两个月不得靠岸,所有人都没法下船,补给由其他船只运送过来。看上去,以后对于那些高传染性的疾病,海上隔离似乎是一个可行的方案。 4、发光滑雪板 美国一家公司推出了会发光的滑雪板,售价500美元。不过,该公司没说,这是白天用的,还是夜晚用的。如果是夜晚使用,是为了观众能看清楚滑雪的轨迹吗? 5、刷脸乘地铁 3月8日,深圳地铁公司在福田站,开通了"刷脸乘地铁"的测试通道。乘客可以先在地铁公司登记,然后进站时,不需任何动作,只需将脸正对一个平板电脑的摄像头,就能刷脸扣款。目前还不知道,该服务何时会在深圳地铁的其他站点使用。 6、柔软的机器手 机器手臂通常都是钢铁材质,牢牢抓取物体的时候,很容易造成物体损伤。为了解决这个问题,麻省理工学院的科学家发明了柔软的机器手。它是一个橡胶做的套子,可以像花朵一样打开和关闭。 当它套住物体的时候,会泵出里面的气体,通过气密性,使得大气压将套子牢牢压在物体上面,从而能够在不损伤物体的情况下,拾取精细的物品。它能够抓起自身重量100倍的物体。 7、雨伞发电 台湾和美国的科学家研发出一种可以发电的雨伞。这种雨伞利用雨和风与伞面产生的摩擦电能,进行发电。伞和雨衣上的纳米发电机可以收集水滴的冲击能量,将其转化为电能。 这种面料可用于开发自供电的照明雨具,以帮助防止雨天发生交通事故。在125毫升/秒的降雨量下,纳米发电机在5分钟内将 1μF 电容充电至 9V 左右。重复洗涤也不会降低这种面料的性能。 8、环卫工人的手环 有消息称,南京市河西区的环卫工人被要求佩戴 GPS 跟踪智能手环,这会随时监控他们的位置,而且如果他们停止移动超过20分钟,手环就会发出提醒"请继续工作"。 报道披露后,公众压力使得当地环卫公司决定稍微让步,现在如果环卫工人留在一个地方,手环不再发出提醒"请继续工作",但仍然会跟踪工人的移动。 9、787 飞机的 GPS 授时错误 GPS 卫星发送的信息包含时间字段,其中表示"周数"的字段只有10个二进制位,导致该字段每20年会发生一次溢出,自动归零。2019年4月6日,该字段就发生了本世纪第一次溢出。 所有依赖 GPS 授时的设备,都可能因此发生计时错误。波音公司的喷气式飞机就是这样,现在已经出现多架 787 客机的系统时间回到了20年前的1999年(上图红框处)。 10、一句话新闻 华纳音乐签约了一个音乐算法,将发行该算法生成的五张唱片。它主要生成轻音乐,供睡前播放,itunes 上面有试听。 IBM 公司在过去6年中,已经解雇了超过2万名40岁以上的美国员工。报道称,该公司有内部政策,更严厉地评估长期服务的员工,使用负面评估对他们进行裁员。 人的大脑保存的信息,研究认为,以英语表示的话大约是 1.5MB。 英国和加拿大决定,不再新建任何燃煤电厂,现有的燃煤电厂也将逐步放弃。因为燃煤会产生大量二氧化碳。 文章 1、刘慈欣:释放想象力(中英对照) 2018年11月,刘慈欣在克拉克想象力服务社会奖颁奖仪式上的演说。 2、Java 开发者需要知道的20个库(英文) 本文介绍 Java 语言20个常用的库,比如 log4j、JUnit、JSoup 等。 3、与死亡一线之隔的完美(中文) Free Solo 是一部《国家地理》杂志拍摄的纪录片,讲述了徒手独攀优胜美地國家公園內、全世界最難攀爬的酋长岩的故事。它得到了 2019奧斯卡最佳紀錄片獎。本文讲述了这部纪录片背后的故事,为什么有人愿意冒着生命危险去攀岩,他又是怎么爬上去的。 4、再见 Docker(英文) 作者认为,Docker 作为一家公司已经失败,作为一种技术,也即将被其他容器技术取代。 5、关于 EOF(英文) EOF 是一个很容易混淆的概念。Windows 系统的文本文件,结尾可以有 EOF 终止符;C / C++ 语言有一个表示读取终止的特殊值 EOF,还有测试读取是否终止的 eof() 和 feof() 函数。 6、使用 AV1 编解码器(英文) AV1 是一个新的开源的视频编码和解码标准,本文介绍 AV1 的基本知识,以及如何把视频压缩成 av1 格式。 7、无 JavaScript 的前端(英文) 作者呼吁 HTML 语言内置更多的功能,从而使得只用 HTML 就可以写出可交互的页面,减少 JavaScript 的使用。 8、线程的基本知识(英文) 一篇写得非常好的科普文章,通俗地详尽解释了进程和线程的相关知识。 9、如何使用 React Hooks 获取数据?(英文) 本文由浅入深一步步介绍,如何使用 React Hooks 的 useEffect 从远程服务器获取数据。 10、浏览器内置的 KV Storage(英文) 浏览器提供的键值对存储 localStorage API 是同步操作,有时候很慢。为了解决这个问题,Chrome 浏览器开始提供异步键值对存储的 API。 11、浏览器原生的图片懒加载(英文) Chrome 75 将原生支持图片的懒加载,写成 ,就可以滚动到视口加载图片。 软件 1、node-five 一个基于 QT 的 Nodejs 框架,用于开发 Node 应用的图形界面。 2、Learn anything 一个学习资源的搜索引擎,可以搜索各种主题,返回相应的教程。(@Paleless 投稿) 3、Gckit-CLI 命令行下使用一行命令,生成Swift、Objective-C等项目的模板代码。(@SeongBrave 投稿) 4、php-lisp 一个使用 PHP 写的 Lisp 代码解释器。(@wujunze 投稿) 5、Paste to Markdown 粘贴到该窗口的任何文本内容,都会自动转为 Markdown 格式。(@AidySun 投稿) 6、RCT 一个通过解析 rdb 文件对 redis 内存结构分析的一站式平台。(@TrumanDu 投稿) 7、squoosh 谷歌开源的图像压缩服务。(@ifrontend-xyz 投稿) 8、Whoer.net 查看你的 HTTP 请求携带多少个人信息的网站。(@xcuYao 投稿) 9、chunkwm Mac 电脑的多窗口平铺式管理器。 10、StreamSaver.js 流媒体保存成本地文件的浏览器库。(@ifrontend-xyz 投稿) 11、你的电脑有多快? 一个小游戏,提供一系列常见任务的 Python 脚本,让你猜计算机在1秒内可以执行多少次。(@NeoTse 投稿) 12、morec 一个 Flutter 制作的电影 App,用于学习 Flutter。(@Mayandev 投稿) 资源 1、Generative.fm 该网站专门收集软件生成的音乐。比较奇特的是,这些音乐可以无限播放,并且每次听都不一样。暂停以后重新播放,你会听到跟前面不同的音乐。 2、Star Wars Asciimation ASCII 码的形式演绎整部《星球大战》,可以使用 telnet towel.blinkenlights.nl 在命令行观看,也可以在网页观看。(@linkoln 投稿) 3、Test-Driven Web Development with Python 免费的英文电子书,介绍如何以 TDD 的方式开发互联网应用,使用 Django 框架举例。(@nosarthur 投稿) 4、算法 开源英文电子书,作者是美国伊利诺伊大学的教师,本书是他的讲课笔记,偏重于数学。(@nosarthur 投稿) 5、Killed by Google 该网站收集谷歌关闭的所有自家产品。(@murongsihua 投稿) 6、航班实时追踪 国内做的全球航班实时位置展示,国内航班的覆盖是全球最好的。(@cq0206 投稿) 文摘 1、为什么我放弃 Amazon 年薪50万美元的工作? 上周,我辞掉了8年的亚马逊工作。尽管一再得到奖励和表彰,但我没有足够的动力再干一年。 当年,加入亚马逊时,我是初级工程师。5年内,我晋升了两次,现在是高级工程师。如果我留下来,几乎可以肯定今年会再次晋升,成为首席工程师。我被告知,我在公司有很大的潜力。公司里,人们对我的尊重不断增长,我被视为所在领域的专家和领导者。 我在亚马逊的第一年赚了75,000美元。去年,我赚了511,000美元。如果再呆几年,我的年薪应该可以到100万美元。 我的工作不算很忙,也不再需要证明自己。我可以在一周40小时内完成所有工作,而且我的团队每周一天在家工作。晚上或周末,我很少打开笔记本电脑。我总共有三位主管,他们人都很好,有很多同理心。 尽管一切都很好,但每天早上,我上班的动机都在减少。 最初的几年,我主要与另一个同事,一起开发一个内部工具。各种限制很少,我有很大的独立性,直接与用户交谈,然后发布更新,开展测试等等。只要我觉得这件事是重要的,通常就可以去做。大多数时候,工作的方向是我们自己控制的。 后面的几年却完全不同。我领导着部门历史上最重要的项目,有许多利益相关者和复杂的目标。我能做的事情受到了很大的限制,通常取决于我能否说服所有相关人员,而我想做的是实现目标的最佳方式,却不一定能做。 我在公司总是处理其他人的要求或条件,开始时很简单,但随着时间的流逝而变得越来越复杂,因为必须满足所有利益相关者。这种情况迫使我做一些不愿意做的事情,或者我愿意做的事情没法做。 2、善于销售 成功需要自信,但是仅有自信是不够的,你还必须能够让别人相信你的主张。 某种程度上,所有伟大的职业都包含销售工作。您必须向客户、员工、媒体、投资者宣传你的计划。这需要鼓舞人心的愿景,强大的沟通技巧,魅力,以及执行能力的证据。 善于沟通,特别是善于书面沟通,是值得培养的一种能力。如果要达到明确沟通,我的建议是,首先要确保你的思路清晰,然后使用简洁明了的语言,表达出你的想法。 销售的最佳方式是真正相信你所销售的产品。卖你真正相信的东西感觉很棒,试图卖自己都不相信的产品,感觉很糟糕。 我的另一个销售建议是,重要的时候,你最好亲自出现。我刚开始做销售的时候,我总是愿意上飞机,自己去一趟。这通常是不必要的,打电话也可以解决。但其中有三次导致了我的职业生涯转折点,如果我不是亲自去,我的人生本来会走另一条路。 3、Youtube 的热门频道统计 Youtube 有2000多万个活跃频道,2018年底,359个频道有超过1000万个订阅者。其中,87个频道是2018年创建的,在一年内就达到了1000万订阅,相比2017年的47个频道增长了185%。 这87个频道平均需要167天才能达到1000万订户。其中,最快的是墨西哥的 Kenia OS 只用了5天,其次是另一个墨西哥频道 Juki Dog,花了20天。这87个频道的国籍分布是,14个墨西哥频道,12个美国频道,11个印度频道,5个土耳其,4个印度尼西亚频道。 娱乐类频道(电影和娱乐,音乐)是增长最快的频道,其次是生活频道和游戏频道。烹饪、健康、体育类频道也有快速增长。 根据统计,这些热门频道在周五和周六上传了更多视频,这两天发布的视频在观看和订阅方面,要比其他时间更高。 图片 1、打印 DNA 有人把 DNA 上面23亿个碱基对,用打孔机打印出来。打印了一个星期,还不到 DNA 的5%。 2、带名字的手术帽 动手术的时候,医生戴着口罩,穿着手术服和帽子,很难分清谁是谁。一位澳大利亚医生正在互联网上,发起一场运动,倡议医生在帽子上标识自己的名字。 3、各语言的域名分布 截止2019年2月,互联网上共有93,482,546个有内容的域名,其中68%是英文站点,12%是中文站点,3%是西班牙语站点。 言论 1、 随着在线服务的激增,每个用户2007年大约有25个密码,2015年增加到130个,预计到2020年将增长到207个。 -- 《密码管理器研究》 2、 每家公司都说:"我们非常重视您的隐私和安全。"请不要再说这种话了,大多数公司并不关心数据的隐私或安全,而是为了数据被盗时,他们有一个向客户解释的说辞。 -- 《别说"我们严肃对待你的隐私和安全"》 3、 最好的故事是不完美的。当一个故事有点奇怪时,它会吸引你,人们会谈论那些没有按照预期发展的事情。那些出乎意料的东西会让你念念不忘。 -- 《马尔科姆·格拉德威尔的写作课》 4、 思考某事和讲述某事是不同的事情。我们思考事物的方式很复杂,有时甚至是不连贯的,而且经常是矛盾的。但是讲述时,我们必须把某事表达得很清晰,可以在很短的时间内说得出来。 -- 《马尔科姆·格拉德威尔的写作课》 5、 过去七年,谷歌平均每周收购两家公司。 -- Patrick Pichette,谷歌前首席财务官 6、 技术正在发展一定程度的自治,它好像正在以某种方式利用人类来创造它自己。 -- Paul Kingsnorth 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月12日


OAuth 2.0 的四种方式

2019-04-09 02:47:31 阮一峰

上一篇文章介绍了 OAuth 2.0 是一种授权机制,主要用来颁发令牌(token)。本文接着介绍颁发令牌的实务操作。 下面我假定,你已经理解了 OAuth 2.0 的含义和设计思想,否则请先阅读这个系列的上一篇文章。 进入正文之前,插播一则活动消息。 本周一(4月8日)到周日(4月14日),每天晚上八点都有两小时的免费直播课,体系化介绍高级前端开发知识,网易云课堂主办。详细介绍请看本文结尾,欢迎关注。 RFC 6749 OAuth 2.0 的标准是 RFC 6749 文件。该文件先解释了 OAuth 是什么。 OAuth 引入了一个授权层,用来分离两种不同的角色:客户端和资源所有者。......资源所有者同意以后,资源服务器可以向客户端颁发令牌。客户端通过令牌,去请求数据。 这段话的意思就是,OAuth 的核心就是向第三方应用颁发令牌。然后,RFC 6749 接着写道: (由于互联网有多种场景,)本标准定义了获得令牌的四种授权方式(authorization grant )。 也就是说,OAuth 2.0 规定了四种获得令牌的流程。你可以选择最适合自己的那一种,向第三方应用颁发令牌。下面就是这四种授权方式。 授权码(authorization-code) 隐藏式(implicit) 密码式(password): 客户端凭证(client credentials) 注意,不管哪一种授权方式,第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。 第一种授权方式:授权码 授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。 这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。 第一步,A 网站提供一个链接,用户点击后就会跳转到 B 网站,授权用户数据给 A 网站使用。下面就是 A 网站跳转 B 网站的一个示意链接。 https://b.com/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read 上面 URL 中,response_type参数表示要求返回授权码(code),client_id参数让 B 知道是谁在请求,redirect_uri参数是 B 接受或拒绝请求后的跳转网址,scope参数表示要求的授权范围(这里是只读)。 第二步,用户跳转后,B 网站会要求用户登录,然后询问是否同意给予 A 网站授权。用户表示同意,这时 B 网站就会跳回redirect_uri参数指定的网址。跳转时,会传回一个授权码,就像下面这样。 https://a.com/callback?code=AUTHORIZATION_CODE 上面 URL 中,code参数就是授权码。 第三步,A 网站拿到授权码以后,就可以在后端,向 B 网站请求令牌。 https://b.com/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL 上面 URL 中,client_id参数和client_secret参数用来让 B 确认 A 的身份(client_secret参数是保密的,因此只能在后端发请求),grant_type参数的值是AUTHORIZATION_CODE,表示采用的授权方式是授权码,code参数是上一步拿到的授权码,redirect_uri参数是令牌颁发后的回调网址。 第四步,B 网站收到请求以后,就会颁发令牌。具体做法是向redirect_uri指定的网址,发送一段 JSON 数据。 { "access_token":"ACCESS_TOKEN", "token_type":"bearer", "expires_in":2592000, "refresh_token":"REFRESH_TOKEN", "scope":"read", "uid":100101, "info":{...} } 上面 JSON 数据中,access_token字段就是令牌,A 网站在后端拿到了。 第二种方式:隐藏式 有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。 第一步,A 网站提供一个链接,要求用户跳转到 B 网站,授权用户数据给 A 网站使用。 https://b.com/oauth/authorize? response_type=token& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read 上面 URL 中,response_type参数为token,表示要求直接返回令牌。 第二步,用户跳转到 B 网站,登录后同意给予 A 网站授权。这时,B 网站就会跳回redirect_uri参数指定的跳转网址,并且把令牌作为 URL 参数,传给 A 网站。 https://a.com/callback?token=ACCESS_TOKEN 上面 URL 中,token参数就是令牌。A 网站因此直接在前端拿到令牌。 这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(session)有效,浏览器关掉,令牌就失效了。 第三种方式:密码式 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"(password)。 第一步,A 网站要求用户提供 B 网站的用户名和密码。拿到以后,A 就直接向 B 请求令牌。 https://oauth.b.com/token? grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID 上面 URL 中,grant_type参数是授权方式,这里的password表示"密码式",username和password是 B 的用户名和密码。 第二步,B 网站验证身份通过后,直接给出令牌。注意,这时不需要跳转,而是把令牌放在 JSON 数据里面,作为 HTTP 回应,A 因此拿到令牌。 这种方式需要用户给出自己的用户名/密码,显然风险很大,因此只适用于其他授权方式都无法采用的情况,而且必须是用户高度信任的应用。 第四种方式:凭证式 最后一种方式是凭证式(client credentials),适用于没有前端的命令行应用,即在命令行下请求令牌。 第一步,A 应用在命令行向 B 发出请求。 https://oauth.b.com/token? grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET 上面 URL 中,grant_type参数等于client_credentials表示采用凭证式,client_id和client_secret用来让 B 确认 A 的身份。 第二步,B 网站验证通过以后,直接返回令牌。 这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。 令牌的使用 A 网站拿到令牌以后,就可以向 B 网站的 API 请求数据了。 此时,每个发到 API 的请求,都必须带有令牌。具体做法是在请求的头信息,加上一个Authorization字段,令牌就放在这个字段里面。 curl -H "Authorization: Bearer ACCESS_TOKEN" \ "https://api.b.com" 上面命令中,ACCESS_TOKEN就是拿到的令牌。 更新令牌 令牌的有效期到了,如果让用户重新走一遍上面的流程,再申请一个新的令牌,很可能体验不好,而且也没有必要。OAuth 2.0 允许用户自动更新令牌。 具体方法是,B 网站颁发令牌的时候,一次性颁发两个令牌,一个用于获取数据,另一个用于获取新的令牌(refresh token 字段)。令牌到期前,用户使用 refresh token 发一个请求,去更新令牌。 https://b.com/oauth/token? grant_type=refresh_token& client_id=CLIENT_ID& client_secret=CLIENT_SECRET& refresh_token=REFRESH_TOKEN 上面 URL 中,grant_type参数为refresh_token表示要求更新令牌,client_id参数和client_secret参数用于确认身份,refresh_token参数就是用于更新令牌的令牌。 B 网站验证通过以后,就会颁发新的令牌。 写到这里,颁发令牌的四种方式就介绍完了。下一篇文章会编写一个真实的 Demo,演示如何通过 OAuth 2.0 向 GitHub 的 API 申请令牌,然后再用令牌获取数据。 (正文完) 前端高级开发工程师免费直播课 经过多年的发展,前端工程师的地位日益提升,越来越多的人想往前端的方向发展。 但是,市场对前端工程师的要求也越来越高,深入掌握底层技术的高级前端,才能在市场上找到自己立足之地。 为了帮助大家深入了解高级前端的学习要点,本周一(4月8日)到周日(4月14日),网易云课堂推出了前端进阶免费直播课。 (更多介绍点击这里) 他们邀请了网易资深前端工程师,免费直播分享实战中的经验方法。内容涉及网易内部自定组件库工具分享,前端开发相关知识,深度剖析 JavaScript 等。 这个直播面向前端初、中级开发工程师,每天2个小时,都是一些干货分享并且不收费,建议想进阶的同学坚持学习。大家可以微信扫码,添加助教,获取听课地址。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 9日


理解 Go 语言 defer 关键字的原理

2019-04-07 15:25:00 Draveness

现在很多现代的编程语言中其实都有用于在作用域结束之后执行函数的关键字,Go 语言中的 defer 就可以用来实现这一功能,它的主要作用就是在当前函数或者方法返回之前调用一些用于收尾的函数,例如关闭文件描述符、关闭数据库连接以及解锁资源。


基于Kubernetes 构建.NET Core 的技术体系

2019-04-07 05:24:16 李强

很多公司技术支持岗位的工作,如配置域名,部署环境,修改复位配置,服务重启,扩容缩容,梳理和完善监控,根据开发的需要查找日志等工作,需要和开发进行大量的沟通,如什么是外网域名,什么是内网域名、A name、C name,防火墙规则该如何设定,操作系统等基础环境需要什么依赖。因为很多研发不了解运维的术语和知识点,导致沟通困难,效率很低。

tags: 容器和Docker


每周分享第 50 期

2019-04-05 02:57:42 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 (题图:杭州,2018) 前几天,我听一个广播节目。主持人问,现在很多人开网约车,这样能赚多少钱,能够赚到大钱吗? 这个问题很容易回答,答案就是不能。出租车司机的收入,主要由营业时间的长短决定。基本上,一天开12个小时,就是比开6个小时,收入高出一倍。每天只有24个小时,因此收入存在上限,不可能偏离平均水平很远。 出租车是"时间换收入"的典型行业,投入的时间越多,收入越高,在家休息就没收入。很多行业都属于"时间换收入",所有此类行业都赚不到大钱。因为你能用来交换的时间是有限的,而且进入中年以后,你就拿不出更多的时间来交换。开出租车赚零花钱,或者作为短期过渡,这是没问题的,但作为终身职业是很糟糕的。 我觉得,越来越多的程序员正在落入这个陷井,用编码的时间换取收入。只有不停地做项目,才能拿到钱。项目做得越多,收入越高。这个项目开发完了,公司又让他去干下一个项目。 忙了好几年,项目完成了一大堆,但是自己什么也没留下,以后的收入还要取决于从零开始的新项目。这样的话,你跟出租车司机有何两样,哪一天你不写代码了,不是照样没收入。 那些赚到大钱的人,没有一个是靠时间换取收入的。他们要么通过积累资产致富,要么购买他人的时间,为自己创造财富。你应该警惕,不要落入"时间换取收入"的陷井,不要只顾着为别人生产代码,而要注意积累自己的资产,以及适时开展属于自己的业务。 新闻 1、银行模仿科技公司 银行通常给人一种严肃保守的感觉。丹麦一家银行决定改变这种印象,向科技公司学习,让银行也变得轻松随便。它重新装修了办公楼,允许员工穿便服,还采用了开放式办公室。 2、霍金教授的纪念硬币 英国皇家造币厂为了纪念去年去世的霍金教授,推出了一枚纪念硬币,面值为50便士。这枚硬币中间有一个洞,象征霍金对黑洞的研究成果。 3、删除 Facebook WhatsApp 于2014年以193亿美元的价格,被 Facebook 收购。但是,2019年3月13日,WhatsApp的联合创始人布莱恩·阿克顿(Brian Acton,上图最右边)在斯坦福大学的一个讲座上,公开呼吁学生删除 Facebook。 他解释说,收购完全是资本的需要,他本人是无可奈何。"我有50名员工,我不得不考虑他们,以及他们从这笔交易中赚到的钱。我不得不考虑我们的投资者,我不得不考虑我的少数股权。即使我想拒绝收购,我也没有完全的影响力来否决。" 4、月球岩石 1969年到1972年,阿波罗计划的宇航员多次登录月球,一共采集了382公斤月球岩石,其中大部分都公开了,但是有三个样本一直是保密的。今年是人类登陆月球50周年,美国宇航局决定将所有样本都公开。 科学家已经决定,采用最先进的手段,彻底检查这些样本。因为月球被发现存在固态水,这些岩石中可能有氧化物,科学家想知道有无可能从月球岩石提取氧气。 5、圆周率的最新记录 3月14日是国际圆周率日,谷歌宣布,日本的谷歌员工 Emma Haruka Iwao 打破了世界记录,将圆周率计算到了31万亿位数,远远超过之前的22万亿记录。整个计算使用虚拟机,花了121天才完成。这个新的圆周率保存在硬盘上,需要 170TB 的空间。 6、VR 电影 今年的美国 SXSW 艺术节,推出了 VR 电影体验。观众一人一套设备,每套设备都有很长的电线,以便观看时可以适度的移动。这次展映了20多部 VR 电影,每部长度都在10分钟~15分钟。不同的电影有不同的观看设备,上图是坐在轮椅上观看,观众表示体验还不错。 VR 电影的优势是沉浸式体验,可以360度观看。下面的这部电影讲述第一次世界大战时,一个英国士兵的经历。他走进一所老宅,然后是战地医院,最后在战地营房里,到处是他无法寄出去的明信片。 另一部 VR 电影则是观看一对夫妻的故事。 7、苹果取消 AirPower 苹果公司宣布,取消 AirPower 这个产品,理由是无法达到该公司的产品要求。AirPower 是2017年宣布的,它是一个椭圆型的无线充电器,可以同时为三个设备进行无线充电。原定2018年上市,但被推迟了,现在终于宣布放弃。 外界猜测,真正的原因是物理学的限制,导致这个产品很难实现。主要的障碍有两个,一个是无线充电通过感应电流实现,会有一部分电量泄漏出来,AirPower 内部有多个线圈,如果同时充电,多个感应电流会互相加强,泄漏电量的强度可能会影响到心脏起博器和助听器这样的设备。另一个障碍是,无线充电的效率不是很高,多个设备同时充电,需要很大的功率,内部会有大电流,过热无法避免。 8、一句话新闻 GPS 传送的数据采用10个二进制位表示"周数",4月6日午夜这个字段将会溢出,重新归零。那些采用 GPS 授时的设备,可能将会出现时间错误。 欧洲议会通过决议,建议成员国2021年废止实行夏令时。此前,欧盟强制所有成员国实行夏令时。 法国与中国签署协议,参与2023-2024年实施的嫦娥六号探月计划,准备在嫦娥六号上搭载15千克的法方设备,包括一台照相机和一台分析仪。 抖音被美国联邦贸易委员会罚款570万美元,因为是没有经过监护人同意,就保存13岁以下儿童的信息。 文章 1、我的 Linux 桌面配置(英文) 一个高级程序员介绍他的 Linux 桌面开发环境,以及他的各种软件选择。 2、我们不再需要 Chrome(英文) Chrome 已经垄断了浏览器市场,作者论证为什么这种情况对互联网是不利的。 3、React Hooks 入门教程(英文) 一篇很好的 React Hooks 的入门介绍文章。 4、Kanban 与 Scrum 的比较(英文) Kanban 和 Scrum 都是敏捷开发的具体实现方法,本文讨论它们的异同。 5、在特斯拉工作的感受(中文) 在马斯克的影响下,特斯拉公司上下极其激进、残酷冰冷、毫无感情,你的工作不仅压力超级大,而且很有可能因为表现不好被开除。但是为什么还有员工没辞职呢? 6、LFU 算法的一种实现(英文) LFU 是常用的删除过期缓存的算法,本文介绍了它的一种代码实现。 7、重新设计 UI 基本上是浪费时间(英文) 作者认为,95%情况下,你不需要重新设计 UI。 8、中国超高压电网(英文) 中国已经建成了全国性的超高压电网,用来将西部的电力输送到东部。这是世界上前所未有的,IEEE 的这篇报道进行了长篇介绍。 9、State of CSS 2019(英文) 针对全世界开发者的 CSS 调查。(@lanlejiudunle 投稿) 10、业余无线电爱好者入门(中文) 如何在国内拥有一个个人的无线电台。 软件 1、syncthing 多台电脑之间自动同步文件夹的工具,可以在命令行作为服务运行,也提供图形界面。 2、snailjs 一个同时包括前端和后端的 Web 框架,采用 node + react,可以用作架构参考。 3、subsync 有时,srt 字幕文件跟视频不同步,该工具可以自动让其同步。它的原理是,从视频里面检测出,何时有语音,然后将字幕与其对齐。 4、Zero server 一个 JS 的后端框架,设计很有意思,每个文件(HTML / JSX / JS)自动成为可访问的路径,不需要其他任何配置。 5、pi-hole 一个基于树莓派的家用 DNS 服务器,自带屏蔽广告功能。 6、dbdiagram.io 制作数据库关系图的在线工具。(@linlicro 投稿) 6、pagedraw 一个浏览器里面的 UI 生成器,可以通过拖曳组件来设计 UI,然后自动生成 JSX 代码。 7、EditorConfig 生成编辑器配置文件,以便整个团队有同样的编辑器设置。 8、Pika 一个只能搜索 npm 上面的 ES6 模块的搜索引擎。 9、BashUpload 一个可以从命令行上传文件的网站,文件上传后可以保存七天,其间可以无限次下载。 10、dead.io 一个显示你是否还活着的 API,做法是它每隔一段时间向你发一封邮件,如果你连续多次没有回复,它就认为你已经死了。你可以通过这个 API,设置一些死了以后需要触发的动作。 11、colorise 一个为黑白照片着色的在线服务。(@bikmanwei 投稿) 12、dust3d 开源的 3D 建模软件,适用于游戏开发,3D打印等。(@huxingyi 投稿) 资源 1、React 教程 一个 React 的30天开源教程。(@CharlesCCC 投稿) 2、PC Assembly Language 介绍汇编语言的本科生入门教材,有中文译本,免费下载。 3、ARM 汇编语言简介 通过树莓派介绍 ARM 汇编语言的开源教材。 4、Visu Algo 各种算法的动态演示网站。(@wyzlove 投稿) 5、7DRL Challenge 2019 这是一个地图探险类(rogue like)游戏的比赛,全世界开发者都可以将自己的作品上传,唯一的条件是该游戏必须是在七天内开发完成。目前,已经有100多个作品,各个平台都有,其中将近一半可以在浏览器里面运行,都可以免费下载。 6、name-suggestion-index 这个项目收集各类商品的著名品牌,作为 OpenStreetMap 的自动拼写建议。比如,你在地图上要标识一家"名牌鞋专卖店",它会自动提示59个牌子的鞋子。 图片 1、建筑物的水平线和垂直线 以前的建筑物追求庞大威严,因此更看重高度和垂直感,会有很多垂直线。但是,现在的建筑物越来越多的是水平线。下图左边是以前的建筑,右边是当代建筑。 2、纯 CSS 图片 下面图片不是照片,而是纯粹用 CSS 生成的。(@beiyeqingteng 投稿) 3、佛罗里达钓鱼比赛 美国佛罗里达州每年举办出海钓鱼比赛。下图是1957年的比赛成果。 下图是80年代初的比赛成果。  最后是2007年。 可以看到,五十年间,鱼变得越来越小,种类也越来越少。 文摘 1、SQL 是最有价值的技能之一 我的职业生涯学到了很多技能,但没有比 SQL 更有用的技术技能。由于以下几个原因,SQL 对我来说是最有价值的技能。 (1)SQL 适用很多方面。 作为产品经理,你需要从数据库看数据。知道如何使用 SQL 查看原始数据,可以为你节省大量的精力,无需向其他人询问数字。 作为一名工程师,SQL 通常可以让我更快地获取我想要的信息,而不需要用 Ruby 或 Python 编写脚本。Web 应用变得缓慢时,了解所执行的 SQL 以及优化它的方法是不可或缺的。 (2)SQL 只需学习它一次,且不需要重新学习。 过去20年,SQL 并没有真正改变。当然,有一些新的改进,但是比起其他语言,它算是毫无变化。是的,每隔几年 SQL 会有一个新的标准,偶尔会出现一些新东西,但 SQL 的基础知识是非常永久的。学习 SQL 一次将允许您在职业生涯中重复使用它,而无需重新学习。 不要误会我的意思,我喜欢学习新的东西,但我宁愿学习一些真正新的东西,而不仅仅是另一种完成同样任务的方法。 (3)SQL 很酷。 熟练掌握 SQL 人并不多,大多数开发者跳过它,很少有人真正了解 SQL,所以掌握 SQL 的人可能看起来比实际更像精英。过去在一家拥有数百名工程师的公司中,我每周会收到多个同样的请求,来自从初级工程师到主要工程师各种人:"嘿,你能帮忙写一个查询吗?"因为你很擅长这样的事情,可以帮助其他人。 2、ARM 公司的蓝图 ARM 是一家芯片公司,但它自己不制造芯片,而是销售芯片的设计图纸。它是地球上最受欢迎的芯片公司,自1990年成立以来,根据它的图纸制造和销售的芯片高达1300亿片,苹果、华为、高通等巨头都购买 ARM 的设计,然后制造的每一块芯片都会向 ARM 支付版税。 2016年,孙正义的软银公司以320亿美元收购了 ARM。这是软银最大的收购,也是最昂贵的收购之一(比 ARM 的市值高出43%)。ARM 原来是一家很赚钱的公司,但是孙正义要求它将利润降至零,全力以赴扩展业务领域,争取收入的快速增长,而不是利润的增长。 收购之前的2015年,ARM 收入高达5.9亿英镑,利润5.39亿英镑。收购之后,2017年它的利润下降至3.25亿英镑,收入为13亿英镑。 ARM 重点关注的一个领域是汽车,它认为未来几年,越来越多的处理器将用于汽车。ARM 现在只占汽车芯片市场的20%份额。由于车内的电子设备越来越多,汽车制造商开始要求将多个控制电路做进一个芯片,以节省空间并消除电路的复杂性。随着自动驾驶汽车的出现,将需要更多的芯片。自动驾驶需要的计算能力是手机的10倍,这意味着每辆自动驾驶汽车,可能会让 ARM 收到十倍的特许费。ARM 预计,汽车芯片市场将变得与手机芯片市场一样大。 ARM 另一个重点领域是网络设备。ARM 认为世界将需要更多的网络设备,来有效地传送数据,并保证网络安全。ARM 在这个市场的份额从2011年的5%,已经增加到20%。 ARM 最弱的地方是服务器,这是一个几乎由英特尔垄断的市场,ARM 的份额不到1%。不过,去年11月,亚马逊宣布已经将 ARM 芯片用于服务器,开始提供云服务。主导云计算的巨型公司,希望能够有 ARM 服务器,这样就可以避免英特尔对他们索取垄断高价。 ARM 公司的一个障碍可能是开源芯片,任何企业都可以免费使用,从而放弃使用 ARM 芯片,比如 RISC-V 芯片就是开源的。 言论 1、 全周期工程师就是一个人负责完整的软件生命周期:设计,开发,测试,部署,操作和支持。 -- 《从全栈工程师到全周期工程师》 2、 只有大型工业,才会让人口大量聚集在一小块地方,愿意不干净地挤在一起生活。 -- T.E.劳伦斯《智慧七柱》 3、 磁带储存数据有一个好处,要是断了,只要把两头再连起来,依然可以读取文件,只丢了断掉的那部分。 -- 《CERN 见闻》 4、 互联网公司的时间是狗年。狗的一年,据说相当于人的七年。一家开张两年的互联网公司,就像经营了二十年的传统行业公司。 -- 某微信公号 5、 任何一种专门服务小企业的软件都很糟糕。对于大众软件来说,客户获取成本低,开发成本可以分散在数百万人身上,因此即使价格低,也有巨大的利润潜力。对于大企业软件而言,客户获取成本很高,但报酬也很高。对于小企业软件而言,客户获取成本仍然很昂贵(面对面的个人销售和售后支持),但销售价格仍然很低。 --《从零到一》 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 5日


OAuth 2.0 的一个简单解释

2019-04-04 00:18:04 阮一峰

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。 这个标准比较抽象,使用了很多术语,初学者不容易理解。其实说起来并不复杂,下面我就通过一个简单的类比,帮助大家轻松理解,OAuth 2.0 到底是什么。 一、快递员问题 我住在一个大型的居民小区。 小区有门禁系统。 进入的时候需要输入密码。 我经常网购和外卖,每天都有快递员来送货。我必须找到一个办法,让快递员通过门禁系统,进入小区。 如果我把自己的密码,告诉快递员,他就拥有了与我同样的权限,这样好像不太合适。万一我想取消他进入小区的权力,也很麻烦,我自己的密码也得跟着改了,还得通知其他的快递员。 有没有一种办法,让快递员能够自由进入小区,又不必知道小区居民的密码,而且他的唯一权限就是送货,其他需要密码的场合,他都没有权限? 二、授权机制的设计 于是,我设计了一套授权机制。 第一步,门禁系统的密码输入器下面,增加一个按钮,叫做"获取授权"。快递员需要首先按这个按钮,去申请授权。 第二步,他按下按钮以后,屋主(也就是我)的手机就会跳出对话框:有人正在要求授权。系统还会显示该快递员的姓名、工号和所属的快递公司。 我确认请求属实,就点击按钮,告诉门禁系统,我同意给予他进入小区的授权。 第三步,门禁系统得到我的确认以后,向快递员显示一个进入小区的令牌(access token)。令牌就是类似密码的一串数字,只在短期内(比如七天)有效。 第四步,快递员向门禁系统输入令牌,进入小区。 有人可能会问,为什么不是远程为快递员开门,而要为他单独生成一个令牌?这是因为快递员可能每天都会来送货,第二天他还可以复用这个令牌。另外,有的小区有多重门禁,快递员可以使用同一个令牌通过它们。 三、互联网场景 我们把上面的例子搬到互联网,就是 OAuth 的设计了。 首先,居民小区就是储存用户数据的网络服务。比如,微信储存了我的好友信息,获取这些信息,就必须经过微信的"门禁系统"。 其次,快递员(或者说快递公司)就是第三方应用,想要穿过门禁系统,进入小区。 最后,我就是用户本人,同意授权第三方应用进入小区,获取我的数据。 简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。 四、令牌与密码 令牌(token)与密码(password)的作用是一样的,都可以进入系统,但是有三点差异。 (1)令牌是短期的,到期会自动失效,用户自己无法修改。密码一般长期有效,用户不修改,就不会发生变化。 (2)令牌可以被数据所有者撤销,会立即失效。以上例而言,屋主可以随时取消快递员的令牌。密码一般不允许被他人撤销。 (3)令牌有权限范围(scope),比如只能进小区的二号门。对于网络服务来说,只读令牌就比读写令牌更安全。密码一般是完整权限。 上面这些设计,保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全。这就是 OAuth 2.0 的优点。 注意,只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。 OAuth 2.0 对于如何颁发令牌的细节,规定得非常详细。具体来说,一共分成四种授权类型(authorization grant),即四种颁发令牌的方式,适用于不同的互联网场景。下一篇文章,我就来介绍这四种类型,并给出代码实例。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年4月 4日


把运维和开发放一起就是DevOps?还差得远!

2019-03-31 08:10:45 李强

DevOps倡导“谁开发,谁运维”和开发运维一体化。那么是不是简单地把开发和运维人员放在一起就完事了呢?

tags: DevOps


浅谈 Go 语言 select 的实现原理

2019-03-30 08:22:00 Draveness

很多 C 语言或者 Unix 开发者听到 select 想到的都是系统调用,而谈到 I/O 模型时最终大都会提到基于 select、poll 和 epoll 等函数构建的 IO 多路复用模型,我们在这一节中即将介绍的 Go 语言中的 select 关键字其实就与 C 语言中的 select 有比较相似的功能。


每周分享第 49 期

2019-03-29 02:39:00 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 (题图:千岛湖,浙江,2018) 一个美国程序员分享自己的工作方法,其中有一条是 "要么不做,要做就做完"。 他的意思是,不要给自己留下做了一半的活。因为这意味着你需要再回来,继续把它做完;你会挂念这件事情,它就像一个钟摆,过一段时间就会重新出现在你的脑海,时不时烦扰着你。 你的目标应该是,当天就把这件事情做完,从此不必再去碰它,第二天继续做下一件事就行了。如果遇到一天做不完的大项目,那就把它分解成一个个小步骤,每天完成一个步骤。 我觉得他说得很好,但是这句话比较重要的,其实是前半句:有些事情不要去做。事情是做不完的,而你的时间和精力是有限的,不要只想着如何才能把事情做完,还要学会不做那些不应该做的事情。 某种程度上,不做比做完更困难。因为通常来说,做完一件事,多多少少都有一些好处,不做意味着你要放弃一些眼前的好处,这并不容易。 最糟糕的一种情况是,某个项目不值得做,但是你已经做了,为了不要浪费已经投入的成本,于是你进一步投入,在泥坑里面越陷越深。等到项目最后失败的时候,你大伤元气,一蹶不振。项目管理有一个很重要的原则,叫做"尽快失败",就是为了防止这种情况。胡适先生原来学农科,专业是果树栽培,他觉得实在没意思,大学读到一半就改学哲学,后来当上了北大校长。如果他没有放弃,想着拿完农科文凭再说,那他大概就不会有以后的成就了。总之,对于那些没希望的项目,放弃得越早越好。 新闻 1、胰岛素胶囊 糖尿病的病人需要注射胰岛素,而胰岛素只能血液给药(注射),不能通过口服,因为无法进入血液。麻省理工学院开发了一种胰岛素胶囊,可以通过口服补充胰岛素,大大方便了患者。 它的做法是,胶囊里面带有弹簧和一个可降解的小针,针头由压缩的冷冻干燥的胰岛素制成。当胶囊进入胃中,胃酸溶解了外层的糖壳,弹簧就会舒张,针头射到胃壁上,药物穿透胃壁,溶解进入血液。胃壁没有神经,因此患者感受不到疼痛。 2、气候科学家的遗言 2月中旬,美国著名气候科学家 Wallace Smith Broecker 录制了遗言。一周后,他就去世了。 遗言中,他认为由于过度排放二氧化碳,气候灾难已经无法避免,下一步人类将不得不采用一些极端的措施,比如在地球大气层中建立一个巨大的太阳光屏障,防止地球温度太高。最坏的情况下,我们需要让喷气式飞机,在地表以上约70,000英尺的大气中,释放大量二氧化硫。这跟大规模火山喷发的效果相似,1991年菲律宾的皮纳图博火山爆发,喷出的硫磺气体在整整一年的时间里,让地球冷却了一摄氏度。 3、白鲸回归海洋 上海长风海洋世界白鲸馆内的两头明星小白鲸"小白"和"小灰",2月28日进行了最后一次表演。这次表演结束后,这对白鲸姐妹将结束15年的表演生涯,重回大海怀抱。 为了帮它们找到一个合适回归的地方,团队实地考察了俄罗斯、北美洲、挪威和苏格兰等地。最终,位于冰岛南部海岸赫马岛的 Klettdvik 海湾,成为放归目的地,而它们也将成为该保护区首批住客。这个由默林娱乐集团创立的海洋生物基金会(SEA LIFE TRUST)打造的全球首个大型鲸目动物保护区,水域广达32000平方米、深达10米,非常适合鲸类生活。 为了让这趟回归之旅更加安全舒适,来自欧洲的卢森堡货运航空公司,为小白和小灰赞助了一架"私人飞机"。"私人飞机"为波音747-400ERF货机,足足有大半个足球场那么大。飞机表面还喷绘了小白小灰的可爱笑脸。 4、沃尔沃的安全措施 沃尔沃汽车宣布,从2020年开始,将提升旗下产品的安全等级。最主要的措施是,沃尔沃汽车的最高速度只能到180公里/小时,任何情况下都无法超出这个速度。另外,每辆汽车都自带数字地图,当行驶在学校、医院、行人密集的区域时,汽车行驶速度将自动放慢,无法加速。该功能被称为地理围栏。 5、AI 预测老年相貌 美国和加拿大的一组科学家开发了一个 AI 系统,可以根据照片和视频,生成该人老年时的相貌。科学家说,该系统的一个用途是寻找多年前失踪的儿童。 6、TensorFlow 的廉价硬件 TensorFlow 是谷歌的机器学习库,通常需要运行在昂贵的硬件上面。为了降低对硬件的要求,谷歌推出了 TensorFlow Lite 1.0,可以运行在嵌入式硬件上面。上图是一个 Cortex-M4 主板,可以运行简单的语音识别任务。这块主板具有 384KB RAM 和 1MB 闪存存储,售价只有15美元,功耗极低,使用一颗纽扣电池就可以运行数天。人工智能的硬件要求越来越低,以后越来越多的设备将具备"智能"。 7、隼鸟2号的难题 日本隼鸟2号(Hayabusa2)探测器,于2019年2月22日成功登陆小行星"龙宫"(Ryugu)。按照计划,它将于4月在小行星表面制造一次爆炸,然后抓取爆炸产生的地层内部碎片,2019年12月返回地球。 但是,这个计划现在遇到了一个问题。小行星"龙宫"非常小,大约是一个直径1公里的球体。这意味着,它的引力也非常小,任何速度高于每秒38厘米的物体都具备了逃逸速度,可以摆脱它的引力,飞向宇宙深处。这个速度大约就是企鹅的前进速度。那么爆炸产生的碎片会不会都脱离小行星,飞向宇宙?日本研究人员表示,他们还没有考虑这个问题,目前无法判断结果会是怎样。 8、MySpace 丢失数据 MySpace 宣布,用户在2003年~2015年上传到该网站的照片、音乐、视频,都已经丢失,无法找回。很显然,该网站没有备份。2006年,MySpace 曾经一度超过谷歌,成为美国访问量最大的网站。 这件事情的教训就是,永远不要相信,网站会永久保存你上传的数据。 9、一句话新闻 Intuit 是美国最畅销的报税软件,现在被发现,过去五年它花了1150万美元,游说政府不要减税。 美国政府正在考虑 6G 和 7G 的频谱分配,范围是 95GHz 到 3THz。作为参考,5G 的频谱范围大约 2GHz 到 60GHz。 挪威立法禁止砍伐森林,并且禁止采购任何与砍伐森林相关的产品。比如,砍伐森林改种果树,那么这些水果将无法向挪威出口。 中国已经成为全世界出国旅游人数最多的国家,尽管只有7%的中国人(9700万)有护照。 文章 1、JavaScript 模块简史(英文) 本文介绍历史上 JavaScript 各种模块方案的演变。 2、广告 ID 的现状(英文) 通常,网站用 Cookie 设置 ID,以便追踪用户。用户可以通过清除 Cookie,防止被追踪。但是手机上,App 可以通过无法重置的硬件 ID 追踪用户,比如 IMEI、网卡 MAC 地址,SIM 卡序列号等。为了解决这个问题,iPhone 和安卓都提供广告 ID 功能,既可以表示身份,又可以被用户重置。 3、SSD 硬盘是否可靠?(英文) 本文介绍了固态硬盘 SSD 的一些知识,以及与传统硬盘可靠性的对比。 4、磁力链接介绍(英文) 磁力链接是下载和共享 bittorrent 文件的一种方式,本文介绍了磁力链接的基本知识,以及与 Torrent 文件的关系。 5、单页应用的二进制打包(英文) 本文介绍了一种方法,将网站打包成一个 Go 语言的二进制程序。启动网站,就是运行这个程序。 6、抽象的成本(英文) 重复的代码通常会被抽象掉,本文讨论抽象带来的额外成本。 7、JSX 的替代方案(英文) JSX 是前端框架中书写网页代码的一种形式,本文介绍了 JSX 的替代方案,如果不用它,你有什么选择,以加深理解。 8、创建你的第一个 npm 包(英文) 入门文章,针对新手介绍如何创建一个 npm 模块。 9、App 的实验数据(英文) 很多 App 会进行 A/B 测试和新功能实验,将数据传回服务器,本文分析了 Airbnb、Pinterest 等 App 传回服务器的数据。 10、每行80个字符是很好的标准(英文) 作者谈了为什么每行80个字符的长度非常合理有用。 11、独立运行的 WebAssembly(英文) Mozilla 宣布发布独立的、跟 Web 无关的 WebAssembly 运行时,即 WASM 代码现在可以直接在各个操作系统运行。 软件 1、AssemblyScript 一个将 TypeScript 编译成 WebAssembly 的工具。 2、gitmoji-cli 在 git commit message 里面使用 emoji 的工具。(@LanjianNUll 投稿) 3、How old is it 该网站可以查询各种技术存在了多久,用来供 HR 招聘时了解,有些技术岗位要求五年经验是不现实的。 4、WorldWideWeb 世界第一个浏览器的模拟器,还原了欧洲核子研究中心发明的 WWW 服务。 5、uncss 去除样式表里面没有用到的 CSS 规则的工具。(@IceBay 投稿) 6、Bookworm 电子书阅读软件,目前只能在 Linux 系统安装。 7、EmailBin 向该网站发送 Email,你的 Email 会变成一个网页,所有人都可以访问。 8、ICONSVG 一套可以定制的 SVG 图标。 9、ayvri 根据行进路线,生成 3D 可视化的行程视频。 10、day.js 一个 2KB 的 JS 日期时间库,和 Moment.js 的 API 设计保持完全一样. 如果您曾经用过 Moment.js, 那么您已经知道如何使用 Day.js。(@xxyuk 投稿) 11、WordPress 版微信小程序 将 WordPress 应用转为微信小程序。(@Y024 投稿) 12、greendns 一个防止 DNS 污染且 CDN 友好的开源 DNS 服务端。(@faicker 投稿) 13、996.icu 一个程序员制作的抗议 996 工作制的网站。(@9527q 投稿) 资源 1、OCaml 语言在线教程 OCaml 语言教程,从最简单的讲起。 2、Qt5 教程 开源电子书,介绍如何使用 Qt5,开发图形界面。 3、Python 数据科学手册 使用 Python 工具进行数据科学研究的教程,现在全书开源了。 4、WikiHow 一个收集如何解决生活中各种问题的网站,比如"如何换轮胎"、"如何调整电脑字体大小"等等。(@xcuYao 投稿) 5、互动式计算机语言学习网站 该网站提供近10种常用语言(C、Python、JS、Java 等等)的实例教程。(@baibm 投稿) 6、计算机理论导论 哈佛大学本科生的《计算机理论》课程的教材,已经开源。 7、Japan Dev Jobs 一个分享日本技术工作机会的邮件列表,想去日本工作的开发者可关注。(@roujiangzailushang 投稿) 图片 1、密码雕塑 美国 CIA 总部内部有一件雕塑品,上面是四段加密文字。这是1989年一位雕塑家创作的。目前,其中三段已经被破解了,但是最后一段依然无法破解。 2、红衫树桩 1890年,美国加州砍伐了一棵红衫之后,人们的合影。 3、月亮照片 一位爱好者拍摄了近5万张夜空图像,然后合成了一张81万像素的月球图像。 文摘 1、为什么你应该停止阅读新闻? 今天的新闻业与以前有很大不同。 (1)新闻传播的速度大大提高。现在,新闻在发生后的几秒内,就开始传播,每个人在很短时间内,就会知道发生了什么事。 (2)新闻的产出成本大幅下降。现在,有人可以每天写12篇报道,一年就是近3000篇,这还只是一个人的产量。这么快的产出速度,几乎不可能在一个主题有一些深思熟虑的东西。由于产出成本已降至接近零,因此新闻业存在很多竞争。 (3)新闻业企图给读者洗脑。今天的新闻不再强调客观,而是充满了主观看法,企图用个性吸引读者。 (4)点击量成了主要目标。由于竞争激烈,大多数新闻媒体都不得不提供免费新闻,因此必须依靠广告产生收入。广告收入的高低直接依赖于点击量。创造很多耸人听闻的新闻,最容易获得点击。 总之,今天网上的大部分新闻都毫无意义,对你的生活并不重要,不会帮助你做出更好的决定,也不会帮助你理解世界,与周围的人建立联系。它们只会消耗你的注意力,造成你的注意力不足。你被大量信息包围,感到不知所措,为了赶上这一切,内心承受了压力。完全不看新闻,可能是更好的做法。 2、研究也是一种债务 大多数研究就像爬山一样。 有抱负的研究人员必须努力理解摆在他们面前的大量工作,学习各种技巧,攀登现有知识的顶峰。到达顶峰后,研究人员开始做新的工作,将新的石头扔到山顶上,让接下来的人可以爬得更高一点。 数学就是一个鲜明的例子。几个世纪以来,无数学者攀登了数学山脉,并在顶部铺设了新的巨石。随着时间的推移,形成了不同的山峰,建立在美丽的数学定理之上。当代数学的高峰是如此众多和陡峭,以至于任何人都无法全部攀爬它们。即使经过一生的努力,数学家也只能享受其中的一些景观。 人们期望攀登变得艰难,这反映了数学的巨大进步和数学家的努力。攀登被视为一次智力朝圣,是一种晋级的仪式。但是,攀登本身并不值得骄傲。 科学的山峰越来越高,攀登越来越难,这并不是单纯的进步,而是留给后人的一堆债务。 言论 1、 我们这个时代的痛苦在于,那些愚蠢的人都非常自信,那些有想象力和理解能力的人充满了怀疑和犹豫不决。 -- 《关于愚蠢》 2、 他拥有在一件事成为现实之前,就发现它的本事。对他显而易见的事情,其他人要等到十年之后,才觉得显而易见。 -- 《孙正义的故事》 3、 社交媒体的问题是永不结束。它只让你看最新的东西,就像在轮子上奔跑的仓鼠一样,我们生活在消耗短暂内容的无限循环中,结果我们失去了历史感。 -- 《此时此刻永无止尽》 4、 可乐不会形成味道的记忆。你可以在上午9点,上午11点,下午5点各喝一杯,而不会对它的味道厌倦,其他饮料都做不到,一段时间后你会厌倦它们。普通人每天饮用64盎司的液体,你可以将所有64盎司的液体都换成可乐。 -- 巴菲特解释他为什么投资可口可乐 5、 创业公司的一个好处是,一切都如此混乱,如果你不小心搞砸了某事,没有人会注意到。 -- HN 读者留言 订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年3月29日


解锁卡片分类全过程

2019-03-28 08:00:42 Shia

从线下执行至线上分析一站教学式搞定

tags: 读书分享,卡片分类


商业画布初体验

2019-03-27 08:46:23 李强

本期向大家介绍一个在产品设计中的重要工具——商业画布。在产品研发中,产品经理常常将精力重点放在用户体验部分,设计了貌似完美的功能和极其花哨的界面,而在产品上线后却发现用户寥寥无几。究其根源,是因为对产品的商业模式没有一个清晰的认知和规划,在设计产品时没能找到正确的途径。本文将简要介绍商业画布这一工具及其绘制思想与方法,帮助我们避免陷入产品叫好不叫座的尴尬局面。

tags: 随笔


Grid 布局教程

2019-03-25 13:07:27 阮一峰

一、概述 网格布局(Grid)是最强大的 CSS 布局方案。 它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。以前,只能通过复杂的 CSS 框架达到的效果,现在浏览器内置了。 上图这样的布局,就是 Grid 布局的拿手好戏。 Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。 Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。 二、基本概念 学习 Grid 布局之前,需要了解一些基本概念。 2.1 容器和项目 采用网格布局的区域,称为"容器"(container)。容器内部采用网格定位的子元素,称为"项目"(item)。

1

2

3

上面代码中,最外层的
元素就是容器,内层的三个
元素就是项目。 注意:项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的

元素就不是项目。Grid 布局只对项目生效。 2.2 行和列 容器里面的水平区域称为"行"(row),垂直区域称为"列"(column)。 上图中,水平的深色区域就是"行",垂直的深色区域就是"列"。 2.3 单元格 行和列的交叉区域,称为"单元格"(cell)。 正常情况下,n行和m列会产生n x m个单元格。比如,3行3列会产生9个单元格。 2.4 网格线 划分网格的线,称为"网格线"(grid line)。水平网格线划分出行,垂直网格线划分出列。 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。 上图是一个 4 x 4 的网格,共有5根水平网格线和5根垂直网格线。 三、容器属性 Grid 布局的属性分成两类。一类定义在容器上面,称为容器属性;另一类定义在项目上面,称为项目属性。这部分先介绍容器属性。 3.1 display 属性 display: grid指定一个容器采用网格布局。 div { display: grid; } 上图是display: grid的效果。 默认情况下,容器元素都是块级元素,但也可以设成行内元素。 div { display: inline-grid; } 上面代码指定div是一个行内元素,该元素内部采用网格布局。 上图是display: inline-grid的效果。 注意,设为网格布局以后,容器的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。 3.2 grid-template-columns 属性,grid-template-rows 属性 容器指定了网格布局以后,接着就要划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; } 上面代码指定了一个三行三列的网格,列宽和行高都是100px。 除了使用绝对单位,也可以使用百分比。 .container { display: grid; grid-template-columns: 33.33% 33.33% 33.33%; grid-template-rows: 33.33% 33.33% 33.33%; } (1)repeat() 有时候,重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用repeat()函数,简化重复的值。上面的代码用repeat()改写如下。 .container { display: grid; grid-template-columns: repeat(3, 33.33%); grid-template-rows: repeat(3, 33.33%); } repeat()接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值。 repeat()重复某种模式也是可以的。 grid-template-columns: repeat(2, 100px 20px 80px); 上面代码定义了6列,第一列和第四列的宽度为100px,第二列和第五列为20px,第三列和第六列为80px。 (2)auto-fill 关键字 有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。 .container { display: grid; grid-template-columns: repeat(auto-fill, 100px); } 上面代码表示每列宽度100px,然后自动填充,直到容器不能放置更多的列。 (3)fr 关键字 为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。 .container { display: grid; grid-template-columns: 1fr 1fr; } 上面代码表示两个相同宽度的列。 fr可以与绝对长度的单位结合使用,这时会非常方便。 .container { display: grid; grid-template-columns: 150px 1fr 2fr; } 上面代码表示,第一列的宽度为150像素,第二列的宽度是第三列的一半。 (4)minmax() minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。 grid-template-columns: 1fr 1fr minmax(100px, 1fr); 上面代码中,minmax(100px, 1fr)表示列宽不小于100px,不大于1fr。 (5)auto 关键字 auto关键字表示由浏览器自己决定长度。 grid-template-columns: 100px auto 100px; 上面代码中,第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width,且这个值大于最大宽度。 (6)网格线的名称 grid-template-columns属性和grid-template-rows属性里面,还可以使用方括号,指定每一根网格线的名字,方便以后的引用。 .container { display: grid; grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4]; grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4]; } 上面代码指定网格布局为3行 x 3列,因此有4根垂直网格线和4根水平网格线。方括号里面依次是这八根线的名字。 网格布局允许同一根线有多个名字,比如[fifth-line row-5]。 (7)布局实例 grid-template-columns属性对于网页布局非常有用。两栏式布局只需要一行代码。 .wrapper { display: grid; grid-template-columns: 70% 30%; } 上面代码将左边栏设为70%,右边栏设为30%。 传统的十二网格布局,写起来也很容器。 grid-template-columns: repeat(12, 1fr); 3.3 grid-row-gap 属性,grid-column-gap 属性,grid-gap 属性 grid-row-gap属性设置行与行的间隔(行间距),grid-column-gap属性设置列与列的间隔(列间距)。 .container { grid-row-gap: 20px; grid-column-gap: 20px; } 上面代码中,grid-row-gap用于设置行间距,grid-column-gap用于设置列间距。 grid-gap属性是grid-column-gap和grid-row-gap的合并简写形式,语法如下。 grid-gap: ; 因此,上面一段 CSS 代码等同于下面的代码。 .container { grid-gap: 20px 20px; } 如果grid-gap省略了第二个值,浏览器认为第二个值等于第一个值。 根据最新标准,上面三个属性名的grid-前缀已经删除,grid-column-gap和grid-row-gap写成column-gap和row-gap,grid-gap写成gap。 3.4 grid-template-areas 属性 网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-template-areas: 'a b c' 'd e f' 'g h i'; } 上面代码先划分出9个单元格,然后将其定名为a到i的九个区域,分别对应这九个单元格。 多个单元格合并成一个区域的写法如下。 grid-template-areas: 'a a a' 'b b b' 'c c c'; 上面代码将9个单元格分成a、b、c三个区域。 下面是一个布局实例。 grid-template-areas: "header header header" "main main sidebar" "footer footer footer"; 上面代码中,顶部是页眉区域header,底部是页脚区域footer,中间部分则为main和sidebar。 如果某些区域不需要利用,则使用"点"(.)表示。 grid-template-areas: 'a . c' 'd . f' 'g . i'; 上面代码中,中间一列为点,表示没有用到该单元格,或者该单元格不属于任何区域。 注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end。 比如,区域名为header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end。 3.5 grid-auto-flow 属性 划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。 这个顺序由grid-auto-flow属性决定,默认值是row,即"先行后列"。也可以将它设成column,变成"先列后行"。 grid-auto-flow: column; 上面代码设置了column以后,放置顺序就变成了下图。 grid-auto-flow属性除了设置成row和column,还可以设成row dense和column dense。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。 下面的例子让1号项目和2号项目各占据两个单元格,然后在默认的grid-auto-flow: row情况下,会产生下面这样的布局。 上图中,1号项目后面的位置是空的,这是因为3号项目默认跟着2号项目,所以会排在2号项目后面。 现在修改设置,设为row dense,表示"先行后列",并且尽可能紧密填满,尽量不出现空格。 grid-auto-flow: row dense; 上面代码的效果如下。 上图会先填满第一行,再填满第二行,所以3号项目就会紧跟在1号项目的后面。8号项目和9号项目就会排到第四行。 如果将设置改为column dense,表示"先列后行",并且尽量填满空格。 grid-auto-flow: column dense; 上面代码的效果如下。 上图会先填满第一列,再填满第2列,所以3号项目在第一列,4号项目在第二列。8号项目和9号项目被挤到了第四列。 3.6 justify-items 属性,align-items 属性,place-items 属性 justify-items属性设置单元格内容的水平位置(左中右),align-items属性设置单元格内容的垂直位置(上中下)。 .container { justify-items: start | end | center | stretch; align-items: start | end | center | stretch; } 这两个属性的写法完全相同,都可以取下面这些值。 start:对齐单元格的起始边缘。 end:对齐单元格的结束边缘。 center:单元格内部居中。 stretch:拉伸,占满单元格的整个宽度(默认值)。 .container { justify-items: start; } 上面代码表示,单元格的内容左对齐,效果如下图。 .container { align-items: start; } 上面代码表示,单元格的内容头部对齐,效果如下图。 place-items属性是align-items属性和justify-items属性的合并简写形式。 place-items: ; 下面是一个例子。 place-items: start end; 如果省略第二个值,则浏览器认为与第一个值相等。 3.7 justify-content 属性,align-content 属性,place-content 属性 justify-content属性是整个内容区域在容器里面的水平位置(左中右),align-content属性是整个内容区域的垂直位置(上中下)。 .container { justify-content: start | end | center | stretch | space-around | space-between | space-evenly; align-content: start | end | center | stretch | space-around | space-between | space-evenly; } 这两个属性的写法完全相同,都可以取下面这些值。(下面的图都以justify-content属性为例,align-content属性的图完全一样,只是将水平方向改成垂直方向。) start - 对齐容器的起始边框。 end - 对齐容器的结束边框。 center - 容器内部居中。 stretch - 项目大小没有指定时,拉伸占据整个网格容器。 space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。 space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。 space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。 place-content属性是align-content属性和justify-content属性的合并简写形式。 place-content: 下面是一个例子。 place-content: space-around space-evenly; 如果省略第二个值,浏览器就会假定第二个值等于第一个值。 3.8 grid-auto-columns 属性,grid-auto-rows 属性 有时候,一些项目的指定位置,在现有网格的外部。比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。 grid-auto-columns属性和grid-auto-rows属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns和grid-template-rows完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。 下面的例子里面,划分好的网格是3行 x 3列,但是,8号项目指定在第4行,9号项目指定在第5行。 .container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-auto-rows: 50px; } 上面代码指定新增的行高统一为50px(原始的行高为100px)。 3.9 grid-template 属性,grid 属性 grid-template属性是grid-template-columns、grid-template-rows和grid-template-areas这三个属性的合并简写形式。 grid属性是grid-template-rows、grid-template-columns、grid-template-areas、 grid-auto-rows、grid-auto-columns、grid-auto-flow这六个属性的合并简写形式。 从易读易写的角度考虑,还是建议不要合并属性,所以这里就不详细介绍这两个属性了。 四、项目属性 下面这些属性定义在项目上面。 4.1 grid-column-start 属性,grid-column-end 属性,grid-row-start 属性,grid-row-end 属性 项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。 grid-column-start属性:左边框所在的垂直网格线 grid-column-end属性:右边框所在的垂直网格线 grid-row-start属性:上边框所在的水平网格线 grid-row-end属性:下边框所在的水平网格线 .item-1 { grid-column-start: 2; grid-column-end: 4; } 上面代码指定,1号项目的左边框是第二根垂直网格线,右边框是第四根垂直网格线。 上图中,只指定了1号项目的左右边框,没有指定上下边框,所以会采用默认位置,即上边框是第一根水平网格线,下边框是第二根水平网格线。 除了1号项目以外,其他项目都没有指定位置,由浏览器自动布局,这时它们的位置由容器的grid-auto-flow属性决定,这个属性的默认值是row,因此会"先行后列"进行排列。读者可以把这个属性的值分别改成column、row dense和column dense,看看其他项目的位置发生了怎样的变化。 下面的例子是指定四个边框位置的效果。 .item-1 { grid-column-start: 1; grid-column-end: 3; grid-row-start: 2; grid-row-end: 4; } 这四个属性的值,除了指定为第几个网格线,还可以指定为网格线的名字。 .item-1 { grid-column-start: header-start; grid-column-end: header-end; } 上面代码中,左边框和右边框的位置,都指定为网格线的名字。 这四个属性的值还可以使用span关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格。 .item-1 { grid-column-start: span 2; } 上面代码表示,1号项目的左边框距离右边框跨越2个网格。 这与下面的代码效果完全一样。 .item-1 { grid-column-end: span 2; } 使用这四个属性,如果产生了项目的重叠,则使用z-index属性指定项目的重叠顺序。 4.2 grid-column 属性,grid-row 属性 grid-column属性是grid-column-start和grid-column-end的合并简写形式,grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。 .item { grid-column: / ; grid-row: / ; } 下面是一个例子。 .item-1 { grid-column: 1 / 3; grid-row: 1 / 2; } /* 等同于 */ .item-1 { grid-column-start: 1; grid-column-end: 3; grid-row-start: 1; grid-row-end: 2; } 上面代码中,项目item-1占据第一行,从第一根列线到第三根列线。 这两个属性之中,也可以使用span关键字,表示跨越多少个网格。 .item-1 { background: #b03532; grid-column: 1 / 3; grid-row: 1 / 3; } /* 等同于 */ .item-1 { background: #b03532; grid-column: 1 / span 2; grid-row: 1 / span 2; } 上面代码中,项目item-1占据的区域,包括第一行 + 第二行、第一列 + 第二列。 斜杠以及后面的部分可以省略,默认跨越一个网格。 .item-1 { grid-column: 1; grid-row: 1; } 上面代码中,项目item-1占据左上角第一个网格。 4.3 grid-area 属性 grid-area属性指定项目放在哪一个区域。 .item-1 { grid-area: e; } 上面代码中,1号项目位于e区域,效果如下图。 grid-area属性还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置。 .item { grid-area: / / / ; } 下面是一个例子。 .item-1 { grid-area: 1 / 1 / 3 / 3; } 4.4 justify-self 属性,align-self 属性,place-self 属性 justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。 align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。 .item { justify-self: start | end | center | stretch; align-self: start | end | center | stretch; } 这两个属性都可以取下面四个值。 start:对齐单元格的起始边缘。 end:对齐单元格的结束边缘。 center:单元格内部居中。 stretch:拉伸,占满单元格的整个宽度(默认值)。 下面是justify-self: start的例子。 .item-1 { justify-self: start; } place-self属性是align-self属性和justify-self属性的合并简写形式。 place-self: ; 下面是一个例子。 place-self: center center; 如果省略第二个值,place-self属性会认为这两个值相等。 五、参考链接 A Complete Guide to Grid, by Chris House Understanding the CSS Grid Layout Module, by Ian Yates How to Build an Off-Canvas Navigation With CSS Grid, Ian Yates Introduction to the CSS Grid Layout With Examples, Dogacan Bilgili Learn CSS Grid, Jonathan Suh How I stopped using Bootstrap's layout thanks to CSS Grid, Cédric Kui (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年3月25日


Go 语言 Channel 实现原理精要

2019-03-23 07:06:00 Draveness

Go 语言中的管道 Channel 是一个非常有趣的数据结构,作为语言中一种核心的数据类型,多个 Goroutine 在进行通信时就会使用 Channel 作为中间的通信方式,我们在一节中要介绍的就是 Golang 中 Channel 的实现原理。


社会经济地位(SES):一个比收入更好的用户分类指标

2019-03-22 09:56:11 CDCer

经济水平是公认重要的用户分类指标。本文探索了科研领域受到广泛认可的“社会经济地位”SES在商业上的应用。并主要以CDC与微保联合发布的《2018年互联网保险年度报告》数据证明了SES用于商业研究的价值。

tags: 未分类


每周分享第 48 期

2019-03-22 03:09:06 阮一峰

这里记录过去一周,我看到的值得分享的东西,每周五发布。 欢迎投稿,或推荐你自己的项目,请前往 GitHub 的 ruanyf/weekly 提交 issue。 上图是世界最著名的程序员之一:Bill Joy。 四十年前,他20岁出头,在加州大学柏克利分校读研究生,是 Unix 系统 BSD 版本的主要作者之一。因为找不到合适的编辑器,他用一个周末,在 ex 命令的基础上创造了 Vi 编辑器。Unix 系统的 TCP/IP 协议也是他实现的。 28岁时,他与其他人一起创建 Sun 系统公司,担任首席科学家,参与发明了 Java 语言。2003年,49岁时,他从 Sun 公司离职,改为从事风险投资。但是,他不投互联网公司,只投绿色能源,尤其是新型电池。原因是电动汽车大规模推广以后,地球上所有的锂元素制造电池都不够,必须找到新种类的电池。 我觉得,他的人生非常令人羡慕。不是因为取得的成就,而是因为每个人生阶段,他都在干不一样的事情:年轻时是程序员,中年时是科学家,老年时是新能源企业家。美国总统特朗普也是这种情况:年轻时是房地产商,中年时变成电视明星(《学徒》一口气拍了十季),老年时变成了总统。人生就好像一次旅行,不同时期能够从事不同的领域,就好像看到了不同的风景,体验了不一样的人生。 时代在变化,人生的可能性比任何时候都要多,真的没必要,一种职业干到老,多么单调的人生。实际上也不太可能,有人统计2002年的中国500大企业,三分之二以上已经消失或没落了。这么大的公司都撑不久,何况个人呢?我们在规划自己的人生时,应该有这种预见:总有一天,可能是每隔七年,我就会彻底离开现在的领域,在一个不一样的地方,干着自己感兴趣(理想的情况)或者不感兴趣(不理想的情况)的事情。 新闻 1、汽水税 2014年,美国加州伯克利市宣布开征"汽水税",希望降低人们对含糖饮料的消费,因为大量喝含糖饮料会导致肥胖和糖尿病。 四年后,有一项研究发现,2014~2017年期间,该市的汽水销售量减少了52%。2014年之前,伯克利的居民每天平均喝1.25次含糖饮料。2014年之后,每天平均喝0.5次。同一时期,周边城市的汽水消费量则没有明显变化。 2、世界最大的蜜蜂 印度尼西亚北部的一个小岛上,生活着一种世界最大的蜜蜂 Megachile pluto,比普通蜜蜂大四倍。上次人们看到这种蜜蜂,还是在1981年。 2018年3月,一只雌性的此类蜜蜂的新标本,出现在拍卖网站上,以9100美元的价格成交。几个月后,第二个标本出现,售价为4,150美元。科学家非常担忧,一方面印尼的热带雨林正在快速消失,另一方面这么高的拍卖价格,将会加速这种蜜蜂的灭亡。 2019年1月,一支由美国、澳大利亚、加拿大科学家组成的团队,前往寻找这种蜜蜂。在一个小岛上搜寻五天后,终于在离开前一天,他们发现了这种蜜蜂的活体。科学家希望印尼政府对此采取保护措施。 3、仍在使用的寻呼机 上个世纪80年代,手机普及之前,寻呼机曾被广泛使用,目前已经淘汰了。但是,医疗行业仍在使用寻呼机,单单是英国,还有13万台寻呼机在使用中。医疗行业的许多人认为,寻呼机快速可靠,尤其在紧急情况下有重要作用。 相比手机,寻呼机的优点有:(1)医院的手机信号和 Wi-Fi 信号覆盖范围不完整,往往有死角;(2)手机可能会干扰医院设备;(3)寻呼机功能单一,因此更便捷可靠。 4、ARM 芯片的 Mac 有迹象表明,苹果公司可能会在2020年,将 Mac 电脑的 CPU 芯片从 Intel 的 x86 改为 ARM 芯片,主要目的是让 iPhone、iPad 和 Mac 可以运行同一个应用程序。Mac 以前也改过 CPU 芯片,当时是从摩托罗拉的 PowerPC 芯片改成英特尔。 5、转基因蚊子 意大利的一个实验室已经培养出了转基因蚊子。这种蚊子的嘴巴类似于雄蚊子的嘴巴,所以不能咬人,因此无法传播病菌。此外,这种蚊子的生殖器官变形,这意味着它们不能产卵。这些基因改变会传给下一代,这意味着有可能让蚊子灭绝。 实验室还在评估,这种技术是否安全有效。如果确认的话,有朝一日可能会在疟疾盛行的非洲村庄,把它们释放出来,目标是最终让所有的雌蚊子都受到感染。 6、维珍银河的第一位太空乘客 2月22日,英国太空飞机公司维珍银河(Virgin Galactic),搭载了第一位太空乘客,进行了试飞。飞机飞到距离地面90公里的太空,然后安全返回。该公司计划开展太空观光,让游客在太空观看地球,并且体验失重,据称目前已经有600多人报名。 这次的乘客是一名叫做 Beth Moses 的女性,在维珍银河担任太空乘客的培训老师。与她一起上天的还有两名飞行员。下图是飞行过程的示意图。 7、机器人菩萨 2月23日,日本京都的高台寺公开展示了一个机器人菩萨 Kannon,它象征日本的怜悯之神,造价90万美元。该机器人身高1米95,会念《心经》,进行佛教布道。 该机器人内部安装了 Android 系统,它是世界上第一个受到信徒崇拜的机器人。它的左眼安装了一个摄像头,可以移动头部,手臂和躯干。 8、一句话新闻 Gali.com 这个网站每天至少有5000次访问,并且收到几百万封邮件,原因是人们把 gmail 拼错了。 最新研究发现,周末补睡也无法弥补平时缺乏睡眠对健康造成的影响。 特斯拉公司发布新的超级充电桩,充电5分钟可以行驶120公里,使得用户平均减少充电时间50%。 互联网是1989年3月12日由 Tim Berners-Lee 发明的,三十周年纪念日来临之际,谷歌发布了一个纪念 Doodle。 文章 1、异步编程是什么?(英文) 一组系列文章,从操作系统的高度,较为通俗地介绍如何认识异步编程。 2、行内 JS 脚本的堵塞效应(英文) 网页加载 JS 脚本时,允许异步加载脚本(即加上 async 属性),但是行内脚本可以堵塞异步脚本,本文介绍解决方法。 3、Unix 文本操作命令介绍(英文) Unix 命令行有许多操作文本的命令,本文逐一介绍。 4、Python 数据类型简介(英文) 初学者的基础知识文章,介绍和列举 Python 的数据类型。 5、正则表达式为什么不能解析 HTML 网页?(英文) 正则表达式最多只能解析网页的片段,而不可能写出一个基于它的 HTML 解析器。 6、Go 语言编程风格的最佳实践(英文) 作者谈了一些建议,如何编写可维护的 Go 语言代码。 7、橙色的历史(英文) 欧洲人直到16世纪才开始使用这种颜色。橙色象征着生育和富饶,上图是1895年的油画,反映了穿着橙色长袍的青年女性。 8、Beacon:暗网的搜索引擎(英文) 暗网必须在加密条件下才能访问。Beacon 是一个暗网的搜索引擎,允许在正常网络中搜索暗网的信息,该工具目前还没有正式推出,本文只是介绍。 9、网站扩展的图说教程(英文) 本片使用多张图片,通俗地解释如何拓展网站服务,承受更大的访问量。 10、Flexbox 详解(中文) 详细介绍 CSS 的 Flexbox 布局,配有大量图片说明。(@veedrin 投稿) 11、React Router 为什么发布5.0版?(英文) 如果你记不住脱字符( ^ )的作用,下面这起事故会让你记住。react-router 先发了4.4版,但是一个核心衍生库(react-router-dom)的4.3版,依赖错误地写成 "react-router": "^4.3.1" ,与4.4版不兼容导致报错。最后团队决定,撤销4.4版,改发5.0版。 工具 1、github-history 该工具提供一个用户友好的界面,查看某个文件在 GitHub 上面的编辑历史。 2、swc 一个使用 Rust 语言写的 JS 转码器,可以取代 Babel,将 ES6/TS/JSX 代码转成 ES5 代码。 3、miniC-hosting 运行在浏览器里面的 C 语言虚拟机。 4、Search Icons Visually 图标搜索引擎。你上传一个图标,它就返回一系列相似的图标。 5、gitignore.io 生成 gitignore 文件的网站。 6、DeskGap 生成跨平台(Win & Mac)桌面应用的工具,类似 Electron,但是使用了系统内置的 WebView。 7、TLDR 小程序 TLDR 项目移植到小程序,微信查看 Linux 命令。(@zqb-all 投稿) 8、WireGuard for macOS WireGuard 的 Mac 客户端。 9、Sloth Mac 系统的桌面应用,显示当前所有正在运行的进程、打开的文件和系统连接(socket),基本上就是 lsof 命令的图形界面。 10、Marp 跨平台的桌面工具,将 Markdown 文档转成幻灯片。 11、COI - Chat Over IMAP(英文) IMAP 电子邮件协议可以实时推送邮件,COI 就是基于这一点实现的一个聊天协议。通过它的客户端,可以达到聊天效果,但实际是互相发送 Email。 12、coderplanets 小众语言的社区,可以建立各种主题的子社区。CodePlantes 是开源的,服务端使用 Elixir 语言编写。(@mydearxym 投稿) 资源 1、Tracker 服务器列表 BT 下载需要有稳定的 Tracker 服务,该网站收集可用的 Tracker 服务器列表。另外还有一个 GitHub 仓库 ,也是做类似的事情。 2、Treeographer 该网站收集各种著名树木的历史。 3、Our World in Data 该网站收集一些世界性问题的数据,比如人口、健康、食物、能源等等。 4、互动式线性代数教程 基于网页的线性代数教程,有各种互动式图形。 5、Grokking Deep Learning 深度学习入门教材的在线阅读。 6、Marc Andreessen 创业文集 Marc Andreessen 是 Netscape 浏览器创始人,现在是硅谷著名的风险投资家,本书收集了他关于创业的文章。 7、中国独立 iOS 和 macOS 开发者的作品 该仓库收集个人开发者提交的作品。(@Y024 投稿) 8、GeoFS GeoFS是一个免费的在线飞行模拟器,包含全球的真实景色。你只需要一个网页浏览器就能运行它。(@JeremiahZhang 投稿) 文摘 1、微出行的意义 去年,美国开始流行共享电动滑板车和自行车。很多人把它们看作玩具或者一种时尚风潮,但是我认为,这种微出行比自动驾驶的意义更重大。 微出行比汽车出行更清洁、更安全。除了非常便宜,它们将空间和能源的使用效率提升了一个数量级,而且马上就可以部署它们,不用等待新技术普及。这些特点会改变游戏规则,汽车公司花费数十亿美元追求同样的效果,微出行轻松就达到了。 (1)清洁 交通运输占温室气体排放量的28%。微出行可以承担2英里以下的大部分出行,占城市出行的40%,不排放任何温室气体。 更重要的是,它提高了能源效率。汽车内燃机的效率仅为35%,即只有35%的能量可以用于行进,其余部分都是热能损耗。然后,35%的能量里面,只有5%用于移动乘客 - 另外95%用于移动汽车本身。因此,汽车的整体效率为0.05 * 0.35 = 1.75%。这意味着每加仑汽油,只有2盎司用于移动乘客,其余的要么在高温下丢失,要么用来移动你的车。 相比之下,电动滑板车的能源效率是85%,由于它本身重量约为30磅,所以整体能量的70%可以用于移动乘客。这比汽车提高了4000%。 (2)空间 微出行更节省空间。下图是60个人的出行方式,左边是他们全部驾驶汽车占据的空间,右边是他们步行、骑自行车、乘公共汽车占据的空间。 下图是哥本哈根的一所学校,停放汽车和停放自行车的对比。同样的空间,只能停放七八辆汽车,如果改成自行车,可以停放100多辆。 电动滑板车还允许骑车者彼此之间保持较短的安全距离。这两个因素相结合,将导致交通流量增加10倍。 (3)安全 如果城市交通40%变成自行车和电动滑板车,全世界每年可以少死几十万人。 (4)城市面貌 一座充满自行车的城市,远远比充满汽车的城市更适合居住。下图是30年前和现在的丹麦街道的对比,该国大力推广自行车取代汽车。 这些变化不仅仅对城市风貌有影响,还对当地经济产生影响:它增加了客流量和当地企业的收入。这反过来提升了社区的房地产价值。 汽车是将你隔离在车厢里,汽车行业的创新都是使得这个隔离尽可能有效:更好的噪音隔离,更好的防震动,更好的扬声器......微出行是相反的。当你骑滑板车时,你并不与周围空间隔离。驾驶汽车非常无聊,这就是为什么我们要尝试自动化驾驶。骑自行车很有趣 - 当它是电动时更是如此! 我觉得有趣的是,美国人访问欧洲后,歌颂欧洲很迷人,有热闹的街道,然后回到美国,继续建造汽车城市。 我最喜欢的例子是洛杉矶,用约翰列侬的话说,它只是一个"停车场,你可以在那里购买一个去旧金山的汉堡包。"洛杉矶的停车场面积是曼哈顿的四倍多,这个城市很像一个巨大的停车场。 一个外人来到美国城市,感觉就像一个二等公民。因为这些城市明显地是为汽车设计的,不是为行人设计的。走在城里,缺乏视觉多样性,使得行走很无聊,根本无法长时间闲逛,而且长时间在高楼的阴影里也不健康。 (5)成本 微出行的成本远远低于汽车。今天最便宜的交通选择是公共交通,但是仍然存在"最后一英里"的问题,公共汽车到不了许多地点,微出行可以弥补这个缺陷。 本周图片 1、重访 Lena 相隔46年之后,著名的 Lena 重拍了一张当年姿势的照片。那时她21岁,现在67岁。 2、太空殖民的概念图 1970年代,美国宇航局委托物理学家,绘制太空殖民的概念图,1万人左右的太空殖民点可能是什么样子。下面就是当时绘制的一些想象图。 本周金句 1、 云计算领域对于学习者几乎没有进入障碍,只需要一点天生的好奇心。所有云服务都有免费层,优秀的文档,示例项目等,Kubernetes 是免费和开源的。 技术很有趣,你边玩边学,就会得到一份工作。 -- HN 读者留言 2、 如果你每月在 AWS 花费10万美元,亚马逊会向你提供折扣。如果你一个月的花费超过100万美元,他们将不再理会你。因为他们知道你已经被锁在他们的服务里面,去不了别的地方。 -- 《Lambda 和 无服务器将锁定你》 3、 如果你跟风险投资家说,你的项目将使得他们三年内获得3倍的回报,他们可能根本不会进行投资。每年50%的回报率不值得他们花时间。 这是因为所有风投项目如果有1/3提供3倍的回报,其余的都失败了,那么这个风投基金将一无所获。 -- 《我们未能建立一个10亿美元的公司》 4、 我的80多岁的阿姨说,她没有太大困难适应新事物,但是她无法适应旧东西的消失。 -- 《纽约人》杂志 5、 目前,智能手机的平均尺寸是5.5英寸。苹果手机选择更大的屏幕,可能不是一个好主意。因为统计显示,女性拥有 iPhone 的可能性比男性高,而女性的手比男性小。 -- 英国《卫报》 欢迎订阅 这个专栏每周五发布,同步更新在我的个人网站、微信公众号和语雀。 微信搜索"阮一峰的网络日志"或者扫描二维码,即可订阅。 (完) 文档信息 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证) 发表日期: 2019年3月22日


为什么我从 Git Flow 开发模式切换到了 Trunk Based 开发模式?

2019-03-21 16:42:05 周文洋

为什么我从 Git Flow 开发模式切换到了 Trunk Based 开发模式?

tags: DevOps,Git,软件工程


深入了解Azure DevOps团队的开发部署方式

2019-03-21 04:58:24 周文洋

Azure DevOps团队如何使用 "基于主干的分支策略" 来实现Azure DevOps产品的持续快速交付

tags: DevOps,TFS,微软研发云VSTS/TFS,软件工程


写在 Istio 1.1发布时

2019-03-19 23:44:44 宋净超

下面这段是发布说明,来自 Istio 官方博客 https://istio.io/zh/blog/2019/announcing-1.1/,是我翻译的。 Istio