概述
概念
馬甲包:和主產(chǎn)品包擁有同樣的內(nèi)容和功能讯嫂,除了icon和應用名稱不能完全一致,其他基本一致兆沙。
主包:主APP
馬甲包的好處:
- 占領(lǐng)搜索資源位欧芽,獲取更多業(yè)務資源;
- 為主包引流葛圃,提高主包品牌影響力千扔;
- 規(guī)避風險,預防萬一库正。就像嗶哩嗶哩一樣曲楚。嗶哩嗶哩剛下架了,他的馬甲立馬就頂上了褥符。
存在問題
雷同問題
頁面不可完全雷同龙誊,需要修改頁面色調(diào)、主圖属瓣、模塊载迄、樣式。
長期維護
馬甲是需要長期維護抡蛙。如果一個馬甲做得很好护昧,那么完全可以將其獨立出來作為精品馬甲,其實就是獨立APP粗截,必要的時候惋耙,如果主包遭遇不測可以將馬甲作為新的主包頂上。
方案
需要解決的問題
- 使用新的icon熊昌、包名绽榛、應用名
- 頁面樣式避免與主包完全雷同
- 盡可能更多的復用現(xiàn)有代碼邏輯
- 后期維護起來不可成本太高
解決思路
- 應用基礎信息可配置化
- 應用頁面樣式可動態(tài)設置
- 根據(jù)配置信息依賴指定業(yè)務組件
- 拆分殼應用與馬甲包lib,創(chuàng)建腳本自動更新馬甲包lib
實踐
馬甲包腳手架
腳手架
前端概念
? 隨著前端工程化的概念越來越深入人心婿屹,腳手架的出現(xiàn)就是為減少重復性工作而引入的命令行工具灭美,擺脫ctrl + c, ctrl + v,此話zenjiang? 現(xiàn)在新建一個前端項目昂利,已經(jīng)不是在html頭部引入css届腐,尾部引入js那么簡單的事了,css都是采用Sass或則Less編寫蜂奸,在js中引入犁苏,然后動態(tài)構(gòu)建注入到html中;除了學習基本的js扩所,css語法和熱門框架围详,還需要學習構(gòu)建工具webpack,babel這些怎么配置祖屏,怎么起前端服務助赞,怎么熱更新买羞;為了在編寫過程中讓編輯器幫我們查錯以及更加規(guī)范,我們還需要引入ESlint嫉拐;甚至哩都,有些項目還需要引入單元測試(Jest)。對于一個更入門的人來說婉徘,這無疑會讓人望而卻步。而前端腳手架的出現(xiàn)咐汞,就讓事情簡單化盖呼。
? 一鍵命令,新建一個工程化撕,再執(zhí)行兩個npm命令几晤,跑起一個項目。在入門時植阴,無需關(guān)注配置什么的蟹瘾,只需要開心的寫代碼;另外掠手,對于很多系統(tǒng)憾朴,他們的頁面相似度非常高,所以就可以基于一套模板來搭建喷鸽,雖然是不同的人開發(fā)众雷,但用腳手架來搭建,相同的項目結(jié)構(gòu)與代碼書寫規(guī)范做祝,是很利于項目的后期維護的砾省;以上就是為什么腳手架存在的意義, 讓項目從"搭建-開發(fā)-部署"更加快速以及規(guī)范 (出自于某乎達人)混槐。
項目說明
只需運行命令行輸入Android 基礎項目信息如應用名编兄、版本號、包名
即可收獲一個可以直接運行的定制化Android項目
腳手架環(huán)境
- node: v9.2.0
命令
init | generate vest template.
- 引入inquirer.js 交互式命令行工具声登,定義 question
- 接收輸入信息
- 拉取模板項目
- 寫入輸入信息
- 提示幫助
核心代碼
function create() {
inquirer.prompt(questions).then(function(answers) {
let _answers = JSON.parse(JSON.stringify(answers))
let { name, version, applicationID} = _answers
const spinner = ora('downloading template'),
tmp = path.resolve(process.cwd(), name)
...
spinner.start();
if (exists(tmp)) rm(tmp);
download(`http://xxx/vest-template`, tmp, { clone: true } ,function(err) {
spinner.stop()
if (err) logger.fatal('Failed to download repo ' + TEMPLATE + ': ' + err.message.trim())
...
changeFile(tmp + '/config/vest.app.js', `${TEMPLATE}-name`, name)
...
})
});
};
使用示例
sync | sync vest project config
- 使用fs讀取項目配置文件自定義信息狠鸳,包括:
- 目標業(yè)務組件
- 應用樣式
- 應用圖標
- 三方SDK配置信息
- 寫入自定義配置信息至Android項目
核心代碼
let thirdSdkArr = new Array();
thirdSdkArr.push(thirdSdkPrefix)
thirdSdkArr.push("APPLICATIONID=" + vestApp.applicationId)
thirdSdkArr.push("APP_NAME=" + vestApp.appName)
thirdSdkArr.push("VERSIONNAME=" + vestApp.version)
thirdSdkArr.push("APP_FFROM=" + vestApp.ffrom)
Object.keys(compileThirdSdk).forEach(function (key) {
thirdSdkArr.push(key + "=" + compileThirdSdk[key])
});
thirdSdkArr.push(thirdSdkEndfix)
let thirdSdkStr = thirdSdkArr.join("\n");
let sdkPreIndex = propertiesContent.lastIndexOf(thirdSdkPrefix)
let sdkEndIndex = propertiesContent.lastIndexOf(thirdSdkEndfix) + thirdSdkPrefix.length - 1;
let sdkEndStr = (propertiesContent.slice(sdkEndIndex, propertiesContent.length).length !== 0 ? "\n" + propertiesContent.slice(sdkEndIndex, propertiesContent.length) : "")
fs.writeFileSync(propertiesPath, propertiesContent.slice(0, sdkPreIndex).concat(thirdSdkStr, sdkEndStr), 'utf8');
使用示例
模板項目
項目目錄
實現(xiàn)
腳手架合并項目配置信息后寫入vest.properties文件
-
編寫 build.gradle 腳本
讀取vest.properties
-
寫入配置信息至buildConfigField中
new HashMap<String, String>((Map) vestProperties).each { buildConfigField "String",it.key, "\"${it.value}\"" }
-
寫入配置信息至manifestPlaceholders中
manifestPlaceholders = new HashMap<String, String>((Map) vestProperties)
腳手架讀取vest.modules.js,寫入modules.json文件至Android 項目下的app/src/main/assets目錄下
-
應用開啟時捌刮,讀取assets目錄下modules.json文件碰煌,序列化為實例對象
fun init(context: Context) { val assertsFile = getAssertsFile(context, "modules.json") if (assertsFile == null) { LogUtil.e("請先運行 vest sync 命令初始化配置文件") return } val configJson = String(assertsFile) if (TextUtils.isEmpty(configJson)) { LogUtil.e("請先運行 vest sync 命令初始化配置文件") return } modulesConfigBean = GsonProvider.getGson().fromJson(configJson, ModulesConfigBean::class.java) }
使用配置信息實例對象初始化應用
總結(jié)
本馬甲包自動組裝方案使用配置文件和腳手架相配合,屏蔽Android項目信息绅作,使其在使用時只需配置完成后運行腳手架命令就可得到定制化的Android項目芦圾。
后期添加管理后臺,部署至服務器上后開發(fā)階段可以完全不需要Android開發(fā)人員介入俄认,只需定期更新版本个少。
極大減少Android開發(fā)工程師工作量洪乍,降低應用開發(fā)成本,解決了后期迭代更新不及時的問題夜焦。