在上一篇《微信小程序「官方示例代碼」淺析【上】》中污淋,我們只是簡(jiǎn)單的羅列了一下代碼,這一篇寸爆,讓我們來(lái)玩點(diǎn)刺激的——就是看看IDE的代碼找田,了解它是怎么運(yùn)行的。
還好微信的開發(fā)團(tuán)隊(duì)在軟件工程的實(shí)踐還有待提高心铃,我們才有機(jī)會(huì)可以深入了解他們的代碼——真想建議他們看看Growth的第二部分樊破,構(gòu)建系統(tǒng)奔滑。
解壓應(yīng)用
首先你需要有下面的工具啦
- Mac電腦
- 微信web開發(fā)者工具.app
- WebStorm / 其他編程器 或 IDE脆炎,最好可以支持重命名
首先,我們需要右鍵微信web開發(fā)者工具.app癞松,然后顯示包的內(nèi)容枫甲,在 Contents/Resources/app.nw
下面的內(nèi)容即是我們的代碼,拷貝出來(lái)啦:
drwxr-xr-x@ 7 fdhuang staff 238B Sep 22 19:43 app
drwxr-xr-x@ 4 fdhuang staff 136B Sep 21 13:12 modified_modules
drwxr-xr-x@ 194 fdhuang staff 6.4K Sep 21 13:12 node_modules
-rw-r--r-- 1 fdhuang staff 900B Sep 22 21:09 package.json
簡(jiǎn)單的說(shuō)明一下:
- app/ 目錄下放置了app的代碼
- modified_modules/ 即一些修改后的模塊
- node_modules/ 地球人都知道
- package.json 呵呵幔崖,你一定是知道的,配置了NW相關(guān)的內(nèi)容
在modified_modules
目錄下有兩個(gè)子模塊:
- anyproxy自娩,從名字就可以看起來(lái)這是一個(gè)代理模塊
- weinre智什,遠(yuǎn)程調(diào)試工具
IDE運(yùn)行順序
我們已經(jīng)知道了這是一個(gè)NodeWebkit封裝的Web應(yīng)用了。
在package.json中的"main": "app/html/index.html",
删豺,即定義了這個(gè)APP的入口是這個(gè)index.html
蓬蝶,而不是別的文件。
很順利的我們看到了他們調(diào)用的文件了:
<script src="../dist/app.js"></script>
這里面有一個(gè)init方法定续,看來(lái)他就是NodeWebkit相關(guān)的入口了倡鲸。用WebStorm的shift + f6 RENAME 這些變量好十幾次宁炫,終于看到了下面的代碼了:
var React = require("../dist/lib/react.js");
var reactDom = require("../dist/lib/react-dom.js");
var init = require("../dist/common/loadInit/init.js");
var controller = require("../dist/components/ContainController.js");
var proxy = require("../dist/common/proxy/startProxy.js");
var windowActions = require("../dist/actions/windowActions.js");
var webViewAction = require("../dist/actions/webviewActions.js");
var webViewStore = require("../dist/stroes/webviewStores.js");
var log = require("../dist/common/log/log.js");
var shortCut = require("../dist/common/shortCut/shortCut.js");
var isDev = global.appConfig.isDev;
這是一個(gè)React應(yīng)用竿秆,還好我一年多以前學(xué)得不錯(cuò)傅是。掃視了一下代碼帽驯,終于看到了這一句:
reactDom.render(React.createElement(controller, null), document.querySelector("#container")
直接跳轉(zhuǎn)到ContainController.js,跳轉(zhuǎn)到render方法哀澈,找到了這個(gè):
React.createElement(Main, {
project: this.state.project,
appQuit: this.appQuit,
appMax: this.appMax,
appMin: this.appMin
})
果然Main里面就是大入口了
React.createElement("div", {className: "main"},
React.createElement(menuBar, {
appQuit: this.props.appQuit,
appMin: this.props.appMin,
appMax: this.props.appMax,
showSetting: this.showSetting,
project: this.props.project
}),
React.createElement(toolbar, {project: this.props.project}),
React.createElement("div", {
className: "body"
},
React.createElement(sidebar, {
project: this.props.project,
optProject: this.optProject
}),
React.createElement(develop, {
show: this.state.show,
optDebugger: this.optDebugger,
project: this.props.project
}),
React.createElement(edit, {
show: this.state.show,
project: this.props.project
}),
React.createElement(detail, {
project: this.props.project,
show: this.state.show
})),
React.createElement(toast, null),
React.createElement(setting, {
show: this.state.showSetting,
showSetting: this.showSetting
}),
React.createElement(dialog, null),
React.createElement(popup, null),
React.createElement(about, null))
}
對(duì)應(yīng)的就是下面這個(gè)界面了:
-
edit
就是編輯器及其相關(guān)的事項(xiàng) -
detail
就是項(xiàng)目的配置
WeApp是如何運(yùn)行的
慢慢的就探索到了打包,其運(yùn)行時(shí)的過(guò)程。由于我并沒有拿到內(nèi)測(cè)資格鱼鼓,所以我只好邊看邊猜測(cè)一下置媳。
在之前的文章中,我們提到了兩點(diǎn)很有意思的東西:wxml
和wxss
谒拴,這兩個(gè)文件會(huì)被分別轉(zhuǎn)換惭聂,即wxml -> html见剩,wxss -> css。對(duì)應(yīng)的有幾個(gè)不同的transform:
- transWxmlToJs
- transWxssToCss
- transConfigToPf
- transWxmlToHtml
- transManager
這里的PF指代的是PageFrame的意思没炒,pageFrame有一個(gè)對(duì)應(yīng)的模板文件:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link rel="Shortcut Icon">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0" />
<script>
var __webviewId__;
</script>
<!-- percodes -->
<!--{{WAWebview}}-->
<!--{{reportSDK}}-->
<!--{{webviewSDK}}-->
<!--{{exparser}}-->
<!--{{components_js}}-->
<!--{{virtual_dom}}-->
<!--{{components_css}}-->
<!--{{allWXML}}-->
<!--{{eruda}}-->
<!--{{style}}-->
<!--{{currentstyle}}-->
<!--{{generateFunc}}-->
</head>
<body>
<div></div>
</body>
</html>
這種風(fēng)格一看就是生成字符串Replace的,然后他們寫了一個(gè)名為wcc以及一個(gè)名為wcsc的工具。
- wcc用于轉(zhuǎn)轉(zhuǎn)wxml中的自定義tag為virtual_dom
- wcsc破停,我觀察到的現(xiàn)象是它為轉(zhuǎn)換wxss為css
這樣的話,我們就可以理解為微信小應(yīng)用有點(diǎn)類似于 Virtual Dom + WebView,畢竟上面有個(gè)WAWebView文件 ,還有一個(gè)webviewSDK文件 。
當(dāng)然無(wú)論是React + WebView币厕,或者Vue + WebView都不重要,現(xiàn)在有了 WA + WebView了腺兴,哈哈枕扫。
WeApp采用的是如下圖所示的提交方式,所以:
你在本地寫的WeApp都會(huì)被提交到微信服務(wù)器,然后打包檀夹,上傳到服務(wù)器,交給CDN——畢竟為了分發(fā)宫仗。
上傳的過(guò)程大致如下:
- APP會(huì)被打包成以日期命名 + .wx文件
- IDE會(huì)檢測(cè)包的大小办悟,并提示:代碼包大小為 xx kb酒甸,超過(guò)限制 xx kb,請(qǐng)刪除文件后重試。這個(gè)xx好像是1024蔫浆,所以APP的大小是1M。
- APP將會(huì)上傳到 https://servicewechat.com/wxa-dev/commitsource/?appid=xx&user-version=&user-desc=xx
好了俄讹,瞎扯完了延曙,睡覺準(zhǔn)備寫繼續(xù)寫新書了。