服務項目
品牌網站建設

數字營銷

係統平台開發

數字產品

安全運維

Menu
官网开云
官网开云
梁興臣:微信小程序開發三宗罪和解決方案
時間:2016-10-15 22:33:00

在微信公布小程序的文檔和開發工具後,脈衝(chong) 軟件在第一時間進行了學習(xi) 和體(ti) 驗,我們(men) 發現微信小程序的技術架構和開發體(ti) 驗讓我們(men) 非常失望。

由於(yu) 微信小程序的運行環境並不是一個(ge) 標準的瀏覽器環境,而且微信的封裝工作並不完善,所以我們(men) 以往開發中的很多經驗並不適用。

這並非簡單的開發習(xi) 慣不適應,更重要的是我們(men) 的開發流程、規範將不適用。

微信小程序開發第一宗罪: 無法調用NPM包

雖然微信小程序開發工具打包時實現了require函數加載依賴,但並不是完整的CommonJS依賴管理。因為(wei) require函數僅(jin) 僅(jin) 能夠加載項目中的JS文件,而且必須嚴(yan) 格定義(yi) JS文件路徑,路徑不支持CommonJS的路徑風格。例如如下加載方式都將出錯:

require('lodash');

require('lodash/map');

require('./foo');

微信小程序開發工具中,我們(men) 必須對應寫(xie) 為(wei) 如下格式:

require('node_modules/lodash/lodash.js');

require('node_modules/lodash/map.js');

require('./foo.js');

雖然我們(men) 可以像上麵代碼一樣加載node_modules目錄中的庫,但是實際運行時卻發生了:

在調試工具的Network選項卡中,我們(men) 看到運行時加載了1000多個(ge) 文件,總數據量1.8MB,而我們(men) 僅(jin) 僅(jin) 是在代碼中加載了一個(ge) lodash庫而已!這是因為(wei) 微信小程序開發工具會(hui) 將所有項目下的js文件視為(wei) 項目文件,並進行打包。而實際開發中,我們(men) 需要安裝很多的NPM擴展庫,而這些擴展庫中有大量的不需要打包的文件,例如lodash中有上千文件,而我們(men) 隻需要用到其中的非常少的一部分。

另外,在開發中,我們(men) 往往需要安裝babal、eslient、webpack、grunt等待開發工具,微信小程序開發工具會(hui) 一視同仁將這些工具的源碼也進行打包......實測開發者工具將崩潰!開發者將崩潰!我崩潰!

所以不支持NPM包的原因,是微信開發者工具不支持CommonJS標準,不支持CommonJS標準的原因,是微信開發者工具想當然地認為(wei) 項目目錄下的js文件一定是項目文件,所以隻實現了簡單的require函數,想當然的原因是。。。

微信小程序開發第二宗罪: 無法使用Babel轉碼

無法使用Babel轉碼的原因其實仍然歸結於(yu) 無法加載NPM庫。但是後果將十分嚴(yan) 重。因為(wei) 你將不能再安全使用ES6/7特性,你將無法使用async/await函數,你將和無盡的callback做鬥爭(zheng) ,你該怎樣描述自己?回調地獄中的苦逼程序員?

如果你看到這裏不明白Babel為(wei) 何物,那麽(me) 祝賀你,因為(wei) 不曾見過天堂就不知何為(wei) 地獄,你無須為(wei) 不支持ES6/7而煩惱。但一旦你的大腦支持了ES6/7,用過了Babel,你就回不去了,像我一樣,無Babel不編碼。

微信小程序開發第三宗罪: 無法重用組件

其實微信小程序開發是並非完全不能重用組件,比如WXML語法中支持import和 include。但是那僅(jin) 僅(jin) 是視圖模板可重用,並非組件可重用,因為(wei) 我們(men) 認為(wei) 組件在應當包含視圖和邏輯。

WXML其實是基於(yu) 可重用的組件,但是不允許我們(men) 自定義(yi) 組件。如果你有React經驗,你就會(hui) 明白我的意思。

例如,你的小程序是個(ge) 電商APP,項目中有兩(liang) 個(ge) 頁麵中同時包含了商品列表組件,比如某分類下商品列表和搜索結果列表,我們(men) 知道這兩(liang) 個(ge) 列表其實僅(jin) 僅(jin) 是參數不同而已。但是在小程序開發中,你隻能將列表的模板抽象出來,不能將邏輯抽象出來,所以你就需要在兩(liang) 個(ge) 頁麵上都實現一遍列表組件的控製邏輯,比如刷新、加載更多。。。

我們的實踐

隻吐槽、管殺不管埋是不道德的,既然發現了微信小程序開發中的各種弊端,我們(men) 脈衝(chong) 軟件在開發之中總結出了一套流程和工具,專(zhuan) 為(wei) 解決(jue) 上述三個(ge) 問題,並免費發布到了開源社區,這就是Labrador。接下來我們(men) 一起來嚐試一下我們(men) 脈衝(chong) 軟件的開發體(ti) 驗。

安裝Labrador

通過命令 npm install -g labrador-cli 全局安裝Labrador控製行工具。

初始化項目

通過如下命令新建一個(ge) Labrador項目:

mkdir demo

cd demo

npm init

labrador init

項目初始化完成後,該目錄是這個(ge) 樣子的:

圖中的src是我們(men) 的源碼目錄,node_modules是NPM包目錄,dist是目標輸出目錄。請在開發者工具中新建一個(ge) 項目,並設置路徑到dist目錄,請勿設置為(wei) demo目錄!使用WebStorm或Sublime打開demo目錄,開發過程中,我們(men) 使用WebStorm或Sublime修改src目錄下的源碼,請勿直接修改dist目錄中的文件,因為(wei) dist目錄是通過labrador命令生成的。

在demo目錄中運行 labrador build 命令編譯項目,該命令會(hui) 將src目錄下的文件一一處理並生成dist目錄下對應的文件。我們(men) 也可以運行 labrador watch 命令監控src目錄下的文件變化,這樣就不用每次修改後手動運行編譯命令。

加載NPM包

我們(men) 以lodash包為(wei) 例,在src/app.js中鍵入代碼 const _ = require('lodash'); 編譯後,我們(men) 看到dist目錄下的文件是這樣的:

我們(men) 看到dist目錄下有一個(ge) npm/lodash目錄,該目錄下隻有一個(ge) lodash.js文件,那麽(me) 在微信web開發者工具中打包預覽,lodash的庫將隻有這個(ge) 文件被加載。

這一切是怎麽(me) 發生的?

我們(men) 看一下dist/app.js的源碼,發現源碼中const _ = require('lodash'); 被編譯為(wei)  var _ = require('./npm/lodash/lodash.js'); 然後labrador命令將node_modules/lodash/lodash.js 文件複製到了dist/npm/lodash/lodash.js 。這就是通過labrador可以調用NPM包的原理。

重要的是,隻有真正用到的js文件才被labrador命令加入到項目目錄中。這樣一個(ge) 小小的改進象征著我們(men) 的小程序可以便捷調用NPM倉(cang) 庫中海量的擴展庫!

Babel轉碼

在初始化的示例代碼src/app.js中的內(nei) 容是這樣的:

圖中timer和getUserInfo屬性都為(wei) async函數,函數體(ti) 內(nei) 使用await調用異步操作。labrador 庫對微信API進行了封裝,使用 const wx = require('labrador'); 覆蓋默認的全局變量wx; 封裝後的wx對象提供的異步方法返回的都是Promise異步對象,結合async/await函數徹底終結callback,將異步代碼同步寫(xie) ,輕鬆逃離回調地獄!

但目前async/await函數是不被瀏覽器支持的,我們(men) 需要使用babel對其轉碼,labrador編譯命令已經內(nei) 置了babel轉碼,轉碼後的代碼可以查看dist/app.js,內(nei) 容過長,不再張貼。

重用組件

重用組件最需要解決(jue) 的問題是組件的邏輯代碼怎樣重用。在實例代碼中有一個(ge) src/components目錄,用來存放項目內(nei) 的可重用組件,其結構是這樣的:

子目錄src/components/list中存放著一個(ge) 可重用的組件。list.js / list.less / list.xml 分別對應微信小程序的 js / wxss / wxml 文件。JS為(wei) 控件的邏輯層,其代碼如下:

文件導出一個(ge) List類,這個(ge) 組件類擁有像Page一樣的生命周期函數onLoad, onReady, onShow, onHide, onUnload 以及setData函數。

LESS文件對應微信的WXSS文件,因為(wei) 微信小程序實現的限製,LESS中無法使用連級選擇語法,但是可以定義(yi) 變量,方便開發。

XML文件對應微信的WXML文件,是組件視圖描述文件,list.xml內(nei) 容為(wei) :

文件中導出一個(ge) 名為(wei) list的template。
組件不但可以存放在src/components目錄內(nei) ,還可以單獨做成NPM包,這樣就可以輕鬆做到跨項目間的組件共享。

組件定義(yi) 完成後,接下來是在頁麵中調用,在 src/pages/index/index.js 中有如下代碼:

代碼中首先引入了labrador庫替換全局的默認wx對象,並使用labrador.createPage方法代替全局的Page函數聲明頁麵。然後加載List組件類,在頁麵聲明配置中,增加了components屬性,並將List組件類實例化傳(chuan) 入。labrador.createPage方法是對Page方法的一層封裝,目的是在頁麵初始化時和組件對象進行關(guan) 聯。

在 src/pages/index/index.less 中加入代碼 @import 'list' 即可調用list組件的樣式,如果在src/components/list中找不到list.less,那麽(me) 編譯命令將在NPM包中尋找 node_modules/list/index.less 。

在 src/pages/index/index.xml 中加入代碼 <component key="list"/> 即可調用list組件的模板文件,component 是Labrador自定義(yi) 的組件,編譯後對應生成 import 和 template。如果在src/components/list中找不到list.xml,那麽(me) 編譯命令將在NPM包中尋找 node_modules/list/index.xml

Kaiyun体育官方全站入口服務SERVICE
谘詢
微信掃碼谘詢
電話谘詢
400-888-9358