若无小程序开发经验,可先阅读 玩转微信小程序 一文。javascript
微信小程序正式上线已有几周时间,相信它的开发模式你已烂熟于胸,可能你也有所疑问,我竟能用 web 语言开发出如此流畅的几乎原生体验的应用。可能你又会猜这不就是 h5 么,厉害点的想不就是 hybrid 么。可是在咱们的开发旅途中至始至终都没有使用过 webview ,为啥呢?开发时用的 view 一类的标签,浏览器又是怎么解析成页面的呢?带着重重疑惑,进入微信小程序源码分析吧!css
这个 IDE 是如何保证咱们小程序的开发和预览的?简要分析两点。html
1. 文件目录前端
打开 微信web开发者工具目录
,进入 package.nw
,嗯?熟悉的味道来了。里面就3个文件:app
,node_modules
,package.json
。显然咱们开发时构建阶段所用资源来自于 node_modules ,因而我尝试找下 react模块
,结果没有收获...java
进入 app 目录下,呈现的四个文件夹分别是:html
,style
,images
,dist
。而你开发时使用的 IDE 的实现正是经过这些文件,不妨用浏览器打开其中一个 html 看看。node
这不就是从桌面打开后看到的效果吗(其中 nodeWebkit
提供了 web 到桌面应用的转换)。而且在 index.html
中找到咱们的主脚本文件 ../dist/app.js
,整个 IDE 从编辑,开发,预览,发布等一系列操做都在 app.js 及其引用的脚本中。react
2. 逻辑关系android
接下来开始分析下 dist
下有什么鬼。 不要怕,也就几十行的源码。webpack
不过每行都是压缩事后的而已...好吧,丢去反压缩一下。在 Sublime Text3 中装一个 jsFormat
的插件,对要格式化的代码进行 Ctrl + Alt + F 便可,接下来对咱们的文件进行一个逻辑划分。ios
显然,微信小程序 IDE 自己是用 React 组件而且以 Flux 的架构来构建的,那咱们所编写的小程序又是如何运行起来的呢?首先从 ./app/dist/components/sidebar/sidebar.js 开始看起,找到 React Render 出的 restart
按钮(编译
按钮的上方)。
// sidebar.js a.createElement('div', { className: 'sidebar-item sidebar-item-sep' }), a.createElement('div', { className: 'sidebar-item-toolbar', style: p }, a.createElement(g, null), a.createElement('div', { title: `${'darwin'===process.platform?'Command':'Ctrl'} + b`, onClick: this.handleAppRestart, className: 'sidebar-item', style: { paddingBottom: 0 } }, a.createElement('i', { className: 'sidebar-item-icon sidebar-item-icon-reset' }));
每当点击这个按钮时,IDE 都会从新展示当前 app 。因此这个 handleAppRestart
就是关键之处了。
1. 构建流程
触发 handleAppRestart 的 200ms 后会调用 ./actions/projectActions.js
中的 restart
方法,构建流程正式开始。
// sidebar.js handleAppRestart: function(l) { clearTimeout(j), j = setTimeout(() => { e.restart(this.props.project); // e为projectActions.js输出对象 let m = 'edit' === this.props.show ? `project_compile` : `project_restart`; i(m, this.props.project.appid) }, 200) }
在 projectActions.js 中,能够清楚的看到 flux 架构的部分 actions ,这些 actions
都会随着 dispatch
传入到 store
当中,进行一个状态的改变,最后从新渲染到应用中。
// projectActions.js del: function(b) { a.dispatch({ actionType: 'DELETE_PROJECT', projectid: b }) }, add: function(b, c) { a.dispatch({ actionType: 'ADD_PROJECT', project: b, needInitQuickStart: c }) }, close: function(b) { a.dispatch({ actionType: 'CLOSE_PROJECT' }) }, restart: function(b) { a.dispatch({ actionType: 'RESTART_PROJECT', project: b }) }
projectActions.js 的每个 action 都会经过 projectDispatcher.js 映射到 projectStores.js
中,应用的 restart
,add
方法在 store 中也有具体实现。
add: function(F, G) {
F.hash = a(F.projectid), F.es6 = !0, F.watcher = !0, F.editWebview = !0, F.newFeature = { time: Date.now(), show: !1, check: !1 }, F.initPath = { enable: !1 }, F.uploadPath = { enable: !1 }, w.unshift(F), c(F, G), b(), h.info(`projectStores.js add ${JSON.stringify(F)}`), this.emit('ADD_PROJECT', w) }, close: function() { this.emit('CLOSE_PROJECT') }, restart: function(F) { this.emit('RESTART_PROJECT', F) },
对于 Flux,若是还不清楚,这张图能够作个简单的诠释。nw 中用的是 facebook 官方给出的 Flux 架构,github 上比较活跃的 redux
和 mobx
都是比较好用的状态管理架构。
2. 三端运行
在未安装 android/ios sdk 时,咱们的 app 依然可以呈如今 IDE 中,此时是经过云端的 webpack 将 .wxml,.wxss,.js 转换成 nw 可解析的 html,css,js 。固然在 android/ios 的微信客户端上,依然能够访问,这即是 Write Once, run anywhere
,因此微信小程序和阿里 weex 是殊途同归的,只不过微信小程序的 API 都是基于微信的。
以 IOS 为例
微信小程序与传统 hybrid 使用 webview
不一样,后者是提供了 stringByEvaluatingJavaScriptFromString 方法让 js 能在当前 context 上执行,实质上仍是 web 应用。而前者是经过 JsBrigde 定义模块的方法映射到 OcBrigde 中,调用 native module
,其中还有不少回调,但其实质上是 native 应用。
在你工做或者实习公司的前端组,可能已经出现了 native 化这些目标,这给公司客户端人员带来了不小的危机感,的确,前端能作的事愈来愈多(依托于强大的开源社区)。
在合适的应用场景下,好比频率通常流量不大的产品上,native 化的确是很好的选择,由于对于业务复杂度高以及产品须要频繁更新迭代的公司来说能够很大的提高开发效率,一个前端工程师能完成曾经一个前端+一个android客户端+一个IOS客户端须要完成的任务,同时又能避开屡次发版的痛点,因此native 化将是前端将来几年一个必修的方向。
那它究竟带来了哪些好处,之于 web app , native app 以及 hybrid app 又有哪些优点呢?
更低的开发成本
Write Once, Run Anywhere
,只要你会 Web 技术,一样也能开发出 native 应用。这大大下降了前端开发者进入原生开发领域的门槛。
比 hybrid 更接近原生的用户体验
解决了传统 Webview
带来的性能瓶颈,由于调用的是原生的模块,而非直接执行 js 脚本。
解决 native 频繁发版问题
对于敏捷开发的团队来讲,为了能快速上线产品,一个版本的迭代周期可能几天就好了,因此发布新版本就成了一个新问题,有时新版本完成开发,而上一个版本尚未完成审核。而对于用微信小程序/ weex / React Native 开发的 app 只须要加载 jsbundle 便可,这个文件是能够随时更新,从而 app 就能够避免从新发布。