1. 程式人生 > >微信小程式開發三宗罪和解決方案

微信小程式開發三宗罪和解決方案

在這裡插入圖片描述 米鼠資訊:在微信公佈小程式的文件和開發工具後,我們在第一時間進行了學習和體驗,發現微信小程式的技術架構和開發體驗讓我們有些失望。由於微信小程式的執行環境並不是一個標準的瀏覽器環境,而且微信的封裝工作並不完善,所以我們以往開發中的很多經驗並不適用。這並非簡單的開發習慣不適應,更重要的是我們的開發流程、規範將不適用。

微信小程式開發第一宗罪: 無法呼叫NPM包

雖然微信小程式開發工具打包時實現了require函式載入依賴,但並不是完整的CommonJS依賴管理。因為require函式僅僅能夠載入專案中的JS檔案,而且必須嚴格定義JS檔案路徑,路徑不支援CommonJS的路徑風格。例如如下載入方式都將出錯:

require(‘lodash’);require(‘lodash/map’);require(’./foo’);

在微信小程式開發工具中,我們必須對應寫為如下格式:

require(‘node_modules/lodash/lodash.js’);require(‘node_modules/lodash/map.js’);require(’./foo.js’);

雖然我們可以像上面程式碼一樣載入node_modules目錄中的庫,但是實際執行時卻發生了:

在這裡插入圖片描述

在除錯工具的Network選項卡中,我們看到執行時載入了1000多個檔案,總資料量1.8MB,而我們僅僅是在程式碼中載入了一個lodash庫而已!這是因為微信小程式開發工具會將所有專案下的js檔案視為專案檔案,並進行打包。而實際開發中,我們需要安裝很多的NPM擴充套件庫,而這些擴充套件庫中有大量的不需要打包的檔案,例如lodash中有上千檔案,而我們只需要用到其中的非常少的一部分。

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

所以不支援NPM包的原因,是微信開發者工具不支援CommonJS標準,不支援CommonJS標準的原因,是微信開發者工具想當然地認為專案目錄下的js檔案一定是專案檔案,所以只實現了簡單的require函式,想當然的原因是。。。

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

無法使用Babel轉碼的原因其實仍然歸結於無法載入NPM庫。但是後果將十分嚴重。因為你將不能再安全使用ES6/7特性,你將無法使用async/await函式,你將和無盡的callback做鬥爭,你該怎樣描述自己?回撥地獄中的苦逼程式設計師?

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

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

**其實微信小程式開發是並非完全不能重用元件,比如WXML語法中支援import和 include。但是那僅僅是檢視模板可重用,並非元件可重用,因為我們認為元件在應當包含檢視和邏輯。

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

例如,你的小程式是個電商APP,專案中有兩個頁面中同時包含了商品列表元件,比如某分類下商品列表和搜尋結果列表,我們知道這兩個列表其實僅僅是引數不同而已。但是在小程式開發中,你只能將列表的模板抽象出來,不能將邏輯抽象出來,所以你就需要在兩個頁面上都實現一遍列表元件的控制邏輯,比如重新整理、載入更多。。。

我們的實踐

只吐槽、管殺不管埋是不道德的,既然發現了微信小程式開發中的各種弊端,我們在開發之中總結出了一套流程和工具,專為解決上述三個問題,並免費釋出到了開源社群,這就是Labrador。接下來我們一起來嘗試一下我們的開發體驗。

安裝Labrador

通過命令 npm install -g labrador-cli

全域性安裝Labrador控制行工具。

初始化專案

通過如下命令新建一個Labrador專案:

mkdir democd demonpm initlabrador init

專案初始化完成後,該目錄是這個樣子的:

在這裡插入圖片描述

圖中的src是我們的原始碼目錄,node_modules是NPM包目錄,dist是目標輸出目錄。請在開發者工具中新建一個專案,並設定路徑到dist目錄,請勿設定為demo目錄!使用WebStorm或Sublime開啟demo目錄,開發過程中,我們使用WebStorm或Sublime修改src目錄下的原始碼,請勿直接修改dist目錄中的檔案,因為dist目錄是通過labrador命令生成的。

在demo目錄中執行 labrador build

命令編譯專案,該命令會將src目錄下的檔案一一處理並生成dist目錄下對應的檔案。我們也可以執行 labrador watch 命令監控src目錄下的檔案變化,這樣就不用每次修改後手動執行編譯命令。

載入NPM包

我們以lodash包為例,在src/app.js中鍵入程式碼 const _ = require(‘lodash’);

編譯後,我們看到dist目錄下的檔案是這樣的:[圖片上傳中。。。(3)]

我們看到dist目錄下有一個npm/lodash目錄,該目錄下只有一個lodash.js檔案,那麼在微信web開發者工具中打包預覽,lodash的庫將只有這個檔案被載入。

這一切是怎麼發生的?

我們看一下dist/app.js的原始碼,發現原始碼中const _ = require(‘lodash’);

被編譯為 var _ = require(’./npm/lodash/lodash.js’);

然後labrador命令將node_modules/lodash/lodash.js

檔案複製到了 dist/npm/lodash/lodash.js

。這就是通過labrador可以呼叫NPM包的原理。

重要的是,只有真正用到的js檔案才被labrador命令加入到專案目錄中。這樣一個小小的改進象徵著我們的小程式可以便捷呼叫NPM倉庫中海量的擴充套件庫!

Babel轉碼

在初始化的示例程式碼src/app.js中的內容是這樣的:

[圖片上傳中。。。(4)]

圖中timer和getUserInfo屬性都為async函式,函式體內使用await呼叫非同步操作。labrador 庫對微信API進行了封裝,使用 const wx = require(‘labrador’); 覆蓋預設的全域性變數wx; 封裝後的wx物件提供的非同步方法返回的都是Promise非同步物件,結合async/await函式徹底終結callback,將非同步程式碼同步寫,輕鬆逃離回撥地獄!

但目前async/await函式是不被瀏覽器支援的,我們需要使用babel對其轉碼,labrador編譯命令已經內建了babel轉碼,轉碼後的程式碼可以檢視dist/app.js,內容過長,不再張貼。

重用元件

重用元件最需要解決的問題是元件的邏輯程式碼怎樣重用。在例項程式碼中有一個src/components目錄,用來存放專案內的可重用元件,其結構是這樣的:[圖片上傳中。。。(5)]

子目錄src/components/list中存放著一個可重用的元件。list.js / list.less / list.xml 分別對應微信小程式的 js / wxss / wxml 檔案。JS為控制元件的邏輯層,其程式碼如下:[圖片上傳中。。。(6)]

檔案匯出一個List類,這個元件類擁有像Page一樣的生命週期函式onLoad, onReady, onShow, onHide, onUnload 以及setData函式。LESS檔案對應微信的WXSS檔案,因為微信小程式實現的限制,LESS中無法使用連級選擇語法,但是可以定義變數,方便開發。XML檔案對應微信的WXML檔案,是元件檢視描述檔案,list.xml內容為:[圖片上傳中。。。(7)] 檔案中匯出一個名為list的template。元件不但可以存放在src/components目錄內,還可以單獨做成NPM包,這樣就可以輕鬆做到跨專案間的元件共享。

元件定義完成後,接下來是在頁面中呼叫,在 src/pages/index/index.js 中有如下程式碼:[圖片上傳中。。。(8)] 程式碼中首先引入了labrador庫替換全域性的預設wx物件,並使用labrador.createPage方法代替全域性的Page函式宣告頁面。然後載入List元件類,在頁面宣告配置中,增加了components屬性,並將List元件類例項化傳入。labrador.createPage方法是對Page方法的一層封裝,目的是在頁面初始化時和元件物件進行關聯。

在 src/pages/index/index.less 中加入程式碼@import ‘list’ 即可呼叫list元件的樣式,如果在src/components/list中找不到list.less,那麼編譯命令將在NPM包中尋找 node_modules/list/index.less 。

在 src/pages/index/index.xml 中加入程式碼 即可呼叫list元件的模板檔案,component 是Labrador自定義的元件,編譯後對應生成 import 和 template。如果在src/components/list中找不到list.xml,那麼編譯命令將在NPM包中尋找 node_modules/list/index.xml