前言在ReactNative项目中,可以看到node_modules文件夹,该文件夹是存放node模块的地方。Node.js的包管理器npm是世界上最大的开源库生态系统。说到npm,一般是指两种意思:一种是Node.js开放的模块注册管理系统,另一种是Node.js默认的模块管理器,是一个命令行软件,用来安装和管理管理节点模块。本文旨在探索如何在ReactNative中编写自定义npm模块(类似于插件)并上传到npm以供其他人使用。npm简介npm是一个Node.js模块。安装Node.js会默认安装npm。可以在终端使用如下命令查看npm的版本:npm-vupgradenpm:sudonpminstallnpm-g安装模块(安装后会生成一个node_modules目录,下面是安装好的node模块):npminstall查看npm配置:npmconfiglistsetproxy://sethttpproxynpmconfigsetproxyhttp://server:port//sethttpsproxynpmconfigsethttps-proxyhttp://server:port介绍一些基本的npm命令,然后就可以创建一个本地模块。首先打开一个终端,在你要创建自定义模块的地方新建一个文件夹,然后在命令行登录npm。输入以下命令:npmadduser接下来,系统将提示您输入用户名、密码和电子邮件地址。一项一项完成后,可以输入以下命令查看当前的npm用户:npmwhoami如果刚才注册的用户名显示正确,则登录成功。然后使用下面的命令创建一个npm模块:npminit执行完上面的命令后,会引导你创建一个package.json文件,包括名称、版本、作者等信息。创建一个模块这里我想提一下为什么要编写自定义模块。虽然ReactNative实现了很多Native组件,提供了丰富的API,但是一些native库仍然不支持,并且有很多开源的组件和库是面向native的,所以如果你想在ReactNative中使用这些组件和库library需要自己定义一个模块,也方便别人集成。接下来,我们就直接进入正题吧。编写可在ReactNative中使用的自定义模块。在命令行执行react-nativeinitAwesomeProject来初始化一个ReactNative项目。这里以Android为例,使用AndroidStudio选择菜单File->open打开AwesomeProject文件夹下的android文件夹,然后选择File->New->NewModule,选择创建AndroidLibrary,如图如图,这里新建了一个Library模块,然后点击finish,可以看到如下目录结构:然后把需要依赖的jar放到libs目录下。这里以jpush-sdk为例,将官网下载的libs复制到libs下,将相关资源文件放到res文件夹下,然后复制AndroidManifest文件内容,修改包名,最后进行配置在build.gradle中,如下(注意targetSdkVersion改为22,在23上运行可能会crash):applyplugin:'com.android.library'android{compileSdkVersion23buildToolsVersion"23.0.2"defaultConfig{minSdkVersion16targetSdkVersion22versionCode1versionName"1.0"manifestPlaceholders=[JPUSH_APPKEY:"/yourApp在这里修改Push的Key",/AppKeyAPP_CHANNEL:"developer-default"//应用通道号]}lintOptions{abortOnErrorfalsewarning'InvalidPackage'}sourceSets{main{jniLibs.srcDirs=['libs']}}}repositories{mavenCentral()}dependencies{compilefileTree(dir:'libs',include:['*.jar'])compile"com.facebook.react:react-native:+"}至此,我们完成了第一步接下来需要编写Native与JS交互的代码。JS调用Native和Native调用JS部分可以参考本文。我不会在这里详细介绍。假设我们已经完成了Native部分的代码,那么在JS中如何制作呢?别人可以通过import调用我们的JS代码,从而调用Native吗?首先进入my-react-library文件夹,然后在终端执行npminit生成package.json文件(注意这里的name字段,这里是别人引用你模块的名字),然后创建索引。js文件,这是node模块的JS入口。这里推荐使用SublimeText来写JS。这里以jpush-react-native为例:jpush-react-native/index.js部分代码import{NativeModules,Platform,DeviceEventEmitter}from'react-native';//通过找到我们在Native中定义的JPushModule类NativeModulesconstJPushModule=NativeModules.JPushModule;exportdefaultclassJPush{/***Androidonly*初始化JPush必须先初始化再执行其他操作*/staticinitPush(){JPushModule.initPush();}}上面定义了一个initPush方法,initPush实际调用的是定义在JPushModule的initPush方法,其他方法类似,本质上都是通过NativeModules调用Native提供的方法。通过这篇文章,我们完成了ReactNative自定义模块。现在是时候发布我们的自定义模块了。在package.json所在目录执行npmpublish,将我们自定义的模块上传到npm库中。每次更新版本,都需要修改package.json中的version值,然后执行npmpublish。在ReactNative目录下使用,执行:npminstallmy-react-library--save安装完成后,这个模块会保存在node_modules文件夹中。由于我们的模块是一个AndroidLibrary项目,所以我们需要在Native中配置它。主要是添加项目依赖:某人的react-nativeproject/somemodule/build.gradledependencies{compilefileTree(dir:"libs",include:["*.jar"])compile"com.android.support:appcompat-v7:23.0.1"compile"com.facebook.react:react-native:+"//Fromnode_modules//在dependencies中添加一个自定义模块compileproject(':my-react-library')}然后在settings.gradle中配置看看:某人的react-nativeproject/settings.gradleinclude':app',':my-react-library'project(':my-react-library').projectDir=newFile(rootProject.projectDir,'../node_modules/my-react-library/android')在MainActivity中添加自定义包:MainActivity.java...mReactInstanceManager=ReactInstanceManager.builder().setApplication(getApplication()).setBundleAssetName("index.android.bundle").setJSMainModuleName("react-native-android/index.android").addPackage(newMainReactPackage())//添加自定义package.addPackage(newMyReactPackage())...如果是RN0.29.0或以上版本,则应在MainApplication中添加:主要应用ation.java@OverrideprotectedListgetPackages(){returnArrays.asList(newMainReactPackage(),newMyReactPackage());}至此我们就完成了Native部分的配置(完成后同步),接下来我们可以使用其他的时候使用我们的模块,可以这样写:someone.js//'my-react-library'这里是package.json中定义的名字//所以可以importMyModulefrom'my-react-library'exportdefaultclassSomeClassextendsReact.Component{componentDidMount(){//调用index.js中定义的doSomething()MyModule.doSomething();}}