React Native GUIDE

597 views

Published on

React Native 入門用の話がそこそこ
裏側を覗く部分がメインです
以下のコードの解説をしています
- react-native init
- react-native run-ios

Published in: Engineering
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
597
On SlideShare
0
From Embeds
0
Number of Embeds
136
Actions
Shares
0
Downloads
7
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

React Native GUIDE

  1. 1. React Native GUIDE ⼊⾨からその裏側まで覗いてみよう
  2. 2. About Me
  3. 3. ビズリーチ・ キャンパス 学⽣、OB/OG 向けサイト • Java8+Spring Boot (Thymeleaf) • ES2015+KnockoutJS 社内管理者向けサイト • Java8+Spring Boot • ES2015+React(+Redux) アプリ • Java8+Spring Boot • Swift
  4. 4. React とは
  5. 5. React とは 1/3 https://facebook.github.io/react/ Facebook 製 • UI 構築⽤の JavaScript ライブラリ • Declarative(宣⾔的) – アプリの状態に応じたインタラクティブ な UI を簡単に構築できる – コードもわかりやすい • Component-Based – いわゆるコンポーネント(部品)指向 – ⾃分⾃⾝の状態も管理する • Learn Once,Write Anywhere – これだけ覚えればサーバサイドもスマホ アプリも OK
  6. 6. React とは 2/3 https://speakerdeck.com/katamu ki/es2015-react-dot-jswoxue-bu 弊社のおっさんが学んだ話(宣伝) • コンポーネントを組み合わせて構築す るコンポーネント指向の View ライブ ラリ • Facebook、インスタ、Yahoo!、 Airbnb などでも使われている • VirtualDOMを⽤いた画⾯の差分描画を ⾏い⾼速な画⾯表⽰を提供する
  7. 7. React とは 3/3 https://facebook.github.io/react/t utorial/tutorial.html • Tutorial おすすめ • ポイント – ES2015 – React.Component – this.prop – this.state – componentXXXMount • ES2015 は以下ざっと読んでおくのが おすすめ – http://postd.cc/es6-cheatsheet/ – 「...」とか検索難易度⾼すぎる
  8. 8. React Native とは
  9. 9. React Native とは 1/3 https://facebook.github.io/react- native/ Facebook 製 • ネイティブアプリを JavaScript と React を使⽤して構築できる • ちゃんとサクサク動く本当のスマホア プリが作れる • (アプリなのに)ホットリローディン グでさくさく開発できる • Native コードも使える
  10. 10. React Native とは 2/3 https://facebook.github.io/react- native/docs/getting- started.html#content アプリ⽤のコンポネントを確認して おくと効率が良い • こちらも Getting started から Tutorial がおすすめ
  11. 11. React Native とは 3/3 http://www.slideshare.net/TadeuZagallo/a-tour- of-react-native?qid=ddc291a4-7988-46dc- b086-9cf3c92a7235&v=&b=&from_search=4 メリットとか • 今後ますますアプリの需要は⾼まって いく • Android と iPhone で 70% 〜 90% コードを共有可能 • ネイティブの勉強をゴリッとやらない で良い
  12. 12. Question
  13. 13. React Native の裏側を覗く
  14. 14. React Native の裏側を覗く https://facebook.github.io/react- native/docs/getting- started.html#content Getting Started • ⾊々インストール – node – watchman – react-native-cli – … • 初期化 • 起動 react-native init AwesomeProject react-native run-ios
  15. 15. React Native の裏側を覗く 初期化処理を react-native init からみてみる
  16. 16. React Native の裏側を覗く view `which react-native`
  17. 17. React Native の裏側を覗く switch (commands[0]) { case 'init': if (!commands[1]) { console.error( 'Usage: react-native init <ProjectName> [--verbose]' ); process.exit(1); } else { init(commands[1], argv.verbose, argv.version); } break; default: ...
  18. 18. React Native の裏側を覗く function init(name, verbose, rnPackage) { validatePackageName(name); if (fs.existsSync(name)) { createAfterConfirmation(name, verbose, rnPackage); } else { createProject(name, verbose, rnPackage); } }
  19. 19. React Native の裏側を覗く function createProject(name, verbose, rnPackage) { var root = path.resolve(name); var projectName = path.basename(root); console.log( 'This will walk you through creating a new React Native project in', root ); if (!fs.existsSync(root)) { fs.mkdirSync(root); } ・・・
  20. 20. React Native の裏側を覗く ・・・ var packageJson = { name: projectName, version: '0.0.1', private: true, scripts: { start: 'node node_modules/react-native/local-cli/cli.js start' } }; fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(packageJson)); process.chdir(root); console.log('Installing react-native package from npm...'); ・・・
  21. 21. React Native の裏側を覗く ・・・ if (verbose) { runVerbose(root, projectName, rnPackage); } else { run(root, projectName, rnPackage); } }
  22. 22. React Native の裏側を覗く function run(root, projectName, rnPackage) { exec('npm install --save --save-exact ' + getInstallPackage(rnPackage), function(e, stdout, stderr) { if (e) { console.log(stdout); console.error(stderr); console.error('`npm install --save --save-exact react-native` failed'); process.exit(1); } checkNodeVersion(); var cli = require(CLI_MODULE_PATH()); cli.init(root, projectName); }); }
  23. 23. React Native の裏側を覗く view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/cli.js
  24. 24. React Native の裏側を覗く /** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ 'use strict'; require('./packager/babelRegisterOnly')([ /private-cli¥/src/ ]); module.exports = require('./local-cli/cli.js');
  25. 25. React Native の裏側を覗く view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/cli.js
  26. 26. React Native の裏側を覗く ・・・ var cliEntry = require('./cliEntry'); if (require.main === module) { cliEntry.run(); } module.exports = cliEntry;
  27. 27. たらい回し
  28. 28. React Native の裏側を覗く view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/cliEntry.js
  29. 29. React Native の裏側を覗く ・・・ const init = require('./init/init'); ・・・ module.exports = { run: run, init: init, };
  30. 30. React Native の裏側を覗く これ! function run(root, projectName, rnPackage) { exec('npm install --save --save-exact ' + getInstallPackage(rnPackage), function(e, stdout, stderr) { if (e) { console.log(stdout); console.error(stderr); console.error('`npm install --save --save-exact react-native` failed'); process.exit(1); } checkNodeVersion(); var cli = require(CLI_MODULE_PATH()); cli.init(root, projectName); }); }
  31. 31. React Native の裏側を覗く view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/init/init.js
  32. 32. React Native の裏側を覗く /** * Creates the template for a React Native project given the provided * parameters: * @param projectDir Templates will be copied here. * @param argsOrName Project name or full list of custom arguments * for the generator. */ function init(projectDir, argsOrName) { console.log('Setting up new React Native app in ' + projectDir); const args = Array.isArray(argsOrName) ? argsOrName // argsOrName was e.g. ['AwesomeApp', '--verbose'] : [argsOrName].concat(process.argv.slice(4)); // argsOrName was e.g. 'AwesomeApp’ ・・・続く
  33. 33. React Native の裏側を覗く ・・・続き // args array is e.g. ['AwesomeApp', '--verbose'] if (!args || args.length === 0) { console.error('react-native init requires a project name.'); return; } const newProjectName = args[0]; const options = minimist(args); generateProject(projectDir, newProjectName, options); }
  34. 34. React Native の裏側を覗く function generateProject(destinationRoot, newProjectName, options) { ・・・中略 copyProjectTemplateAndReplace( path.resolve('node_modules', 'react-native', 'local-cli', 'templates', 'HelloWorld'), destinationRoot, newProjectName ); ・・・中略 printRunInstructions(destinationRoot, newProjectName); }
  35. 35. React Native の裏側を覗く const copyProjectTemplateAndReplace = require('../generator/copyProjectTemplateAndReplace'); ・・・中略 require('../generator/printRunInstructions');
  36. 36. 余談
  37. 37. 余談(init.js) const yarnVersion = (!options.npm) && yarn.getYarnVersionIfAvailable() && yarn.isGlobalCliUsingYarn(destinationRoot); ・・・中略 if (yarnVersion) { console.log('Adding React...'); execSync(`yarn add react@${reactVersion}`); } else { console.log('Installing React...'); execSync(`npm install react@${reactVersion} --save --save-exact`); }
  38. 38. React Native の裏側を覗く view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/generator/copyProjectTemplateAndReplace.js
  39. 39. React Native の裏側を覗く 割愛します・・・ [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/templates/HelloWorld から [react-native init したディレクトリ]/[アプリ名] に HelloWorld を [アプリ名] に replace しながら頑張ってコピーしている処理
  40. 40. React Native の裏側を覗く $ ls -l total 64 drwxr-xr-x 4 ayumi.toukairin 386209875 136 12 10 19:23 __tests__ -rw-r--r-- 1 ayumi.toukairin 386209875 31 12 8 20:25 _babelrc -rw-r--r-- 1 ayumi.toukairin 386209875 114 12 8 20:25 _buckconfig -rw-r--r-- 1 ayumi.toukairin 386209875 1425 12 8 20:25 _flowconfig -rw-r--r-- 1 ayumi.toukairin 386209875 16 12 8 20:25 _gitattributes -rw-r--r-- 1 ayumi.toukairin 386209875 415 12 8 20:25 _gitignore -rw-r--r-- 1 ayumi.toukairin 386209875 2 12 8 20:25 _watchmanconfig drwxr-xr-x 10 ayumi.toukairin 386209875 340 12 10 19:23 android -rw-r--r-- 1 ayumi.toukairin 386209875 1106 12 8 20:25 index.android.js -rw-r--r-- 1 ayumi.toukairin 386209875 1072 12 8 20:25 index.ios.js drwxr-xr-x 5 ayumi.toukairin 386209875 170 12 10 19:23 ios
  41. 41. React Native の裏側を覗く $ ls –l total 24 drwxr-xr-x 4 ayumi.toukairin 386209875 136 12 10 19:23 __tests__ drwxr-xr-x 10 ayumi.toukairin 386209875 340 12 10 19:23 android -rw-r--r-- 1 ayumi.toukairin 386209875 1091 12 10 20:55 index.android.js -rw-r--r-- 1 ayumi.toukairin 386209875 1057 12 10 20:55 index.ios.js drwxr-xr-x 5 ayumi.toukairin 386209875 170 12 10 19:23 ios drwxr-xr-x 569 ayumi.toukairin 386209875 19346 12 10 20:55 node_modules -rw-r--r-- 1 ayumi.toukairin 386209875 421 12 10 20:55 package.json
  42. 42. React Native の裏側を覗く $ ls –l ios total 0 drwxr-xr-x 8 ayumi.toukairin 386209875 272 12 10 19:23 [アプリ名] drwxr-xr-x 4 ayumi.toukairin 386209875 136 12 10 19:23 [アプリ名].xcodeproj drwxr-xr-x 4 ayumi.toukairin 386209875 136 12 10 19:23 [アプリ名]Tests
  43. 43. というわけで
  44. 44. init 終わり!
  45. 45. Question
  46. 46. React Native の裏側を覗く 続いて react-native run-ios をみてみる
  47. 47. React Native の裏側を覗く view `which react-native`
  48. 48. React Native の裏側を覗く ・・・ var cli; var cliPath = CLI_MODULE_PATH(); if (fs.existsSync(cliPath)) { cli = require(cliPath); } // minimist api var commands = argv._; if (cli) { cli.run(); } else { ・・・
  49. 49. view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/cliEntry.js React Native の裏側を覗く
  50. 50. React Native の裏側を覗く function run() { const setupEnvScript = /^win/.test(process.platform) ? 'setup_env.bat' : 'setup_env.sh'; childProcess.execFileSync(path.join(__dirname, setupEnvScript)); const config = getCliConfig(); commands.forEach(cmd => addCommand(cmd, config)); commander.parse(process.argv); ・・・
  51. 51. view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/setup_env.sh React Native の裏側を覗く
  52. 52. React Native の裏側を覗く # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. # 2048 is the max for non root users on Mac ulimit -n 2048
  53. 53. React Native の裏側を覗く function run() { const setupEnvScript = /^win/.test(process.platform) ? 'setup_env.bat' : 'setup_env.sh'; childProcess.execFileSync(path.join(__dirname, setupEnvScript)); const config = getCliConfig(); commands.forEach(cmd => addCommand(cmd, config)); commander.parse(process.argv); ・・・続く
  54. 54. React Native の裏側を覗く ・・・続き const isValidCommand = commands.find(cmd => cmd.name.split(' ')[0] === process.argv[2]); if (!isValidCommand) { printUnknownCommand(process.argv[2]); return; } if (!commander.args.length) { commander.help(); } }
  55. 55. 迷⼦になった
  56. 56. React Native の裏側を覗く function run() { const setupEnvScript = /^win/.test(process.platform) ? 'setup_env.bat' : 'setup_env.sh'; childProcess.execFileSync(path.join(__dirname, setupEnvScript)); const config = getCliConfig(); commands.forEach(cmd => addCommand(cmd, config)); commander.parse(process.argv); ・・・続く ここらしい!
  57. 57. React Native の裏側を覗く const commander = require('commander'); ・・・中略 function run() { const setupEnvScript = /^win/.test(process.platform) ? 'setup_env.bat' : 'setup_env.sh'; childProcess.execFileSync(path.join(__dirname, setupEnvScript)); const config = getCliConfig(); commands.forEach(cmd => addCommand(cmd, config)); commander.parse(process.argv); ・・・ https://tj.github.io/commander.js/ ### Command#parse() Parse argv, settings options and invoking commands when defined.
  58. 58. React Native の裏側を覗く const addCommand = (command: Command, config: ConfigT) => { const options = command.options || []; const cmd = commander .command(command.name, undefined, { noHelp: !command.description, }) .description(command.description) .action(function runAction() { const passedOptions = this.opts(); const argv: Array<string> = Array.from(arguments).slice(0, -1); Promise.resolve() .then(() => { assertRequiredOptions(options, passedOptions); return command.func(argv, config, passedOptions); }) .catch(handleError); }); ・・・
  59. 59. view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/runIOS/runIOS.js React Native の裏側を覗く
  60. 60. React Native の裏側を覗く function runIOS(argv, config, args) { process.chdir(args.projectPath); const xcodeProject = findXcodeProject(fs.readdirSync('.')); if (!xcodeProject) { throw new Error('Could not find Xcode project files in ios folder'); } ・・・中略 if (args.device) { ・・・中略 } else { return runOnSimulator(xcodeProject, args, inferredSchemeName, scheme); } }
  61. 61. React Native の裏側を覗く function runOnSimulator(xcodeProject, args, inferredSchemeName, scheme){ return new Promise((resolve) => { try { var simulators = JSON.parse( child_process.execFileSync('xcrun', ['simctl', 'list', '--json', 'devices'], {encoding: 'utf8'}) ); } catch (e) { throw new Error('Could not parse the simulator list output'); } const selectedSimulator = findMatchingSimulator(simulators, args.simulator); if (!selectedSimulator) { throw new Error(`Could not find ${args.simulator} simulator`); } ・・・
  62. 62. React Native の裏側を覗く Usage: xcrun [options] <tool name> ... arguments ... Find and execute the named command line tool from the active developer directory. The active developer directory can be set using `xcode-select`, or via the DEVELOPER_DIR environment variable. See the xcrun and xcode-select manualpages for more information.
  63. 63. React Native の裏側を覗く ・・・ const simulatorFullName = formattedDeviceName(selectedSimulator); console.log(`Launching ${simulatorFullName}...`); try { child_process.spawnSync('xcrun', ['instruments', '-w', selectedSimulator.udid]); } catch (e) { // instruments always fail with 255 because it expects more arguments, // but we want it to only launch the simulator } resolve(selectedSimulator.udid) }) ・・・
  64. 64. React Native の裏側を覗く ・・・ .then((udid) => buildProject(xcodeProject, udid, scheme, args.configuration)) .then((appName) => { if (!appName) { appName = inferredSchemeName; } let appPath = getBuildPath(args.configuration, appName); console.log(`Installing ${appPath}`); child_process.spawnSync('xcrun', ['simctl', 'install', 'booted', appPath], {stdio: 'inherit'}); ・・・
  65. 65. React Native の裏側を覗く ・・・ const bundleID = child_process.execFileSync( '/usr/libexec/PlistBuddy', ['-c', 'Print:CFBundleIdentifier', path.join(appPath, 'Info.plist')], {encoding: 'utf8'} ).trim(); console.log(`Launching ${bundleID}`); child_process.spawnSync('xcrun', ['simctl', 'launch', 'booted', bundleID], {stdio: 'inherit'}); }) }
  66. 66. view [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/packager/react-native-xcode.sh React Native の裏側を覗く
  67. 67. React Native の裏側を覗く #!/bin/bash # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. # ・・・中略 case "$CONFIGURATION" in Debug) # Speed up build times by skipping the creation of the offline package for debug # builds on the simulator since the packager is supposed to be running anyways. if [[ "$PLATFORM_NAME" == *simulator ]]; then echo "Skipping bundling for Simulator platform" exit 0; fi ・・・
  68. 68. また 迷⼦になった
  69. 69. xcodebuild -project [アプリ名].xcodeproj -configuration Debug -scheme [アプリ 名] -destination id=[udid] -derivedDataPath build React Native の裏側を覗く
  70. 70. vim [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/React/React.xcodeproj/project.pbxproj React Native の裏側を覗く
  71. 71. React Native の裏側を覗く #!/bin/sh if [ -z "${RCT_NO_LAUNCH_PACKAGER+xxx}" ] ; then 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 fi
  72. 72. vim [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/packager/launchPackager.command React Native の裏側を覗く
  73. 73. React Native の裏側を覗く #!/usr/bin/env bash # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. ・・・中略 # Set terminal title echo -en "¥033]0;React Packager¥a" clear THIS_DIR=$(dirname "$0") pushd "$THIS_DIR" source ./packager.sh popd echo "Process terminated. Press <enter> to close the window" read
  74. 74. vim [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/packager/packager.sh React Native の裏側を覗く
  75. 75. React Native の裏側を覗く #!/usr/bin/env bash # Copyright (c) 2015-present, Facebook, Inc. # All rights reserved. # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. THIS_DIR=$(dirname "$0") node "$THIS_DIR/../local-cli/cli.js" start "$@"
  76. 76. vim [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/server/server.js React Native の裏側を覗く
  77. 77. React Native の裏側を覗く /** * Starts the React Native Packager Server. */ function server(argv, config, args) { ・・・中略 console.log(formatBanner( 'Running packager on port ' + args.port + '.¥n¥n' + '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.¥n¥n' + 'https://github.com/facebook/react-native', { marginLeft: 1, marginRight: 1, paddingBottom: 1, }) ); ・・・中略 runServer(args, config, () => console.log('¥nReact packager ready.¥n')); }
  78. 78. vim [react-native init したディレクトリ]/[アプリ名]/node_modules/react- native/local-cli/server/runServer.js React Native の裏側を覗く
  79. 79. いよいよ HotDeploy部分
  80. 80. 。。。
  81. 81. ごめんなさい。
  82. 82. まとめ
  83. 83. まとめ • React の知識を覚えるとスマホアプリが作れる、ということでそのメリットは ⼤きい • といいつつも、ハマった時のことを考えると node とアプリ構築(xcode)の 知識はある程度有ったほうが良さそう • 割と⾟かった、でも勉強になった – Simulator ⽴ち上げるまでのコードは⼤体把握できたので、ある程度トラブルシュー ティングもできるようになれば良いな・・・ • いつか続きも読みたいな
  84. 84. Question
  85. 85. Thank you

×