中写一个自定义模块,本领树点亮安排

来源:http://www.smjxgs.com 作者:王中王鉄算盘 人气:168 发布时间:2019-09-15
摘要:@author ASCE1885的 Github 简书 微博 CSDN知乎 本文由于潜在的商业目的,不开放全文转载许可,谢谢! 前言 在 React Native 项目中可以看到 node_modules 文件夹,这是存放 node模块的地方,Node.j

@author ASCE1885的 Github 简书 微博 CSDN 知乎本文由于潜在的商业目的,不开放全文转载许可,谢谢!

前言

在 React Native 项目中可以看到 node_modules 文件夹,这是存放 node 模块的地方,Node.js 的包管理器 npm 是全球最大的开源库生态系统。提到npm,一般指两层含义:一是 Node.js 开放式模块登记和管理系统,另一种是 Node.js 默认的模块管理器,是一个命令行软件,用来安装和管理 node 模块。本文旨在探讨如何在 React Native 中写一个自定义的 npm 模块(类似于插件),并上传到 npm 上供他人使用。

常识

图片 1image_1akdbc4t86e41r17s2518obtgb13.png-1421.1kB

npm 使用介绍

npm 是一个 Node.js 模块,安装 Node.js 会默认安装 npm,可以在终端中使用以下命令来查看 npm 的版本:

npm -v

升级 npm:

sudo npm install npm -g

安装模块(安装完毕后会产生一个node_modules目录,其目录下就是安装的各个node模块):

npm install <ModuleName>

查看 npm 配置:

npm config list

设置代理:

//设置 http 代理
npm config set proxy http://server:port
//设置 https 代理
npm config set https-proxy http://server:port 

上面介绍了一些 npm 基本命令,接下来就可以在本地创建一个模块啦。
首先打开终端中新建一个你想在此创建自定义模块的文件夹,然后在命令行中登录 npm。输入以下命令:

npm adduser

接下来会提示你输入用户名和密码还有邮箱,一一完成后就可以输入以下命令来查看当前 npm 用户了:

npm whoami

如果正确显示了刚才注册的用户名,说明登录成功了。然后就使用以下命令来创建 npm 模块:

npm init

执行上述命令后,会引导你创建一个package.json文件,包括名称、版本、作者这些信息等。

React native 开发服务器

在开发时,我们的框架是这样的:
图片 2

当正式发布进入到生产环境时,开发服务器上所有的js文件将会被编译成包的形式,直接嵌入到客户端内。这时,已经不再需要开发服务器的支持了。

广而告之时间:我的新书《Android 高级进阶》( )在京东开始预售了,欢迎订购!

创建模块

这里要提一下,为什么要写一个自定义模块。因为 React Native 虽然实现了很多 Native 组件,并且提供了丰富的 API,但是有些原生库还是不支持的,而且有很多开源的组件和库是面向原生的,因此要想在 React Native 中使用这些组件和库就需要自己定义一个模块,这样也方便别人集成。接下来我们直接进入正题。写一个 React Native 中可以使用的自定义模块。在命令行中执行

react-native init AwesomeProject

初始化一个 React Native 项目。这里以 Android 为例,用 Android Studio 选择菜单 File->open 打开 AwesomeProject 文件夹下的 android 文件夹,然后选择 File -> New -> New Module,选择创建一个 Android Library,如图:

图片 3

如图所示,这里新建了一个 Library module,接下来点击 finish 就可以看到如下的目录结构:

图片 4

然后将所需要依赖的 jar 放到 libs 目录下,这里以使用 jpush-sdk 为例,将官网上下载的 libs 复制到 libs 下,把相关的资源文件放到 res 文件夹下,再把 AndroidManifest 文件内容复制过来,更改一下包名,最后在 build.gradle 中配置一把,如下(这里要注意把 targetSdkVersion 改成 22,在23上运行可能会闪退):

apply plugin: 'com.android.library'
android {    
  compileSdkVersion 23    
  buildToolsVersion "23.0.2"    
  defaultConfig {        
    minSdkVersion 16        
    targetSdkVersion 22        
    versionCode 1        
    versionName "1.0"        
    manifestPlaceholders = [                
      JPUSH_APPKEY: "yourAppKey",  //在此修改JPush的AppKey                    
      APP_CHANNEL: "developer-default"      //应用渠道号        
    ]    
  }    
  lintOptions {        
    abortOnError false        
    warning 'InvalidPackage'    
  }    
  sourceSets {        
    main {            
      jniLibs.srcDirs = ['libs']        
    }    
}
}
repositories {    
  mavenCentral()
}

dependencies {    
  compile fileTree(dir: 'libs', include: ['*.jar'])    
  compile "com.facebook.react:react-native: "
}

到此为止,我们已经完成了第一步操作,接下来需要写 Native 和 JS 交互的代码,可以参考我的这篇文章中 JS 调用 Native 以及 Native 调用 JS 部分,这里不再赘述。假设我们已经完成了 Native 部分代码,我们如何才能在 JS 中让他人能够通过 import 的方式调用我们的 JS 代码,从而调用 Native 呢?首先进入 my-react-library 文件夹,然后在终端执行

npm init

生成 package.json 文件(注意这里的 name 字段,这里是别人引用你的模块的名字),然后再创建一个 index.js 文件,这是 node 模块的 JS 入口,这里推荐使用 Sublime Text 进行 JS 的编写。这里以 jpush-react-native 为例:

jpush-react-native/index.js 部分代码

import {NativeModules, Platform, DeviceEventEmitter} from 'react-native';

// 通过 NativeModules 找到我们在 Native 定义的 JPushModule 类
const JPushModule = NativeModules.JPushModule;

export default class JPush {

    /**
     * Android only
     * 初始化JPush 必须先初始化才能执行其他操作
    */
    static initPush() {
        JPushModule.initPush();
    }
}

上面定义了一个 initPush 方法,initPush 实际上调用了 JPushModule 中定义的 initPush 方法,其他方法与此类似,本质上都是通过 NativeModules 调用了 Native 提供的方法。

npm

npm,全称是 node package manager,顾名思义最开始是作为 Node 的包管理器存在的。不过经过不断的发展和壮大,现在的 npm 早就不再局限于 Node 的范畴,已经成为 Javascript 的包管理器,看看下面的 npm
常见命令:

npm install -g react-native-cli
安装 react native 命令行搭建

图片 5TB2MnqlXH1J.eBjSszcXXbFzVXa_!!1020536390.png-39kB

发布

到此为止,我们已经完成了 React Native 自定义模块。现在可以发布我们的自定义模块了。在 package.json 所在的目录下执行

npm publish

就可以把我们的自定义模块上传到 npm 库了。每次更新版本时,需要改动 package.json 中的 version 值,然后再执行 npm publish 即可。

React Native 命令行环境搭建困难

npm install -g react-native-cli

这是在从npm服务器上拉取react-native-cli。所以慢的原因便是因为npm服务器不在国内。聪明的国人已给出了解决办法,通过FQ来解决此问题。更高兴的是npm提供了一个register的属性,可以让开发者自由的设置镜像地址。开发者们最常用的便是淘宝的镜像地址。据统计国内比较常用的镜像地址有:

http://r.cnpmjs.org/
http://registry.npm.taobao.org/
http://registry.npmjs.eu/
http://registry.npmjs.org.au/
http://npm.strongloop.com/
https://registry.nodejitsu.com/
http://registry.npmjs.pt/

npm,全称是 node package manager,顾名思义最开始是作为 Node 的包管理器存在的。不过经过不断的发展和壮大,现在的 npm 早就不再局限于 Node 的范畴,已经成为 Javascript 的包管理器,看看下面的 npm 官网首页介绍就知道了:

使用

在 React Native 目录下,执行:

npm install my-react-library --save

安装完成后就会把这个模块保存到 node_modules 文件夹下,由于我们的模块是一个 Android Library 项目,所以在 Native 中还需要配置一下。主要是添加项目依赖:

someone's react-native project/some module/build.gradle

dependencies {    
  compile fileTree(dir: "libs", include: ["*.jar"])    
  compile "com.android.support:appcompat-v7:23.0.1"    
  compile "com.facebook.react:react-native: "  // From node_modules   
  // 在 dependecies 中加入自定义模块 
  compile project(':my-react-library')
}

然后在 settings.gradle 中也要配置一下:

someone's react-native project/settings.gradle

include ':app', ':my-react-library'
project(':my-react-library').projectDir = new File(rootProject.projectDir, '../node_modules/my-react-library/android')

在 MainActivity 中将自定义的 Package 添加进去:

MainActivity.java

...
mReactInstanceManager = ReactInstanceManager.builder()                
.setApplication(getApplication())                
.setBundleAssetName("index.android.bundle")                
.setJSMainModuleName("react-native-android/index.android")                
.addPackage(new MainReactPackage())
//添加自定义的 package
.addPackage(new MyReactPackage())
...

如果是 RN 0.29.0 以上版本,则应在 MainApplication 中添加:

MainApplication.java

@Overrideprotected List<ReactPackage> getPackages() {    
return Arrays.<ReactPackage>asList(            
    new MainReactPackage(),            
    new MyReactPackage()    
  );
}

到此为止我们完成了 Native 部分的配置(完成后 sync 一下),接下来就可以使用了。
别人要使用我们的模块时,就可以这样写:

someone.js

//这里的 'my-react-library'是在 package.json 定义的 name
// 这样就可以
import MyModule from 'my-react-library'

export default class SomeClass  extends React.Component {
    componentDidMount() {
      // 调用 index.js 中定义的 doSomething()
      MyModule.doSomething();
    }
}

package.json 的文件结构

一个合格的 package.json 文件需要至少包含 name 和 version 两个字段,这两个字段组成的二元组可以唯一标识一个包,如下所示:

{
  "name": "AwesomeProject",
  "version": "0.0.1"
}
字段名 含义 示例
name 包名需要具备唯一性 "name": "redux"
version 包的版本号,遵循语义化版本(http://semver.org/lang/zh-CN/)格式,也就是版本号包含三位:MAJOR.MINOR.PATCH。MAJOR 表示版本发生大的变化,例如 API 不兼容旧版本;MINOR 表示版本增加新功能,但是兼容旧版本的;PATCH 表示兼容旧版本的一些 bug 修复 "version": "3.5.2"
description 项目的描述,尽量保持言简意赅 "description": "Predictable state container for JavaScript apps"
dependencies 这个 Package 的生产依赖,当用户安装你的 Package 时会自动安装这些依赖 "dependencies": { "react": "15.1.0", "react-native": "0.27.0-rc2" }
private 设置为 true 时,npm 将不会发布这个 Package,这个标记主要用来防止不小心发布某个内部使用的私有 Package 到公共的 npm registry "private": true

目前这些已经足够,如果需要更多,请查看此链接

图片 6image_1ak5a6lts1i7t1taee9t12djb599.png-313.4kB

初始化React Native环境

在我们要配置React Native环境的项目中,进入到*.xcodeproj文件的上级目录,运行React Native初始化react-native init [Project Name]
这样会在ios目录下生成一个同名工程,接下来我们需要把这个同名工程的配置迁移到现有项目。

本系列教程假设你已经按照 React Native 官方入门指南安装好相关的环境(尤其是 Node.js),并且执行 react-native init AwesomeProject 命令生成了 Demo 工程 AwesomeProject,工程目录结构如下图所示:

链接React Native的Libraries

查看ios目录下的那个同名工程,会看到这个工程引用的React Native库如下:
图片 7

在开发过程中如果需要其他组件,也以相同方式加入到项目中。具体操作如下:

  1. 右键项目目录,选择New Group,新建一个名为Libraries的逻辑目录;
  2. 在node modules目录中找到$root_path/node_modules/react-native/Libraries,React Native的所有库都是以static library的形式提供;
  3. 将对应的.project文件拖入到Libraries逻辑目录下,效果如上图所示;
  4. 在Build Phase中link刚才添加的库; 图片 8

图片 9image_1ak5eb3u0h5u1gandlpjle1e1v9.png-151.2kB

清理多余文件

删除ios/和android/下的文件,这些是init命令自动生成的。

  • 出现问题1 :引入工程里要添加 -ObjC

图片 10

从上图中可以看到,AwesomeProject 工程的根目录有一个名为 package.json 的文件,它是工程的元数据集,主要作用有:

应该如何做

node_modules中包含两个部分代码, JS代码和原生代码(OC和Java). 实际上, 只有原生代码需要加入原生项目中编译, 而JS代码只用于打包bundle. 这样意味着, 我们可以将node_modules分成两个部分, 原生代码可以随原生项目的SVN/Git进行版本控制, 而JS部分可以通过npm的package.json进行版本控制. 这样, 原生开发同学不需要下载node_modules, 也可以对RN的源码进行修改, 而RN开发同学也可以享受版本控制的好处.

  • 管理项目中依赖的第三方包,可以很方便的和团队中其他开发者共享工程的依赖配置,这样不需要每个人都手动 npm install 相应的依赖包
  • 定义 npm 中可以执行的脚本

具体步骤

  • 步骤1

获取你所需要的RN版本(node_modules).
如在命令行输入react-native init AwesomeProject, 得到最新版的RN. 获取AwesomeProject中的package.json和node_modules. 将二者置于与原生项目文件夹平级的地方. 即与iOS和Android文件夹平级之处, 方便双平台使用.

  • 步骤2

拷贝node_modules/react-native文件夹至原生项目中, iOS项目保留Libraries文件夹和React文件夹(安卓项目保留ReactAndroid文件夹). 其余所有删除.

  • 步骤3

iOS项目, 创建Group,放置RN工程项目:

/node_modules/react-native/React/React.xcodeproj
/node_modules/react-native/Libraries/Text/RCTText.xcodeproj
/node_modules/react-native/Libraries/WebSocket/RCT WebSocket.xcodeproj

你需要用到哪些就加哪些. 全部加上也无妨.

  • 步骤4

Build Rules中添加静态库文件.
如libRCTText.a等. libRCT开头的都加上.

  • 步骤5

Build Settings添加循环依赖
在Targets-Build Settings-Header Search Paths中加入$(PROJECT_DIR)/项目名/ReactNative/react-native/React 这里要加入的是react-native/React文件夹的路径, 我的react-native文件夹位于项目名/ReactNative下,因此是这样写.

  • 步骤6

设置Other Linker Flags
Targets-Build Settings-Other Linker Flags中加入-ObjC

  • 步骤7

删除原生项目中步骤2拷贝过来的react-native文件夹中所有JS文件. 这步本可以和步骤2合为1步,单独列出的原因是: 如果没有删除其中的JS文件, 其中的JS代码@providesModuleprovide了很多Module, 会与你在步骤1中的node_modules中的代码冲突.

  • 步骤8

删除启动node服务脚本.
打开步骤3中引入的RN工程项目:React.xcodeproj-Targets-Build Phases-Run Script. 删除启动node服务脚本的那个脚本. 即内容是
if nc -w 5 -z localhost 8081 ; then if ! curl -s "http://localhost:8081/status" | grep -q "packager-status:running" ; then echo "Port 8081 already in use, packager is either not running or not running correctly" exit 2 fi else open "$SRCROOT/../packager/launchPackager.command" || echo "Can't start packager automatically" fi的脚本

  • 步骤9

随原生项目上传react-native文件夹, 此时react-native文件夹中只有原生代码, 可以进行版本控制;
修改package.json, 修改你需要的内容(如修改dependencies, 将某些组件固定在某个版本), 之后用package.json控制更新node_modules.
package.json也上传SVN, 大家共用这个管理node_modules.

  • 步骤10

打开命令行, 进入与项目平级的目录(即node_modules所在目录), 输入npm start. 启动node服务.
打开XCode/Android Studio, 进入RN开发.

小细节

iOS真机调试, 需要将localHost改为本机的ip, 同时手机要与电脑处于同一wifi下.
如果要真机chrome debug, 要修改RCTWebSocketExecutor.m中setup函数的URLString的localHost.
Android真机调试就是adb reverse tcp:8081 tcp:8081

一个合格的 package.json 文件需要至少包含 nameversion 两个字段,这两个字段组成的二元组可以唯一标识一个包,如下所示:

参考

  • react native开发服务器 服务器安装
  • React Native入门实例教程 - 从现有项目迁移
  • 在已有项目中接入React Native
  • iOS现有项目集成React Native
{ "name": "AwesomeProject", "version": "0.0.1"}

当然一般情况下,工程的 package.json 不可能这么简单,常用的字段和解释如下表所示,开发者需要根据具体的业务需求进行选择:

字段名 含义 示例
name 包名需要具备唯一性,而且字母必须全部小写,如果一个包缺少这个字段,使用 npm install 将会失败 "name": "redux"
version 包的版本号,遵循语义化版本(http://semver.org/lang/zh-CN/)格式,也就是版本号包含三位:MAJOR.MINOR.PATCHMAJOR 表示版本发生大的变化,例如 API 不兼容旧版本;MINOR 表示版本增加新功能,但是兼容旧版本的;PATCH 表示兼容旧版本的一些 bug 修复 "version": "3.5.2"
description 项目的描述,尽量保持言简意赅 "description": "Predictable state container for JavaScript apps"
author 项目的作者名字和邮件地址,如果有多个,以 JSON 数组形式表示 "authors": ["Dan Abramov dan.abramov@me.com(https://github.com/gaearon)","Andrew Clark acdlite@me.com(https://github.com/acdlite)"]
contributors 项目的贡献者名单,以 JSON 数组的形式表示 "contributors": [{"name": "asce1885","email": "asce1885@gmail.com"}]
bin 项目对外暴露的 CLI 接口,提供给其他项目使用的脚本 "bin": {"module-name":"./bin/module-name"}
scripts 定义 npm 脚本命令,key 值表示命令名,value 值表示命令对应的脚本或者脚本的路径,通过 npm run 或者 npm run-script 可以执行对应的命令 "scripts": { "clean": "rimraf lib dist es coverage", "lint": "eslint src test examples build", "start": "node node_modules/react-native/local-cli/cli.js start"
main 工程生成的 Package 的主入口点,当在 node 中调用 require('{module name}') 时会 require 到这个文件 "main": "lib/index.js"
repostitory 如果我们这个工程是开源的,这个字段用来指明工程的仓库 URL 地址以及版本控制系统的类型,这可以方便其他开发者贡献代码 "repository": { "type": "git", "url": "https://github.com/reactjs/redux.git" }
bugs 使用者可以提交bugs的 URL 或者邮件地址 "bugs": {"url": "https://github.com/reactjs/redux/issues"}
keywords 描述这个 Package 的关键字信息,方便用户通过关键字搜索到这个 Package "keywords": ["redux","reducer","state","predictable","functional","immutable","hot","live","replay","flux","elm"]
dependencies 这个 Package 的生产依赖,当用户安装你的 Package 时会自动安装这些依赖 "dependencies": { "react": "^15.1.0", "react-native": "^0.27.0-rc2" }
devDependencies 这个 Package 在开发或者测试阶段的依赖,不会打包到最终的生产包中 "devDependencies": { "babel-eslint": "^5.0.0", "eslint": "^2.1.0", "eslint-plugin-react": "^3.16.1" }
preferGlobal 表明这个 Package 希望通过 npm install -g {module-name} 全局安装,这个字段是给包含了 CLI 的 Package 使用, 其他情况下不要使用这个字段 "preferGlobal": true
private 设置为 true 时,npm 将不会发布这个 Package,这个标记主要用来防止不小心发布某个内部使用的私有 Package 到公共的 npm registry "private": true
publishConfig 发布这个 Package 时用到的一些配置信息,这些配置信息会覆盖默认的 npm 配置 "publishConfig": { "registry": "https://your-private-hosted-npm.registry.nodejitsu.com" }
subdomain 指明应用的 subdomain,说明应该只包含 subdomain,而不是 root domain
analyze 如果你的 Package 托管在 Nodejitsu(https://www.nodejitsu.com/) 上面,同时将这个字段设置为 true,Nodejitsu 将会自动尝试扫描你的 Package,可以及时发现缺少的依赖,可能存在的 bugs 以及语法错误等 "analyze": true
license 如果这个 Package 是开源的,此处指定它遵循的许可协议 "license": "MIT"

一个真实项目的 Package.json 文件内容如下所示(取自 redux-logger[1])

{ "name": "redux-logger", "version": "2.6.1", "description": "Logger for Redux", "main": "lib/index.js", "scripts": { "lint": "$/eslint src", "test": "npm run lint", "clean": "$/rimraf dist lib", "build:lib": "$/babel src --out-dir lib", "build:umd": "LIBRARY_NAME=reduxLogger NODE_ENV=development $/webpack src/index.js dist/index.js --config webpack.build.js", "build:umd:min": "LIBRARY_NAME=reduxLogger NODE_ENV=production $/webpack -p src/index.js dist/index.min.js --config webpack.build.js", "build": "npm run build:lib && npm run build:umd && npm run build:umd:min", "prepublish": "npm run clean && npm run test && npm run build" }, "files": [ "dist", "lib", "src" ], "repository": { "type": "git", "url": "git https://github.com/theaqua/redux-logger.git" }, "keywords": [ "redux", "logger", "redux-logger", "redux", "middleware" ], "author": "Eugene Rodionov (https://github.com/theaqua)", "license": "MIT", "bugs": { "url": "https://github.com/theaqua/redux-logger/issues" }, "homepage": "https://github.com/theaqua/redux-logger#readme", "devDependencies": { "@dtrussia/eslint-config-dtrussia": "2.2.1", "babel-cli": "6.3.13", "babel-core": "6.3.13", "babel-eslint": "6.0.4", "babel-loader": "6.2.0", "babel-plugin-add-module-exports": "0.1.1", "babel-preset-es2015": "6.3.13", "babel-preset-react": "6.3.13", "babel-preset-stage-0": "6.3.13", "eslint": "2.10.2", "eslint-plugin-react": "5.1.1", "rimraf": "2.4.4", "webpack": "1.12.9" }, "dependencies": { "deep-diff": "0.3.4" }}

熟悉 npm 的常用命令,往往能够使得你的工作事半功倍。首先我们来介绍最常用的 npm install 命令,它是用来将依赖的模块安装到 node_modules 目录中,依赖分为两种:生产环境的依赖和开发环境的依赖,这个在前面一节已经介绍过了,对应的命令分别如下所示:

npm install redux // 生产环境的依赖npm install redux -dev // 开发环境的依赖

在安装之前,npm 会先检查 node_modules 目录中是否已经存在指定的模块,如果存在,则不会重新安装,即使这个模块已经有新版本。当然,我们可以通过增加 -f 或者 --force 参数来强制重新安装最新版本。上面的命令安装完成后,我们可以在 node_modules 目录中找到 redux 的包,但这时 package.json 文件内容并没有发生变化,为了在发布我们这个包给其他开发者使用时,他们可以自动安装这些依赖,我们需要将依赖写入 package.json 文件中,当然你可以选择手动写入,但更方便的方法是在 npm install 时增加 --save 参数,如下所示:

npm install redux --save // 生产环境的依赖npm install redux --save-dev // 开发环境的依赖

这时 npm 会自动帮我们写入 package.json 文件,如下所示:

{ ... "dependencies": { ... "redux": "^3.5.2" }, "devDependencies": { "eslint": "^2.11.1" }}

有了依赖的安装,当然也有卸载的命令,很简单就是 npm uninstall,后面参数是需要卸载的包名,例如 npm uninstall redux

前面使用 React Native 提供的 react-native init AwesomeProject 命令生成的 Demo 工程已经自动帮我们生成了 package.json 文件,如果我们自己手动建立一个 React Native 的工程,那么可以选择从其他工程拷贝现成的 package.json 并进行修改,当正确的做法是使用 npm init 命令来生成它。在 Terminal 中输入 npm init,npm 将会一步一步引导我们输入一些关键的字段,最终生成的文件内容如下所示,从中看到的字段几乎是每个工程必备的:

{ "name": "asce1885", "version": "1.0.0", "description": "One Piece", "main": "index.js", "scripts": { "test": "op" }, "repository": { "type": "git", "url": "git https://github.com/PaicHyperionDev/MobileDevWeekly.git" }, "keywords": [ "mobile", "dev" ], "author": "asce1885", "license": "MIT", "bugs": { "url": "https://github.com/PaicHyperionDev/MobileDevWeekly/issues" }, "homepage": "https://github.com/PaicHyperionDev/MobileDevWeekly#readme"}

当某个第三方依赖库需要发布新版本,我们项目也需要跟着升级时,可以通过 npm update 命令对指定的 Package 进行升级,例如 npm update redux。同时,我们可以通过执行命令 npm outdated 来查询当前安装的所有 npm 包中是否有存在新版本的。

一般来说,掌握上面几个命令,对开发 React Native 来说就已经足够了,对于不熟悉的命令,我们可以通过 npm help 来查询对应命令的用法,例如输入 npm help registry,会得到如下结果:

图片 11image_1akd8q4b8nr8124l1jli1q3sj4im.png-221.9kB

上一节我们介绍了 npm 的模块管理功能,事实上,npm 另外一个高频使用的功能就是用来执行脚本。我们在 package.json 文件的 scripts 字段中定义的脚本可以通过 npm run 或者 npm run-script 执行,例如在 React Native 工程中,我们可以定义如下脚本,分别用来创建,启动 Android 模拟器,启动 node 服务和打包等:

"scripts": { "avd:create": "android create avd -t 1 -n MuchVote -d 9 -b x86_64 -s 1440x2560", "avd:start": "emulator -avd MuchVote -gpu on -dpi-device 560 -scale ${SCALE:-0.25}", "adb:reverse": "adb reverse tcp:8081 tcp:8081", "android": "npm run adb:reverse && node node_modules/react-native/local-cli/cli.js run-android", "start": "npm run adb:reverse && node_modules/react-native/packager/packager.sh", }

定义完成之后,就可以在 React Native 目录中像下面这样执行对应的命令:

npm run adb:reversenpm run android...

为了方便脚本的执行,npm 默认定义了一些命令的快捷键,例如 npm testnpm startnpm stop 等等,也就是说执行这些命令时,我们省去了 run 的输入。之所以定义这些快捷键,除了可以节省执行命令的时间,更重要的一点是这些命令的命名是通用的约定,很多持续构建平台例如 Travis 会默认为 Node.js 工程添加 npm test 命令;同时,这些通用的命令定义也方便其他开发者使用你的包。

npm 为每一条命令都提供了 pre--post 这两个钩子,分别表示在命令执行前和执行后会执行对应的钩子命令。例如下面的脚本,当用户执行 npm run test 命令时,事实上 npm 会先执行 pretest 命令,然后才执行 test 命令。

"scripts": { "eslint": "eslint --rulesdir **", "test": "mocha test/", "pretest": "npm run eslint" }

当一个命令比较复杂时,我们还可以将这个命令定义在一个单独的 js 文件中,然后通过 node 来执行,如下所示:

"scripts": { "build": "node build.js"}

本系列关于 npm 的介绍就到这里,基本上对开发 React Native 已经足够用了,如果你不满足于这些基础知识,可以查阅拓展阅读部分的文档,进一步学习。

拓展阅读

《npm 官方文档》[2]《我为何放弃 Gulp 与 Grunt,转投 npm scripts》上[3] 中[4] 下[5]《Introduction to Using NPM as a Build Tool》[6]《How to Use npm as a Build Tool》[7]《package.json》[8]《玩转 npm》[9]《玩转 npm》[10]《npm 模块安装机制简介》[11]

欢迎关注我的微信公众号,专注与原创或者分享 Android,iOS,ReactNative,Web 前端移动开发领域高质量文章,主要包括业界最新动态,前沿技术趋势,开源函数库与工具等。

图片 12

本文由4887王中王鉄算盘奖结果发布于王中王鉄算盘,转载请注明出处:中写一个自定义模块,本领树点亮安排

关键词:

最火资讯