Taro3中多端组件的项目配置bug解决方案
前段时间公司业务项目升级Taro3之后,进行跨端编译的时候出现问题了。通过控制台的编译报错发现,问题出现在项目配置上。
业务场景
事情的起因是这样的,为了满足业务的需求,解决不同端的差异性问题。虽然Taro内置了环境变量TARO_ENV可以解决跨端的问题,但是会让代码中充斥着大量的逻辑判断的代码,影响代码的可维护性,而且也让代码的可读性变得非常低。为了解决这个问题,进行业务开发的时候采用了多端组件的解决方案。
多端组件(官方文档)
开发者可以通过使用统一接口的多端文件,来解决跨端差异的功能。开发者可以通过将文件修改成
原文件名 + 端类型
的命名形式(端类型对应着process.env.TARO_ENV
的取值),不同端的文件代码对外保持统一接口,而引用的时候仍然是import
原文件名的文件。Taro 在编译时,会跟根据当前的编译平台类型,将加载的文件变更为带有对应端类型文件名的文件,从而达到不同的端加载对应文件的目的。
问题复现
首先展示一下项目结构,由于涉及到公司业务,所以具体代码就不展现了。
├── app.tsx 通用端的业务入口 ├── app.config.ts 通用端的项目配置 ├── app.weapp.tsx 支付宝端的入口文件 └── app.weapp.config.ts 支付宝端的项目配置 复制代码
进行 npm run build:alipay
的时候,编译正常,而进行 npm run build:weapp
的时候,就进行编译报错。报错信息如下:
解决历程
报错初步分析
通过报错信息,发现报错原因来源于 @tarojs/mini-runner 插件的 src/plugins/MiniPlugin.ts 的901行。我进入源码查看,经过一番调试发现,原来问题是这样的:
首先,在获取 app config 配置内容的时候,生成的 this.filesConfig
内容,跟在生成小程序相关文件的获取 app config 配置内容的时候 this.filesConfig[appConfigName]
的时候 key 不匹配。
// this.filesConfig { 'app.config': { content: { pages: [Array], window: [Object] }, path: '...\\src\\app.weapp.config.ts' }, ... } // appConfigName app.weapp.config 复制代码
造成这个原因的源代码:
// 生成小程序相关文件 const appConfigPath = this.getConfigFilePath(this.appEntry); const appConfigName = path.basename(appConfigPath).replace(path.extname(appConfigPath), ''); this.generateConfigFile(compilation, this.appEntry, this.filesConfig[appConfigName].content); // 获取 app config 配置内容 const appName = path.basename(this.appEntry).replace(path.extname(this.appEntry), ''); const fileConfig = this.filesConfig[this.getConfigFilePath(appName)]; 复制代码
初步猜测
既然导致这个问题的原因是,获取 app config 配置的 key 和 生成 app config 配置的 key 不一致导致的,那么,我是不是有可能通过调整 config 配置文件的名称来解决呢?貌似可行哈。具体尝试方案如下:
将 app.weapp.config 删除;
在 app.config.ts 文件中,通过 process.env.TARO_ENV 来配置不同端的项目配置;
重新执行
npm run build:weapp
。
测试结果
很遗憾,GG了,产生了新的报错信息:
问题出现在哪里呢?第一反应是,陷入死循环了,除非掉头回去使用环境变量来解决入口问题,否则就是死胡同。喝口凉水,冷静一下,发现我一开始的思路就进入了错误的方向。我正确的解决方向应该是,通过解决this.getConfigFilePath 和 appConfigName 的差距就可以了。
再次猜测
首先我分析了一下 path.basename(this.appEntry).replace(path.extname(this.appEntry), ''),path.basename 获取路径的最后一部分,path.extname 获取路径的扩展名;然后,正常编译的时候 this.appEntry 是 */src/app.tsx,对应的 appName 是 app,而进行 weapp 编译的时候,this.appEntry 是 */src/app.weapp.tsx,对应的 appName 是 app.weapp,通过this.getConfigFilePath得到的结果都是 app.config。
看完这里我就恍然明白问题所在了,原来是 getConfigFilePath 的问题。那就再深入去看一下 getConfigFilePath 的内容。
helper_1.resolveMainFilePath(`${filePath.replace(path.extname(filePath), '')}.config`) 复制代码
真正的问题点完全浮出水面了,path.extname 处理 app.weapp 的时候,把 .weapp 当作文件的扩展名给 replace掉了。
再次尝试
我通过process.env.TAR_ENV来判断path.extname获取的是端类型,还是真正的扩展名,然后做出不同的处理,具体处理代码如下:
const extname = path.extname(filePath); if (`.${process.env.TARO_ENV}` === extname) { return helper_1.resolveMainFilePath(`${filePath}.config`) } return helper_1.resolveMainFilePath(`${filePath.replace(path.extname(filePath), '')}.config`); 复制代码
经过尝试,万事大吉,成功ko掉了。
好的,问题已经解决了,希望对大家有所帮助。欢迎大家点赞关注,在下方评论区留言交流。
作者:花开花落花中妖
链接:https://juejin.cn/post/7066328625833836574