记录Taro1.3.6 微信小程序 => 抖音(字节)小程序

2022-09-08  本文已影响0人  G_console

描述

由Taro、React、Ts开发的一个微信小程序,现在想变成字节小程序,记录一下迁移过程。

环境

"node": "11.13.0"
"@tarojs/taro": "1.3.6" //有点旧。。。haha

准备工作

https://microapp.bytedance.com 字节开发者中心 注册开发账户,创建一个项目,并认证主体(目前只能企业认证)。
去开发设置里配置服务器域名(直接去小程序后台配置复制过来)。
下载开发者工具。

配置内容

增加project.tt.json,把appID改上去。

编译

把编译命令的:weapp改成:tt
开发工具导入项目的时候,直接导入dist目录,因为IDE会去找project.config.json里面的appid。

问题整理

1、编译结果出错

有两个页面的import Base from '@/components/Base'被编译成了<import src="@/components/Base.wxml" />导致IDE识别出错,跑不起来。其实在:weapp编译出来也是这样的,但微信小程序的IDE就能正常跑。在:tt编译出来的文件里手动删除<import src="@/components/Base.wxml" />之后,项目可以正常跑起来。
这两个页面有个共同点,都用到了无状态函数组件,如下:

public render() {
  return (
    <View>
      {this.renderVipDom()}
    </View>
  )
}
private renderVipDom = () => {
  return <View>...</View>
}

测试发现确实是这个问题导致的。以下是尝试修复过程记录:

(1)、尝试升级taro版本到2.2.13(并不能解决上面问题)
只升级当前项目,先把node版本切换到12.10.0,然后执行yarn add -D @tarojs/cli@2.2.13+yarn taro update project 2.2.13+yarn add -D @tarojs/mini-runner@2.2.13
然后调整config/index配置文件(参考Taro文档)。
再执行yarn remove @tarojs/async-await。同时App.tsx文件里删除import '@tarojs/async-await';
再执行yarn add -D babel-plugin-transform-runtime+yarn add -D babel-plugin-transform-runtime,同时修改项目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'
],

编译后还有如下一些问题,可自行解决:
①、is_js插件有冲突。
②、所有模块化引入的scss全部没有编译进去,样式全部失效。

(2)、研究编译源码,找编译出错的原因(能解决)
我尝试直接删除dist/文件里的<import src="@/components/Base.wxml" />,删除后项目是可以跑起来的。所以理论上只要编译不出现这段代码,就没问题。因为同一套代码,:weapp编译是没有问题的,:tt编译就出这个问题,所以重点去看:tt的编译逻辑。
首先,找到node_modules/@tarojs/cli/src/build.ts,这里面有一个build方法,是taro打包编译的入口。然后顺藤摸瓜,可以依次找到./mini/index > build() > ./mini/page > buildPages() > ./mini/page > buildSinglePage() > ./mini/native > processNativeWxml()。其中有一个关键字段REG_WXML_IMPORT,看他的声明是export const REG_WXML_IMPORT: RegExp = /<import(.*)?src=(?:(?:'([^']*)')|(?:"([^"]*)"))/gi,看着很眼熟。于是我加了个log测试下,果然有收获。

while ((regResult = constants_1.REG_WXML_IMPORT.exec(wxmlContent)) != null) {
    util_1.printLog("reference", '测试', `${regResult[2]}+${regResult[3]}`);  //加的log代码
    importWxmlPathList.push(regResult[2] || regResult[3]);
}
//下面是编译log出来的内容
生成  页面逻辑  dist/pages/resume/publish/index.js*
引用  测试      undefined+@/components/Base.wxml     << 就是他
生成  页面模板  dist/pages/resume/publish/index.ttml

再测试发现前面componentWXMLContent解析出来就已经包含了<import src="@/components/Base.wxml" />这段内容。
./mini/page里有一段:

const transformResult = wxTransformer({
    code: pageJsContent,    //整个页面的内容字符串
    sourcePath: pageJs,      //原始页面路径,如:~/User/git/demo/src/pages/index/index.tsx
    sourceDir,     //根目录,如:~/User/git/demo/src
    outputPath: outputPageJSPath,     //输出页面路径,如:~/User/git/demo/dist/pages/index/index.tsx
    isRoot: true,
    isTyped: constants_1.REG_TYPESCRIPT.test(pageJs),
    adapter: buildAdapter,           //平台名,如:weapp,tt
    env: constantsReplaceList,    //环境变量,如:{ ‘process.env.NODE_ENV’: ‘development’, ENV: undefined, ‘process.env.TARO_ENV’: ‘tt’ }
    rootProps,
    jsxAttributeNameReplace   //属性名替换的配置,如:{ cssClass: ‘css-class’, cssPlaceholderClass: ‘css-placeholder-class’ }
});

这里面传入的数据都没问题,但返回的transformResult就不对了。
然后找到@tarojs/transformer-wx/lib/src/index > transform(),测试发现里面有一段result = new class_1.Transformer(mainClass, options.sourcePath, componentProperies, options.sourceDir).result;处理之后就生成了错误结果。
然后重点来了,找到@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);
        }
    }
},

没搞懂这段代码的目的是什么,我先给它注释掉再说,简单粗暴!

2、自定义头部不支持

字节小程序自定义头部功能需要申请开通才能用。在功能管理 > 页面结构自定义中申请。

3、开发工具默认第一个页面不是"pages/index/index"

开发工具编译后进入的首页不是"pages/index/index",而是进入了"pages/mine/index"。
但是上传代码后用真机进入体验版,首页进入正常。

未完待续。。。

参考资料

Taro 1.x 迁移至 2.x文档:https://taro-docs.jd.com/taro/docs/2.x/migrate-to-2
Taro cli流程及编译代码解析:https://segmentfault.com/a/1190000041515931
字节小程序开发文档:https://microapp.bytedance.com/docs/zh-CN/mini-app/develop/functional-plug-in/custom/

上一篇下一篇

猜你喜欢

热点阅读