Taro开发小红书小程序样式失效问题解决方案

217 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

前情回顾

在上一篇文章(解决Taro开发小红书小程序样式失效问题)中,我们详细的分析了Taro开发小红书小程序时样式失效问题的产生原因。然后,有兄弟们想要了解如何解决的,这里我们就整一篇文章来详细介绍一下最终的解决方案。

前置知识

在了解如何解决这个问题之前,我们需要先简单了解一点点前置知识,以方便大家理解接下来所说的东西。

Taro3编译的底层机制

自从2.x版本之后,Taro官方放弃了自研的打包构建工具,而是采用webpack来进行打包构建,然后以plugin插件的形式解决不同平台的差异性问题。而我们前文也提到了小红书小程序是借助于 @tarojs/plugin-platform-xhs 插件来实现的,这也就给我们解决问题提供了解决方案,开发一个新的插件来抹平Taro编译导致的小红书小程序的特殊表现。

如何开发Taro插件

要想开发一个Taro插件首先需要了解插件开发的规范,这里我们就直接上官方文档,不做多余的说明了。

解决方案

编译过程扩展

我们确定了使用开发Taro插件的方式来解决问题,但是我们要扩展哪个编译过程呢?

Taro官方提供了很多钩子来对应Taro编译不同过程(这一点跟webpack其实的相似的),这里我们介绍一下几个主要的钩子:onBuildStartonBuildFinishonBuildComplete 三个钩子分别表示编译开始,编译结束和构建完成。

onBuildFinish 和 onBuildComplete

  • ctx.onBuildFinish(() => void),编译结束,接收一个回调函数。在每次 Webpack 编译后都会被触发。如果是在 watch 模式下,那么每当有文件改变触发 Webpack 编译时,都会触发 onBuildFinish 钩子。
  • ctx.onBuildComplete(() => void),构建完成,接收一个回调函数。在 Taro 构建命令结束后被触发,与 onBuildFinish 钩子的区别在于其只会被触发一次。

通过官方的介绍,相比很明显了,我们要使用onBuildFInish这个钩子。之所以采用这个钩子,主要是因为我们开发过程中,采用的是watch模式,每次保存修改的时候都会触发一次编译。

核心代码

这里我们就主要介绍一下主要思路,然后展示一下核心代码。

首先在onBUildFinsh钩子触发之后,编译之后的代码已经输出到output中了,这一点十分重要,我们后续的解决方案正是基于这一点实现的。

我们首先通过node提供的fs方法读取到output中的app.css文件内容;然后再通过正则去匹配来判断是否存在公共内容被引入进来;如果存在的话,进行@import内容的位置移动,然后替换app.css的文件内容,否则的话,说明不存在公共内容,直接跳过钩子即可。

获取文件内容的代码:

    fs.readFileSync(filePath, 'utf-8');

进行内容替换的代码:

const importCss = fileStr.match(/@import\sdd+\".*\";/g);

if (!importCss) {
    return;
}

const importCssStr = importCss[0];
const insertIndex = fileStr.indexOf(`@charset "UTF-8";`) > 0 ? 17 : 0;
const rawFileStr = fileStr.replace(/@import\sdd+\".*\";/g, '');
const flyFileStr = rawFileStr.slice(0, insertIndex) + importCss + rawFileStr.slice(insertIndex);

fs.writeFileSync(filePath, flyFileStr);

核心代码就是这么的简单,是否是不可思议呢?

事实上,就是这么的简单。开发中碰到的一些问题主要是思路的问题,只要思路打开了,解决起来相对来说很容易。欢迎大家在下方进行留言讨论。