描述
由Taro坑夯、React喂窟、Ts開(kāi)發(fā)的一個(gè)微信小程序庐椒,現(xiàn)在想變成字節(jié)小程序椒舵,記錄一下遷移過(guò)程。
環(huán)境
"node": "11.13.0"
"@tarojs/taro": "1.3.6"
//有點(diǎn)舊约谈。笔宿。。haha
準(zhǔn)備工作
https://microapp.bytedance.com 字節(jié)開(kāi)發(fā)者中心 注冊(cè)開(kāi)發(fā)賬戶棱诱,創(chuàng)建一個(gè)項(xiàng)目泼橘,并認(rèn)證主體(目前只能企業(yè)認(rèn)證)。
去開(kāi)發(fā)設(shè)置里配置服務(wù)器域名(直接去小程序后臺(tái)配置復(fù)制過(guò)來(lái))迈勋。
下載開(kāi)發(fā)者工具炬灭。
配置內(nèi)容
增加project.tt.json
,把a(bǔ)ppID改上去靡菇。
編譯
把編譯命令的:weapp
改成:tt
重归。
開(kāi)發(fā)工具導(dǎo)入項(xiàng)目的時(shí)候,直接導(dǎo)入dist目錄厦凤,因?yàn)镮DE會(huì)去找project.config.json
里面的appid鼻吮。
問(wèn)題整理
1、編譯結(jié)果出錯(cuò)
有兩個(gè)頁(yè)面的import Base from '@/components/Base'
被編譯成了<import src="@/components/Base.wxml" />
導(dǎo)致IDE識(shí)別出錯(cuò)较鼓,跑不起來(lái)椎木。其實(shí)在:weapp編譯出來(lái)也是這樣的,但微信小程序的IDE就能正常跑博烂。在:tt編譯出來(lái)的文件里手動(dòng)刪除<import src="@/components/Base.wxml" />
之后香椎,項(xiàng)目可以正常跑起來(lái)。
這兩個(gè)頁(yè)面有個(gè)共同點(diǎn)禽篱,都用到了無(wú)狀態(tài)函數(shù)組件畜伐,如下:
public render() {
return (
<View>
{this.renderVipDom()}
</View>
)
}
private renderVipDom = () => {
return <View>...</View>
}
測(cè)試發(fā)現(xiàn)確實(shí)是這個(gè)問(wèn)題導(dǎo)致的。以下是嘗試修復(fù)過(guò)程記錄:
(1)谆级、嘗試升級(jí)taro版本到2.2.13(并不能解決上面問(wèn)題)
只升級(jí)當(dāng)前項(xiàng)目烤礁,先把node版本切換到12.10.0,然后執(zhí)行yarn add -D @tarojs/cli@2.2.13
+yarn taro update project 2.2.13
+yarn add -D @tarojs/mini-runner@2.2.13
肥照。
然后調(diào)整config/index
配置文件(參考Taro文檔)脚仔。
再執(zhí)行yarn remove @tarojs/async-await
。同時(shí)App.tsx文件里刪除import '@tarojs/async-await';
舆绎。
再執(zhí)行yarn add -D babel-plugin-transform-runtime
+yarn add -D babel-plugin-transform-runtime
鲤脏,同時(shí)修改項(xiàng)目babel 配置如下:
babel: {
sourceMap: true,
presets: [['env', { modules: false }]],
plugins: [
'transform-decorators-legacy',
'transform-class-properties',
'transform-object-rest-spread',
['transform-runtime', {
"helpers": false,
"polyfill": false,
"regenerator": true,
"moduleName": 'babel-runtime'
}]
]
}
由于使用了sass,還需要yarn add -D @tarojs/plugin-sass
,并在config里配置:
plugins: [
'@tarojs/plugin-sass',
'@tarojs/plugin-less'
],
編譯后還有如下一些問(wèn)題猎醇,可自行解決:
①窥突、is_js插件有沖突。
②硫嘶、所有模塊化引入的scss全部沒(méi)有編譯進(jìn)去阻问,樣式全部失效。
(2)沦疾、研究編譯源碼称近,找編譯出錯(cuò)的原因(能解決)
我嘗試直接刪除dist/文件里的<import src="@/components/Base.wxml" />
,刪除后項(xiàng)目是可以跑起來(lái)的哮塞。所以理論上只要編譯不出現(xiàn)這段代碼刨秆,就沒(méi)問(wèn)題。因?yàn)橥惶状a忆畅,:weapp編譯是沒(méi)有問(wèn)題的衡未,:tt編譯就出這個(gè)問(wèn)題,所以重點(diǎn)去看:tt的編譯邏輯家凯。
首先缓醋,找到node_modules/@tarojs/cli/src/build.ts
,這里面有一個(gè)build
方法肆饶,是taro打包編譯的入口改衩。然后順藤摸瓜岖常,可以依次找到./mini/index > build()
> ./mini/page > buildPages()
> ./mini/page > buildSinglePage()
> ./mini/native > processNativeWxml()
驯镊。其中有一個(gè)關(guān)鍵字段REG_WXML_IMPORT
,看他的聲明是export const REG_WXML_IMPORT: RegExp = /<import(.*)?src=(?:(?:'([^']*)')|(?:"([^"]*)"))/gi
竭鞍,看著很眼熟板惑。于是我加了個(gè)log測(cè)試下,果然有收獲偎快。
while ((regResult = constants_1.REG_WXML_IMPORT.exec(wxmlContent)) != null) {
util_1.printLog("reference", '測(cè)試', `${regResult[2]}+${regResult[3]}`); //加的log代碼
importWxmlPathList.push(regResult[2] || regResult[3]);
}
//下面是編譯log出來(lái)的內(nèi)容
生成 頁(yè)面邏輯 dist/pages/resume/publish/index.js*
引用 測(cè)試 undefined+@/components/Base.wxml << 就是他
生成 頁(yè)面模板 dist/pages/resume/publish/index.ttml
再測(cè)試發(fā)現(xiàn)前面componentWXMLContent
解析出來(lái)就已經(jīng)包含了<import src="@/components/Base.wxml" />
這段內(nèi)容冯乘。
在./mini/page
里有一段:
const transformResult = wxTransformer({
code: pageJsContent, //整個(gè)頁(yè)面的內(nèi)容字符串
sourcePath: pageJs, //原始頁(yè)面路徑,如:~/User/git/demo/src/pages/index/index.tsx
sourceDir, //根目錄葱弟,如:~/User/git/demo/src
outputPath: outputPageJSPath, //輸出頁(yè)面路徑盐碱,如:~/User/git/demo/dist/pages/index/index.tsx
isRoot: true,
isTyped: constants_1.REG_TYPESCRIPT.test(pageJs),
adapter: buildAdapter, //平臺(tái)名蹦掐,如:weapp,tt
env: constantsReplaceList, //環(huán)境變量,如:{ ‘process.env.NODE_ENV’: ‘development’, ENV: undefined, ‘process.env.TARO_ENV’: ‘tt’ }
rootProps,
jsxAttributeNameReplace //屬性名替換的配置喷好,如:{ cssClass: ‘css-class’, cssPlaceholderClass: ‘css-placeholder-class’ }
});
這里面?zhèn)魅氲臄?shù)據(jù)都沒(méi)問(wèn)題,但返回的transformResult
就不對(duì)了读跷。
然后找到@tarojs/transformer-wx/lib/src/index > transform()
梗搅,測(cè)試發(fā)現(xiàn)里面有一段result = new class_1.Transformer(mainClass, options.sourcePath, componentProperies, options.sourceDir).result;
處理之后就生成了錯(cuò)誤結(jié)果。
然后重點(diǎn)來(lái)了,找到@tarojs/transformer-wx/lib/src/class > CallExpression()
里面有一段:
enter(callPath) {
const callee = callPath.get('callee');
const args = callPath.node.arguments;
if (callee.isMemberExpression()) {
const { object, property } = callee.node;
if (t.isThisExpression(object) && t.isIdentifier(property) && property.name.startsWith('render')) {
const propName = property.name;
if (!self.methods.has(propName)) {
const o = utils_1.getSuperClassPath(self.classPath);
if (o) {
const p = o.resolvePath.endsWith('.js') ? o.resolvePath.slice(0, o.resolvePath.length - 3) : o.resolvePath;
self.importJSXs.add(`<import src="${p + '.wxml'}"/>`); //這是不是很眼熟
}
}
self.renameJSXClassFunc(propName, methodName, callPath, args);
}
}
if (callee.isIdentifier()) {
const nodeName = callee.node.name;
if (nodeName.startsWith('renderClosure')) {
self.renameJSXClassFunc(nodeName, methodName, callPath, args, true);
}
}
},
沒(méi)搞懂這段代碼的目的是什么无切,我先給它注釋掉再說(shuō)荡短,簡(jiǎn)單粗暴!
2哆键、自定義頭部不支持
字節(jié)小程序自定義頭部功能需要申請(qǐng)開(kāi)通才能用掘托。在功能管理 > 頁(yè)面結(jié)構(gòu)自定義中申請(qǐng)。
3籍嘹、開(kāi)發(fā)工具默認(rèn)第一個(gè)頁(yè)面不是"pages/index/index"
開(kāi)發(fā)工具編譯后進(jìn)入的首頁(yè)不是"pages/index/index"烫映,而是進(jìn)入了"pages/mine/index"。
但是上傳代碼后用真機(jī)進(jìn)入體驗(yàn)版噩峦,首頁(yè)進(jìn)入正常锭沟。
未完待續(xù)。识补。族淮。
參考資料
Taro 1.x 遷移至 2.x文檔:https://taro-docs.jd.com/taro/docs/2.x/migrate-to-2
Taro cli流程及編譯代碼解析:https://segmentfault.com/a/1190000041515931
字節(jié)小程序開(kāi)發(fā)文檔:https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/functional-plug-in/custom/