我在中秋假日的大雨里看 Coding WebIDE 的源码
节前喜闻 Coding 开源他们的 WebIDE,往大了说是业界的一大幸事,往小了说可以让我学一下项目的结构和 React 的写法。在这中秋佳节之际、上海降下暴雨之时,孤独的我孤独的学习着源码。
相关的信息和源码如下:
浅显的整体感受
- 没有测试相关代码;
- 居然没有
router
相关的代码,哭啊。我正想学习一下React router
相关代码的。不过对于 IDE 来讲,并没有 router 要切换; - 所有的样式都放在
./styles
里面,并没有和相关js/jsx
代码放在一起。也没有用CSS Modules
或者BEM
来控制 CSS 类的编写; Redux
的代码和相关js/jsx
代码放在一起了。
Packages
看了下 package.json
中的项目依赖,还是有很多陌生的包。大致过一下,不求深入理解,但求浅显印象。
Redux Thunk
我理解 Redux
其实是参照着 Vuex
来理解。Vuex
的 Mutation
对应 Redux
的 Reducer
。因为 Vuex
相比 Redux
减少了很多概念,所以这样理解 Redux
只是减少了猛然接受一个新鲜名词的 异物感
,不能从实质上帮助理解。那对 Redux
应该有一个怎样正确的初步认识,知乎上 理解 React,但不理解 Redux,该如何通俗易懂的理解 Redux? 中 @Wang Namelos 说的很棒。
回到 Redux Thunk
,官方 是这样定义 Redux Thunk 的
Thunk middleware for Redux
首先来看 middleware
,wiki 上对此的介绍与 Redux官方文档(记为:文档,下同)所述有所不同。我认为不管 middleware
究竟是什么,在Redux
中 middleware
的作用就和文档中描述的一样:
它提供的是位于
action
被发起之后,到达reducer
之前的扩展点,可以利用Redux middleware
来进行日志记录、创建崩溃报告、调用异步接口或者路由等。
简单表示就是:
action -> middleware -> reducer
文档以一个 问题: 记录日志
来帮助我们理解 Middleware
。
在 #3 时的
middlewares.forEach(middleware =>
store.dispatch = middleware(store)
)
其实是:
let store
// forEach
store.dispatch = (action) => {
// some action
store.dispatch(action)
}
// forEach
store.dispatch = (action) => {
// some action
store.dispatch(action)
}
以上的代码其实是在每个 middleware
执行时能够正确顺序替换 store.dispatch
的理想情况下。 文档是这样说的:
如果
applyMiddlewareByMonkeypatching
方法中没有在第一个middleware
执行时立即替换掉store.dispatch
,那么store.dispatch
将会一直指向原始的dispatch
方法。也就是说,第二个middleware
依旧会作用在原始的dispatch
方法
这也就引出了新问题:如何将 middlewares
串连起来。解决问题的办法本质上就是 避免出现无法立即替换
。
在 #6 的代码是这样的:
const logger = store => next => action => {
console.log('dispatching', action)
let result = next(action)
console.log('next state', store.getState())
return result
}
let dispatch = store.dispatch
middlewares.forEach(middleware =>
dispatch = middleware(store)(dispatch)
)
middleware
以方法参数的形式接收一个next()
方法,而不是通过store
的实例去获取。
关于 middleware
就先说到这里,下面接着看:为什么需要 Redux Thunk
。
官方 给出了一个在 stackoverflow 的回答:How to dispatch a Redux action with a timeout? 这个回答概括起来有以下几点:
- 简单的应用、简单问题用 React 自带的工具解决就够了。
Redux Thunk
帮你抹平同步代码与异步代码的区别。因为异步代码需要手动传入dispatch
太烦了,而且也容易出错。
答主也给了一些 Redux Async Example。在这个回答内包括其他回答,有提到 Redux Saga
和 Redux Loop
了,不过我已经不打算再深究下去了。
loadsh
A modern JavaScript utility library delivering modularity, performance, & extras.
Webpack Merge
Classnames
Classnames A simple javascript utility for conditionally joining classNames together.
小节
我想我会继续学习源码,不过就是另外的文章了吧。
另外,知乎上有关于如何写一个 Web IDE 的讨论 要实现一个 Web IDE 需要哪些前端技术?
以上。