2015年12月

介绍

在 React-Native 中,实现了一个类似于 webpack 的包系统,命令行工具提供了一个 bundle 的功能,用来打包整个项目的文件。

Bundle

熟悉 webpack 的人应该知道,webpack 最终会将所有引入的文件(JS、CSS、模板等)全部打包到一个 bundle.js 中,最终项目只需要引入这一个文件就可以。

而 React-Native 的打包机制与 webpack 非常类似,最终打包出一个index.platform.bundle(platform 根据平台区分)供最终 APP 打包使用。

一些踩过的坑

1. 包系统带来的问题

因为 React-Native 的包管理机制和 webpack 类似,因此它会对所有与模块相关的关键字进行检测并做对应的操作。检测机制非常简单:

exports.IMPORT_RE = /(\bimport\s+(?:[^'"]+\s+from\s+)??)(['"])([^'"]+)(\2)/g;
exports.EXPORT_RE = /(\bexport\s+(?:[^'"]+\s+from\s+)??)(['"])([^'"]+)(\2)/g;
exports.REQUIRE_RE = /(\brequire\s*?\(\s*?)(['"])([^'"]+)(\2\s*?\))/g;
exports.SYSTEM_IMPORT_RE = /(\bSystem\.import\s*?\(\s*?)(['"])([^'"]+)(\2\s*?\))/g;

因此所有涉及到关键字的地方,都会被尝试自动引入资源文件并且打包。

这就有可能会导致一个问题,当一个模块不存在的时候(其实这可能是我们外部提供的模块),就会出现打包失败的情况。

这时候,我们可以使用 React-Native 提供的方法来处理这一问题。它提供了一个注释关键字@providesModule用来标记我们已经手动引入到系统中的模块。

比如之前我在做一个 fetch 的全局拦截器适配的时候,就遇到了这个问题 (PR 链接)

这个库本身为了对环境进行最大程度的兼容,会在环境不支持 fetch 的时候,尝试引入whatwg-fetch模块,作者使用了 try-catch 来容错,然而在 React-Native 里,打包程序会因为找不到whatwg-fetch模块而直接报错。

这时候,就可以使用@providesModule来处理。

/*
* @providesModule whatwg-fetch
*/

在这个模块中加入这一段注释,React-Native 的 bundle 程序就不会在尝试加载这个额外的模块,也就不会再报错了。

2. Android 平台 APK 生成

React-Native 的 Android 平台支持还不久,还有很多没有完善的地方。生成 APK 还不够自动化,需要手动执行操作。

根据官方的流程说明,在大多数情况下,都可以完成 APK 的构建。也有一些小的坑会遇到。

  1. 使用官方所推荐的构建命令./gradlew assembleRelease,需要保证你已经设定好了签名的 key,不然生成的 APK 是无法正常安装的。
  2. 由于./gradlew assembleRelease这个脚本执行过程中也会调用 React-Native 的 bundle 命令,因此,如果你此前已经开启了一个 React-Native packager 的服务器,就会在构建过程中报错,会告诉你 React-Native 的调用出错了,你可以检查一下是否已经有一个 packager 的服务器已经在运行了,把它停掉重新打包即可。
  3. 官方说明中提到可以通过开启 Proguard 来减小生成的 APK 文件的体积。但是,请务必确保你已经配置好了 Proguard 的设置,不然构建也会失败。

问题:

angular 1.4.x 版本开始,<div ng-repeat="(key, value) in myObj"> ... </div> 的方法移除了按照首字母排序的规则,改为使用浏览器默认的方法,也就是for key in myObj

因此当我们使用 angular-filter 的 groupBy 方法将数组分组时,分组后的数组不会再按照 key 排序,某些情况下就会造成一些麻烦。

解决方案:

根据 这一条说明,利用 toArray 和 orderBy 可以解决这一个问题。

toArray 方法可以将对象转换成固定的数组。这个方法接受一个 bool 类型的参数,用来指定是否将对象的 key 作为转换后数组中的元素的一个属性输出,如果设为 true,那么数组元素将会多一个属性 $key 代表原来的对象的 key

所以我们可以这样完成 groupBy 方法的排序:

<ul ng-repeat="group in myObj | groupBy: 'groupKey' | toArray: true | orderBy: '$key'">
  <li ng-bind="$key"></li>
  <li ng-repeat="item in group"></li>
</ul>

这样,groupBy 的结果就会按照对应的参数的首字母(这里是groupKey)排序了。