shanggqm
shanggqm
 ## 1. 前言 2006年yahoo前端团队发布了一篇名为[《Best Practices for Speeding Up Your Web Site》](https://developer.yahoo.com/performance/rules.html)的博文,在此后的十年间,这篇文章被前端开发人士奉为Web性能优化的圣经。同年8月jQuery发布了第一个版本,支持由Google在2005年使用在google map上的Ajax技术,由此开启了前端开发的一个全新时代。 借助Ajax技术带来的革命性体验,前端第一次拥有了数据,后端大部分渲染逻辑逐渐前移到浏览器,客户端浏览器负责的工作越来越多,也因此逐渐产生了那个年代的“富客户端”开发的挑战: 1. JS体积日益庞大; 2. JavaScript语言缺陷带来的可维护性问题 3. 命名空间冲突问题 4. 性能问题 5. 等等…… 前端工程化正是在这样的背景下开始萌芽的,而在早期,前端开发者还不知道这个新鲜的词语,更多的是在按照雅虎军规做性能优化;使用[IIFE](https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)隔离作用域;使用YUI Compressor 对JS代码进行压缩和丑化;这些大多都是业务开发之外的工作,一般情况只有在生产环境出了问题或者提高了用户体验要求才会去做的事情。 2006到2010年间,随着前端开发的复杂度逐渐增长,JavaScript无Class的设计逐渐成为了JS代码难以维护的罪魁祸首,一时间提供了Class解决方案的各种JS框架和类库都出现在我们眼前: YUI.js、DOJO.js、EXT.js、MooTools、prototype。那是一个百花齐放的年代,JS社区从未如此活跃。前端产品形态也早已从静态站,简单交互的动态站转变成了复杂交互的动态站。 搜狗商业平台正是在这个时代创建的。并且从此一路走来,经过了模块化、组件化时代的洗礼,...
 题图:杜鹃湖的秋夜 | 摄影师:郭美青 2018年的React Conf上Dan Abramov正式对外介绍了`React Hook`,这是一种让函数组件支持状态和其他React特性的全新方式,并被官方解读为这是下一个5年React与时俱进的开端。从中细品,可以窥见`React Hook`的重要性。今年2月6号,React Hook新特性随React v16.8.0版本正式发布,整个上半年React社区都在积极努力地拥抱它,学习并解读它。虽然官方声明,`React Hook`还在快速的发展和更新迭代过程中,很多`Class Component`支持的特性,`React Hook`还并未支持,但这丝毫不影响社区的学习热情。 `React Hook`上手非常简单,使用起来也很容易,但相比我们已经熟悉了5年的类组件写法,`React Hook`还是有一些理念和思想上的转变。React团队也给出了使用Hook的一些[规则](https://zh-hans.reactjs.org/docs/hooks-rules.html)和[eslint插件](https://www.npmjs.com/package/eslint-plugin-react-hooks)来辅助降低违背规则的概率,但规则并不是仅仅让我们去记忆的,更重要的是要去真正理解设计这些规则的原因和背景。 本文是我个人在学习React Hook的过程中,通过学习官方文档、阅读源码、浏览其他优秀同行撰写的经验文章,再结合自己的思考,通过逆向思维从React Hook希望解决的问题出发,复盘了React Hook的核心架构设计和创造的过程。非常适合希望对React Hook有更深了解,但又不愿意去读晦涩的源码的同学。 文章中的代码很多只是伪代码,重点在解读设计思路,因此并非完整的实现。很多链表的构建和更新逻辑也一并省略了,但并不影响大家了解整个React Hook的设计。事实上`React Hook`的大部分代码都在适配`React Fiber`架构的理念,这也是源码晦涩难懂的主要原因。不过没关系,我们完全可以先屏蔽掉`React Fiber`的存在,去一点点构建纯粹的React Hook架构。 因本人能力的局限性,文中难免有解读不正确之处,盼望大家可以交流指正(笔者github博客地址:https://github.com/shanggqm/blog)。 #...
最近关于WebIDE主题的一些调研,还有结合我们团队的现状的一些思考,时间仓促,不一定全面,尤其关于大厂实践这块,基本是根据公开资料了解到的,如有描述不准确的,欢迎指正。                 ## 参考资料 - [基于云端的WebIDE架构](https://myslide.cn/slides/10779#) - [阿里云WebIDE使用指南](https://developer.aliyun.com/article/646273) - [我在阿里做中后台开发](https://www.infoq.cn/article/WHAXxBm8LrEzBUTsvb3x) - [Coding WebIDE 前端架构变迁](https://blog.coding.net/blog/the-evolution-of-coding-webide-frontend-architecture) -...
 题图 | 《蜕变》 | 19年十一作者拍摄于雨岔峡谷 2009年11月8日,在欧洲JSConf大会上,Ryan Dahl第一次正式向业界宣布了Node.js的面世,使JS语言书写后端应用程序成为了可能。在随后的几年里,Node.js受到了Javascript社区狂热地追捧,前端行业也因此进入了一个全新的工程化和全栈时代。 回顾历史,总会让人心潮澎湃。在这股浪潮中,有无数的人和项目在这座丰碑中刻下了自己的名字:React、Vue、Yeoman、RequireJS、Backbone、Antd、Webpack、Mocha、Eslint等等。在这些知名项目的熠熠光辉下,我们可能会忽略为Node.js生态的繁荣之下建立不世之功的NPM,它才是当之无愧的肱骨重臣。 NPM生于2010年1月,它从出生就背负了让Node.js社区更加繁荣的使命。NPM致力于让JS程序员能够更加方便地发布、分享Node.js类库和源码,并且简化模块的安装、更新和卸载的体验。 从今天(2019年)这个时间节点来看,NPM无论从知名度、模块数量、社区的话题数量来看,都算得上是一骑绝尘,将其他语言的模块仓库远远甩在了后面。  数据来源: [moudlecounts](http://www.modulecounts.com/) NPM的生态既已如此成熟,按说开发者对于NPM包的发布和维护应该非常熟悉才是,但事实真的是这样吗?环顾身边的FE,没有发过任何NPM包的同学大有人在,已经发过包的同学也有相当一部分并未考虑过如何才算规范地、高质量地发布一个包。 如今NPM的模块数量已上升至100W,在这样一个JavaScript组件化开发时代,除了能找到好用的组件,我们自然也需要了解如何才能成为创造这个时代的一员。而第一步就是要知道并掌握`如何规范地、负责任地发布一个NPM包?`。 这就是本文接下来的主要内容。 ## 1. 组件化思考 发布人生中第一个NPM组件虽然只是在终端命令行中潇洒地敲下`npm publish`,静等成功通知即可,但这从0到1的跨越却并非易事。这个行为的背后的始作俑者是开发者的大脑中开始萌发`组件化思维方式`。开始去思考`何为组件?`、`为什么要发布组件?`这些更深一层次的问题。 组件的存在的终极意义是为了复用,一个组件只要具备了被复用的条件,并且开始被复用,那么它的价值才开始产生。组件复用的次数越高、被传播的越广,其价值就越大。而要实现组件的价值最大化,需要考虑以下几点: 1. 我要写一个什么组件?组件提供什么样的能力? 2. 组件的适用范围是什么?某个具体业务系统内还是整个团队、公司或者社区? 3. 组件的生产过程是否规范、健壮和值得信赖? 4....
## 问题描述 我们有一个遗留系统,其中所有模块全部按照非strict模式,使用ES5语法书写。现在系统中新增一个全新的模块,我们希望能在这个新模块中引入ES2015语法来书写代码,因此引入了babel编译器来实现ES2015-> ES5的翻译,babel的版本是6.*。 在一次测试的时候我们发现Firefox的控制台报了这样一个错误: ``` TypeError: access to strict mode caller function is censored ``` 字面意思就是在[严格模式(strict mode)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)下使用了caller,这个不符合strict mode的要求,所以报错。 实际上,我们在书写ES2015模块时的确显式地在模块开始的第一行声明了: ``` 'use strict'; ``` 这些ES2015的模块里引用了一个遗留模块Ajax模块,这个模块里使用了caller这种写法,因此报错。 ## 问题定位 本以为是新增的ES2015模块声明的use strict的问题,直接删掉就可以解决问题,结果发现删掉后问题依旧,因此怀疑是否是Babel在转换时动了手脚。 因为项目中使用了Webpack来做构建,引入了babel-loader来做转换,所以通过看构建后的源码发现,虽然刚才手动删掉了自己写的'use...
近几年的前端领域,最感慨的莫过于【变化太快】。各种思想、框架、类库层出不穷,同一个需求点,通常会有多种实现方案,架构选型工作的难度与日俱增。面对每天都在产生的前端领域新词汇,不免感到心累,也难免产生廉颇老矣,尚能饭否的危机感。 无论如何,架构选型和升级的工作仍然要做,在这样的趋势和潮流下,要想对每一种流行概念都了如指掌成本很高,也没有这个必要。反倒是理清前端开发背后的需求至关重要,只要明白了前端开发需求的本质,也就很容易把散落在开源社区里的各种珍珠捡起来,串起来了。 # 关注点 在若干年前,大部分的web系统架构都是多页面架构,用户点击链接就会完全重新加载页面,这种架构如今在大部分场景中已经过时,所以这篇文章只针对SPA架构的应用。 接下来我会以对一个复杂Web前端系统的架构为例,分析一下都需要关注那些点,每个点上都有哪些考虑。 ## URL 一个web系统最终都是要通过URL来访问的,在SPA架构下,URL指代的是页面的状态,通过URL的变化来路由到另一种状态。(数据接口URL会在Server API部分介绍)因此,需要关注的点有: - URL的结构设计成什么样? - URL的结构设计的粒度到什么程度? - 如何监听URL的变化并触发不同状态的呈现? - 使用哪种history? - browserHistory / hashHistory / memoryHistory / …… - URL切换前后是否需要执行相关逻辑? - 哪些组件可以触发URL的变化?应该如何规范导致这一行为的写法?...
 ## 源码分析 在阅读一个库的源码之前,搞清楚这个库的存在是为了解决了什么问题至关重要。 [reselect](https://github.com/reactjs/reselect)的设计初衷是为了解决react-redux架构中,在把全局store里的state树的部分状态映射到对应组件的props中(mapStateToProps),每次组件更新的时候都需要执行计算的问题。即便组件依赖的状态并未发生改变。 因此可以知道,reselect提供的createSelector方法主要就是替代mapStateToProps函数的,并提了供缓存和比较机制,来减少组件更新时的无谓计算,从而提高性能。 实际使用示例如下: ```javascript import { createSelector } from 'reselect' import { connect } from 'react-redux' import { toggleTodo } from '../actions' import TodoList from '../components/TodoList'...