vue與uniapp複用代碼方案及實施步驟

現狀及問題

項目組前端比較少,爲了快速開發,使用的是uniapp來發布多端項目,uniapp目前沒法整合web,因此web端使用的是付費的iview-pro組件庫來實現。前端

由於項目需求變更比較快,爲了不一套邏輯實現屢次,使用的是嵌入的方式來複用web和uniapp相同的功能。vue

這會有以下幾個問題:node

  • web端的SPA在初次加載時很慢,白頁時間很長,用戶體驗不佳
  • 經過自適應的方式適配手機和PC端,前端開發須要考慮兩端,工做量較大,部分狀況下,調整的難度可能並不比寫兩套頁面簡單。最終適配效果也不必定理想
  • 嵌入頁面與父頁面的交互複雜,須要使用各類通訊機制來處理通訊,對前端要求較高,且不易於測試。流程上須要考慮多端,增長思考負擔
  • webview緩存問題,加載的頁面可能會有緩存,致使不手動刷新沒法清除緩存(部分狀況即便刷新也沒法清除緩存)

同時還有項目混亂的問題:webpack

  • uniapp和web端項目結構不統一
  • 功能相同的組件有多套
  • uniapp沒法自動發佈,須要基於HBuilderX打包後才能發佈

目標

鑑於上面的問題,考慮在不增長前端開發負擔的狀況下,解決這些問題,指望:git

  • 一套代碼在web和uniapp中公用,避免相同的功能在web和uniapp重複實現
  • 只須要考慮單端流程,不須要考慮多端流程,下降前端思考負擔(目前使用的嵌入方式是須要考慮多端流程和問題的,無形中增長了前端的思考負擔)
  • 統一web和uniapp的項目結構和語法,目前web使用npm-cli來管理,uniapp使用的hbuilder來建立的
  • 統一部署方式(目前uniapp須要前端打包)
  • 肯定前端代碼規範(目前前端代碼較亂,發送請求的方式就有好幾種!)
  • 提供統一的用戶體驗(uniapp提供類原生體驗,web提供網頁體驗),儘可能避免嵌入致使的白頁問題

思路

首先,uni-app在發佈到H5時支持全部vue的語法發佈到App和小程序時,因爲平臺限制,沒法實現所有vue語法。github

具體差別詳見:uniapp.dcloud.io/useweb

上文列出的差別數量有限,也就是說,只要避免了這些差別,就能保證uniapp和web代碼的基本語法一致性,注意這裏是基本語法vue-cli

其次,uniapp是支持vue-cli以及npm包依賴的。也就是說,uniapp和web能夠共用倉庫,這就解決了共用代碼的管理問題。相似Java,將共用代碼打包發佈到倉庫,uniapp和web分別引用的方式來使用。npm

具體見:json

uniapp.dcloud.io/quickstart?…

uniapp.dcloud.io/frame?id=np…

不過考慮到前期代碼改動會比較頻繁,以這種方式處理仍是比較麻煩(須要修改、打包、發佈、改版本號在install)。因此直接基於git的subtree來實現代碼層面的共享(修改、提交、拉取),待代碼穩定後,再進行庫的管理。

最後,就是組件庫問題。web目前使用的是iViewAdminUI,uniapp使用的是原生UI。

uniapp原生UI見:uniapp.dcloud.io/component/R…

二者差別:ask.dcloud.net.cn/article/354…

二者的差別見上文,主要體如今:

  • 兼容性:iView組件是針對瀏覽器的,裏面有大量dom和window對象操做。但小程序和App是沒有dom這些api的,因此沒法跨端使用。即沒法在uniapp裏使用iView
  • 性能:vue組件性能好於小程序自定義組件,即uniapp提供的組件性能要優於第三方組件性能

因此最主要的問題,就是如何在web端和uniapp端提供一套語法一致的UI組件庫。再結合上面兩個功能,便可提供一套多端語法徹底一致的開發規範。

實際上,要提供一套語法一致的UI組件庫並不難,只是須要花費一點時間,在原UI庫上再封裝一層便可。詳見下節。

方案

計算機科學中遇到的全部問題均可經過增長一層抽象來解決。

All problems in computer science can be solved by another level of indirection。

by David Wheeler

簡單來講,就是經過抽象一層來解決

考慮到vue的使用人羣更廣,也更偏底層,因此在uniapp上抽象來適配vue

這樣能解決兩個問題:

  • 適配問題,由框架來處理,而不須要開發來考慮自適應問題。至關於將問題從運行期提早到了編譯期。
  • 不須要爲了兼顧多端,而選擇一個折中的方案。好比:爲了手機端的展現,web端不能使用table。經過適配,能夠在手機端將table適配成list。

假設,web端有以下代碼:

這段代碼在web端能夠直接運行,可是Select在手機端其實並不友好,比較友好的方式應該是Picker,因此,咱們就能夠在uniapp裏編寫一個組件select.vue(這部分代碼經過組件庫的方式來編寫,項目引用便可。)

將其註冊到項目中,組件名叫Select,這樣上面的Select就會被解釋爲Picker來處理了。

實施步驟

上面的方案,具體能夠分爲以下幾步實施:

  • 統一項目結構:遷移HBuilderX建立的項目到vue-cli。統一前端項目的結構和打包發佈方式。
  • 統一請求調用:封裝統一的AJAX請求API供兩端使用。初步構建common庫,初步統一代碼規範。
  • 制定語法規範:只使用uniapp和vue均支持的語法,同時對於相同功能的代碼,語法要保持一致。好比路由跳轉。進一步統一規範。
  • 二次封裝uniapp組件:適配iView組件。封裝統一的組件庫,完成多端統一,這是一個持續過程。

遷移HBuilderX建立的項目到vue-cli

  • 基於vue-cli建立uniapp

# 建立uni-app

vue create -p dcloudio/uni-preset-vue my-project

## 若是執行失敗,能夠訪問以下git,下載zip包,解壓

github.com/dcloudio/un…

## 而後執行

vue create -p #{解壓目錄} my-project

# 運行、發佈uni-app

npm run dev:%PLATFORM%

npm run build:%PLATFORM%

%PLATFORM% 可取值以下:

vue與uniapp複用代碼方案及實施步驟

  • 將 HBuilderX 工程內的文件(除 unpackage、node_modules 目錄)拷貝至 vue-cli 工程內 src 目錄
  • 在 vue-cli 工程內從新安裝 npm 依賴(若是以前使用了 npm 依賴的話)

npm i node-sass -D

npm i sass-loader -D

基於git的subtree的代碼公用方法

注意,雖然subtree能夠任意修改提交,不過仍是儘可能在一處修改,好比在admin-vue項目中編寫,不然合併時衝突解決比較麻煩

使用步驟:

  • 建立一個項目,用於存放須要公用的代碼,正常建立便可(建立完後,基本就能夠不用管了
  • 在須要使用同步代碼的項目中執行以下命令(只須要執行一次):

# module是取的別名

git remote add -f module ${上面的項目git地址}

# 將這個項目拉取到 src/module目錄下

git subtree add --prefix=src/module module master --squash

  • 在項目中修改模塊代碼後,正常push。而後使用以下命令同步(每次修改共享代碼後執行):

git subtree push --prefix=src/module module master

  • 須要同步的項目,執行以下命令(若是須要同步共享代碼,則執行):

git subtree pull --prefix=src/module module master

基於npm倉庫的代碼公用方法

下載npm包

npm config set registry http://***/repository/npm-public/

設置後,正常使用npm便可

上傳npm包

經過

npm adduser

添加用戶!

項目中須要有package.json,注意下面的配置

{

"name": "vue-tmp",

"version": "1.0.0",

"private": false,

"publishConfig" : {

"registry" : "http://***/repository/npm-releases/"

},

...

}

private爲false才能上傳,publishConfig配置的是上傳的倉庫路徑

使用以下命令登陸registry!

npm adduser --registry=http://***/repository/npm-releases/

在項目根目錄下執行:

npm publish

便可上傳成功

注意:scripts中不能有publish,不然會觸發二次publish!正式releases倉庫是關閉reploy的!

"scripts": {

"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",

"start": "npm run dev",

"unit": "jest --config test/unit/jest.conf.js --coverage",

"e2e": "node test/e2e/runner.js",

"test": "npm run unit && npm run e2e",

"lint": "eslint --ext .js,.vue examples src test/unit test/e2e/specs",

"build": "node build/build.js"

},

公號:抽象思惟

相關文章
相關標籤/搜索