在现有iOS工程加入React-Native

React-Native在iOS工程的集成

当我们想在现有的iOS开发工程中加入React-Native这个模块的时候,我们需要做一些准备工作。<我假设已经安装了homebrew>安装需要的工具:npm

1
brew install npm
一般来说只要有这个就可以,但是鉴于npm 每次都要npm install React-Native并且时间很慢,我们可以辅助使用Yarn,这个工具也是Facebook出品的,这个打React-Native的效率比npm install 高很多。 安装好了npm之后,我们创建一个package.json文件,内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
  "name": "honer",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "update": "echo '{\"presets\":[\"react-native\"],\"plugins\":[\"transform-decorators-legacy\",[\"react-native-css-class\",{\"pragma\":\"CSS\"}]]}' > .babelrc && mkdir bundle && npm i",
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "build": "rm -rf ./bundle/* && react-native bundle --platform ios --entry-file ./ReactComponent/index.ios.js --bundle-output ./bundle/main.jsbundle --assets-dest ./bundle/  --dev false",
    "test": "jest"
  },
  "dependencies": {
    "react": "15.3.2",
    "react-native": "0.36.1"
  },
  "jest": {
    "preset": "jest-react-native"
  },
  "devDependencies": {
    "babel-jest": "16.0.0",
    "babel-plugin-react-native-css-class": "git+https://github.com/qq4647805/babel-plugin-react-native-css-class.git",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-preset-react-native": "1.9.0",
    "jest": "16.0.2",
    "jest-react-native": "16.1.0",
    "react-test-renderer": "15.3.2"
  }
}
通过终端进入工程根目录下,如果这时安装了Yarn。在终端输入yarn,回车一按,自动查找需要安装的packages
1
2
3
4
5
6
7
8
9
10
11
RickdeMacBook-Pro:xueba_ios_2016 Wenba$ yarn
yarn install v0.16.1
info No lockfile found.
[1/4] 🔍  Resolving packages...
warning jest > jest-cli > istanbul-api > fileset > minimatch@2.0.10: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning Unmet peer dependency "whatwg-fetch@^1.0.0".
[4/4] 📃  Building fresh packages...
success Saved lockfile.
✨  Done in 19.62s.
如果没有安装Yarn,安装了npm的话,只要键入 npm install 就会安装packages 然后我们去修改iOS工程的podfile文件,在所在的target多增加这个pod
1
2
3
4
5
6
7
8
pod 'React', :path => './node_modules/react-native', :subspecs => [
  'Core',
  'RCTImage',
  'RCTNetwork',
  'RCTText',
  'RCTWebSocket',
  # Add any other subspecs you want to use in your project
]
在iOS工程目录下执行Pod install。等待安装完成。此时React-Native模块已经加入到我们iOS的工程里了。

在iOS工程使用React-Native。

在工程新建一个ReactView。用于展示React-Native

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@implementation ReactView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"bundle/main" withExtension:@"jsbundle"];
        /*
         For production use, this `NSURL` could instead point to a pre-bundled file on disk:

         NSURL *jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

         To generate that file, run the curl command and add the output to your main Xcode build target:

         curl http://localhost:8081/index.ios.bundle -o main.jsbundle
         */
        _rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"honer" initialProperties:nil launchOptions:nil];
        [self addSubview:_rootView];
    }

    return self;
}


- (void)layoutSubviews {
    [super layoutSubviews];
    _rootView.frame = self.bounds;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/``

@end
在终端输入 (JS_DIR=`pwd`/ReactComponent;cd node_modules/react-native; npm run start -- --root $JS_DIR) 启动React-Native服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
RickdeMacBook-Pro:BestNote Wenba$ (JS_DIR=`pwd`/ReactComponent;cd node_modules/react-native; npm run start -- --root $JS_DIR)

> react-native@0.36.1 start /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote/node_modules/react-native
> /usr/bin/env bash -c './packager/packager.sh "$@" || true' -- "--root" "/Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote/ReactComponent"

(node:14754) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
(node:14754) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
Scanning 717 folders for symlinks in /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote/node_modules (9ms)
 ┌────────────────────────────────────────────────────────────────────────────┐
 │  Running packager on port 8081.                                            │
 │                                                                            │
 │  Keep this packager running while developing on any JS projects. Feel      │
 │  free to close this tab and run your own packager instance if you          │
 │  prefer.                                                                   │
 │                                                                            │
 │  https://github.com/facebook/react-native                                  │
 │                                                                            │
 └────────────────────────────────────────────────────────────────────────────┘
Looking for JS files in
   /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote
   /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote/ReactComponent

[Hot Module Replacement] Server listening on /hot

React packager ready.

[11/15/2016, 1:50:38 PM] <START> Initializing Packager
[11/15/2016, 1:50:38 PM] <START> Building in-memory fs for JavaScript
[11/15/2016, 1:50:38 PM] <END>   Building in-memory fs for JavaScript (173ms)
[11/15/2016, 1:50:38 PM] <START> Building Haste Map
[11/15/2016, 1:50:39 PM] <END>   Building Haste Map (124ms)
[11/15/2016, 1:50:39 PM] <END>   Initializing Packager (365ms)
[11/15/2016, 1:50:42 PM] <START> Requesting bundle: {"url":"/index.ios.bundle?platform=ios"}
[11/15/2016, 1:50:42 PM] <START> Transforming modules
transformed 662/662 (100%)
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://10.88.1.90:8081/index.ios.bundle?platform=ios"];这个IP是开启服务的电脑IP。(JS_DIR=`pwd`/ReactComponent;cd node_modules/react-native; npm run start -- --root $JS_DIR)定义的JSDir会在这两个目录下去查找js文件
1
2
   /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote
   /Users/Rick/Documents/Work/ChatDemo/ReactNative/BestNote/ReactComponent
我们在ReactComponent这个目录下放入index.ios.js文件。文件内容如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React, { Component } from 'react'
import {
  AppRegistry,
  Text
} from 'react-native';
import Main from './src/main.js'

class myhonor extends Component {
  render() {
    return (
      <Main></Main>
    );
  }
}
AppRegistry.registerComponent('honer', () => myhonor);
在这里注册组件honer,我们在ReactView类中找到这个honer模块去使用。 此时我们运行我们的工程会发现运行ok的


离线包

加载需要时间,此时页面是空白,不好,建议将资源以及页面都打包成离线包,这样不用每次都连网去请求页面。如果有新的页面更换,可以先加载旧的页面,在渲染成新页面。


我们在终端输入

1
2
3
4
5
6
react-native bundle \
--platform ios \
--entry-file index.ios2.js \
--bundle-output ./main.jsbundle \
--assets-dest ./ \
--dev true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RickdeMacBook-Pro:BestNote Wenba$ react-native bundle --platform ios --dev false --entry-file ./ReactComponent/index.ios.js --bundle-output main.jsbundle --assets-dest ./Bundle
(node:16763) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
(node:16763) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
[11/15/2016, 2:28:17 PM] <START> Initializing Packager
[11/15/2016, 2:28:17 PM] <START> Building in-memory fs for JavaScript
[11/15/2016, 2:28:17 PM] <END>   Building in-memory fs for JavaScript (165ms)
[11/15/2016, 2:28:17 PM] <START> Building Haste Map
[11/15/2016, 2:28:17 PM] <END>   Building Haste Map (226ms)
[11/15/2016, 2:28:17 PM] <END>   Initializing Packager (463ms)
[11/15/2016, 2:28:17 PM] <START> Transforming modules
[11/15/2016, 2:28:25 PM] <END>   Transforming modules (7758ms)
bundle: start
bundle: finish
bundle: Writing bundle output to: main.jsbundle
bundle: Done writing bundle output
bundle: Copying 15 asset files
bundle: Done copying assets
将我们的js文件打包成bundle,同事将资源文件也打包起来,如果–assets-dest ./ 这个参数不加,会导致我们页面的img图片资源缺失。这个有点坑。

Comments