开发本身的react-native组件并发布到npm[转]

原文连接:https://www.jianshu.com/p/091a68ea1ca7

写在前面

在作react-native开发的时候,咱们常常会找到一些第三方组件,而且经过npm install的方式很方便的安装使用。在使用的同时,你是否想过,咱们本身应该如何开发并发布一个组件呢?不论是给本身的多个项目共用,或者开源给到别人用,这都是一件很酷的事情。javascript

那么今天,我就以我本身开发的一个在iosandroid通用的CardView组件为例来说一下,如何开发一个本身的组件,并开源到github、发布到npm上去css

一个说明java

个人组件名为react-native-rn-cardview。教程里若是出现react-native-cardview组件名,视为同一意思。node

1 建立并实现

1.1 建立自定义组件模版项目

1.1.1 安装react-native-create-library

$ npm install -g react-native-create-library

1.1.2 建立模板项目

咱们用命令react-native-create-library建立项目,并指定平台为ios,android,指定android中的package,其余参数能够自行参考在react-native-create-librarygithub 上的文档说明,这里就不赘述react

$ react-native-create-library --package-identifier com.quenice.cardview --platforms android,ios cardview

咱们重命名一下项目名android

$ mv cardview react-native-cardview

有人可能会说,楼主为何不直接生成react-native-cardview的项目,而要先生成cardview再重命名。其实这是一个小技巧,由于利用react-native-create-library生产的项目,一些跟组件相关的名称或者类会默认加上react-native或者RN前缀。
例如,若是你的初始项目名是react-native-card-view,那么package.json中定义的组件名将是react-native-react-native-card-view,android模块中定义的相关类会是RNReactNativeCardviewModule.java,这显然比较丑啊。ios

ok, 咱们继续。git

如今的目录结构:github

$ tree
└── react-native-cardview
    ├── README.md
    ├── android
    │   ├── build.gradle
    │   └── src
    │       └── main
    │           ├── AndroidManifest.xml
    │           └── java
    │               └── com
    │                   └── reactlibrary
    │                       ├── RNCardviewModule.java
    │                       └── RNCardviewPackage.java
    ├── index.js
    ├── ios
    │   ├── RNCardview.h
    │   ├── RNCardview.m
    │   ├── RNCardview.podspec
    │   ├── RNCardview.xcodeproj
    │   │   └── project.pbxproj
    │   └── RNCardview.xcworkspace
    │       └── contents.xcworkspacedata
    └── package.json

生成好组件项目后,就能够开始编写实现代码了npm

2 编写代码

编写代码分为三部分,一部分是android原生代码,一部分是iOS原生代码,一部分是react-native(或者javascript)代码。因为react-native-cardview只涉及到android原生模块,因此本篇文章暂不涉及到iOS原生模块开发,若是你们感兴趣,我能够另开一篇文章专门讲一下iOS原生模块相关内容

2.1 编写Android Native Module

编写android原生代码,通常如下三个类是必须的:

2.1.1 RNxxxModule

这个类主要做用是定义原生模块名,能够直接在javascript中经过React.NativeModules.xxx来访问,其中xxx是在RNxxxModule类中定义的getName方法返回值。如下为我组件react-native-cardview中的Module类

RNCardViewModule.java

package com.quenice.reactnative;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback;

public class RNCardViewModule extends ReactContextBaseJavaModule {

  private final ReactApplicationContext reactContext;

  public RNCardViewModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
  }

  @Override
  public String getName() {
    return "RNCardView";
  }
}

2.1.2 RNxxxManager

Manager类主要是组件的原生实现,而且把react-native组件的属性映射到原生属性

RNCardViewManager.java

package com.quenice.reactnative;

import android.graphics.Color;
import android.support.v7.widget.CardView;
import android.view.View;

import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.views.view.ReactViewGroup;

public class RNCardViewManager extends ViewGroupManager<CardView> {
    @Override
    public String getName() {
        return "RNCardView";
    }

    @Override
    protected CardView createViewInstance(ThemedReactContext reactContext) {
        CardView cardView = new CardView(reactContext);
        cardView.setUseCompatPadding(true);
        cardView.setContentPadding(0, 0, 0, 0);
        ReactViewGroup reactViewGroup = new ReactViewGroup(reactContext);
        cardView.addView(reactViewGroup);
        return cardView;
    }

    @ReactProp(name = "cardElevation", defaultFloat = 0f)
    public void setCardElevation(CardView view, float cardElevation) {
        view.setCardElevation(PixelUtil.toPixelFromDIP(cardElevation));
    }
...
}

2.1.3 RNxxxPackage

Package类主要用于注册原生模块、原生组件实现,也就是注册上面的Module和Manager类

RNCardViewPackage.java

package com.quenice.reactnative;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.facebook.react.bridge.JavaScriptModule;
public class RNCardViewPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
      return Arrays.<NativeModule>asList(new RNCardViewModule(reactContext));
    }

    // Deprecated from RN 0.47
    public List<Class<? extends JavaScriptModule>> createJSModules() {
      return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
      return Arrays.<ViewManager>asList(new RNCardViewManager());
    }
}

2.2 编写iOS原生代码

react-native-cardview
iOS的实现方式直接利用react-nativeshadow相关属性就能够实现,因此本文暂不涉及

2.3 编写ReactNative代码

编写好了android/iOS原生模块后,须要编写javascript代码来桥接react-native与原生模块。

RNCardView.android.js

import PropTypes from 'prop-types';
import {requireNativeComponent, View} from 'react-native';

const iface = {
    name: 'CardView',
    propTypes: {
        cardElevation: PropTypes.number,
        maxCardElevation: PropTypes.number,
        backgroundColor: PropTypes.string,
        radius: PropTypes.number,
        ...View.propTypes, // include the default view properties
    },
};

module.exports = requireNativeComponent('RNCardView', iface);

3 代码上传与组件发布

3.1 代码上传到github

编写完代码后,咱们须要把它上传到github上,以后在组件发布到npm的时候也须要用到代码的github地址
。若是你没有作github相关的配置,能够参考我另外一篇文章:安装GIt并配置链接GitHub

执行如下命令把代码同步到你github对应的repository中:

$ git add .
$ git commit -a -m "initial commit"
$ git push -u origin master

同步以后能够到github中看下是否push成功:

https://github.com/YourGithubAccount/YourRepository

3.2 组件发布

开发好组件以后,想在其余的项目(或者提供给其余人安装使用)中经过npm install的方式安装你的组件,那么你的组件必须发布到npm registry中。

3.2.1 npm registry

npm registry 是什么

简单来讲,npm registry就至关于一个包注册管理中心。它管理着全世界的开发者们发布上来的各类插件,同时开发者们能够经过npm install的方式安装所须要的插件。

npm官方registry为:http://registry.npmjs.org/

国内速度较快的为:https://registry.npm.taobao.org/

查看

你能够查看当前使用的registry:

$ npm config get registry

切换

固然也能够经过命令切换当前使用的npm registry

# 全局切换
$ npm config set registry http://registry.npmjs.org/

有时候你可能只想在执行某些npm命令时临时切换,这个时候,可使用--registry来指定临时切换的registry,好比在npm发布

$ npm publish --registry http://registry.npmjs.org/

就能够临时指定,固然,在命令执行结束以后,registry仍然会恢复到原来的registry

3.2.2 建立/登录npm registry帐户

要发布组件到npm registry,你必需要是npm registry的注册用户,经过:

$ npm adduser

来新增一个用户,或者你已经在官网注册了一个用户,能够经过:

$ npm login

来登录npm registry帐户。

利用如下两种方式来确认你是否建立/登录成功npm registry

  1. 命令$ npm whoami确认本地是否成功登录认证成功
  2. 在线打开 https://npmjs.com/~username 查看是否建立帐户成功

3.2.3 发布前准备

3.2.3.1 .gitignore 和 .npmignore

  1. .gitignore中定义哪些文件不上传到github中
  2. .npmignore中定义哪些文件发布时不打包
  3. 若是有.gitignore可是没有.npmignore文件,那么.gitignore能够充当.npmignore的做用
  4. 具体规则能够参照:npm-developers, .gitignore or .npmignore pattern rules

3.2.3.2 package.json

package.json文件定义了发布的全部信息,包括:组件名、版本、做者、描述、依赖等等关键信息。具体能够参照 Working with package.json

下面是react-native-cardview的package.json文件内容:

{
  "name": "react-native-rn-cardview",
  "version": "1.0.0",
  "description": "A ReactNative CardView Component for android and iOS",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "react-native",
    "react-component",
    "react-native-component",
    "react",
    "mobile",
    "ios",
    "android",
    "cardview"
  ],
  "author": {
    "name": "quenice",
    "email": "qiubing.it@gmail.com"
  },
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git@github.com:quenice/react-native-cardview.git"
  },
  "devDependencies": {
    "react": "^16.2.0",
    "react-native": "^0.53.0"
  },
  "peerDependencies": {
    "react": "^16.2.0"
  },
  "dependencies": {
    "prop-types": "^15.6.0"
  }
}

3.2.3.3 编写readme.md

能够在readme.md文件中详细说明组件的使用方法、注意事项等。通常使用Markdown语法来编写

3.2.4 发布

作好以上准备以后,就能够发布了。这里须要注意,首次发布跟后面更新发布是不同的。

首次发布

第一次发布的话,直接执行命令:

$ npm publish

就搞定了,能够在线查看确认是否发布成功。访问连接(<package>是你发布的npm package名):
https://www.npmjs.com/package/<package>
看看是否已经有内容了,有内容说明发布成功了。

更新发布

若是不是首次发布,须要执行两个命令

$ npm version <update_type>
$ npm publish

$ npm version命令是用来自动更新版本号,update_type取值有patch minor major。那么在什么场景应该选择什么update_type呢?看下表

update_type 场景 版本号规则 举例
- 首次发布 版本号1.0.0 1.0.0
patch 修复bug、微小改动时 从版本号第3位开始增量变更 1.0.0 -> 1.0.1
minor 上线新功能,而且对当前版本已有功能模块不影响时 从版本号第2位开始增量变更 1.0.3 -> 1.1.3
major 上线多个新功能模块,而且对当前版本已有功能会有影响时 从版本号第1位开始增量变更 1.0.3 -> 2.0.0

注意

若是首次发布版本号不是1.0.0的话,那么用$ npm version <update_type>
来更新会报错,由于你没有按照它约定的版本规则来,这个时候,你能够手动修改package.json中的version字段为符合约定规则的版本号,而后直接执行$ npm publish就能够,而后下次再增量更新的时候,就能够直接使用$ npm version <update_type>的方式来自动更新版本号了

4 测试

组件从开发到最终发布的过程当中,须要不断进行测试,确保功能正常,那如何进行测试呢?

4.1 建立一个react-native项目

首先咱们建立一个叫作example的react-native项目

$ react-native init example

example项目目录能够和组件项目目录react-native-cardview同级,固然你也能够放在任何你想放的位置,这里为了操做方便,咱们就把两个目录放在同级目录。也就是说,如今的目录是这样

$ tree
.
├── example
└── react-native-cardview

而后咱们要作的就是把本地或者已发布的组件安装到example项目中进行测试

4.2 本地代码测试

在组件未发布以前,咱们能够直接安装本地代码到example项目中进行测试,有如下几种方式均可以作到

4.2.1 yarn link

$ cd react-native-cardview
$ yarn link
$ cd ../example
$ yarn link react-native-cardview
$ react-native link react-native-cardview

说明几点:

  1. yarn link是把当前目录中的本地代码用yarn注册为react-native-cardview的一个本地组件,组件名字react-native-cardview实际上是根据package.json中的name字段的值来的,跟目录名无关,只不过这里正好等于目录名
  2. yarn link react-native-cardview命令是把这个本地组件react-native-cardview安装到了example的项目中,你能够在example/node_modules中找到这个组件
  3. react-native link react-native-cardview这个你们应该知道,就是作了android/iOS的原生模块link
  4. 其实yarn link这种方式简单来讲,就是作了一个symbol link,也就是说,example/node_modules/react-native-cardview/目录中的内容是指向react-native-cardview/目录内容,你改动react-native-cardview/目录下的代码,至关于直接改动example/node_modules/react-native-cardview/这个目录中的代码,这样就可以达到边修改组件代码边看效果的目的了

4.2.2 package.json中配置本地路径

直接在examplepackage.json中增长dependencies

example/package.json

{
  "name":"example",
  ...
  "dependencies": {
    "react-native": "^0.55.4",
    "react-native-cardview":"file:../react-native-cardview",
    ...
  }
  ...
}

而后执行

$ react-native link react-native-cardview

yarn link同样,也至关于作了symbol link,直接修改react-native-cardview/目录下的代码,至关于直接改动example/node_modules/react-native-cardview/这个目录中的代码

4.2.3 直接copy本地代码

这种方式就比较简单粗暴了,直接copyreact-native-cardview/目录中内容到example/node_modules/react-native-cardview/这个目录中

$ cp -rf react-native-cardview/ example/node_modules/

而后执行

$ react-native link react-native-cardview

这种方式缺点就是每次在react-native-cardview/改完代码后,须要手工copy到example/node_modules/react-native-cardview/

4.3 已上传/发布代码测试

已上传到github或者发布到npm registry的组件,测试方式就跟普通咱们安装一个第三方组件同样了。

4.3.1 经过github

加入你的代码经过git上传到了github仓库上,那么,你能够直接经过npm install来安装你的组件

npm install --save https://github.com/quenice/react-native-cardview.git

或者

npm install --save git@github.com:quenice/react-native-cardview.git

注意:根据你本身ghthub上的URL替换以上的HTTPS或者SSH

而后执行

$ react-native link react-native-rn-cardview

4.3.2 经过npm

这种方式就跟按照第三方组件没有区别了

$ npm install --save react-native-rn-cardview

而后执行

$ react-native link react-native-rn-cardview

结语

至此,一个react-native组件完整的开发-测试-发布的生命周期就讲完了。

因为是结合我本身开发的组件react-native-rn-cardview的实际开发过程,因此不免有遗漏,确定也有许多不足的地方。若是你们有什么问题,或者发现哪里有错误,欢迎你们在评论区给我留言,咱们一块儿探讨、一块儿解决。

另外若是在react-native中有须要用到CardView的,欢迎使用react-native-rn-cardview

相关文章
相关标签/搜索