How can I use buck to build react-native apps for

2019-02-02 13:53发布

问题:

Buck sounds like a great tool for both iOS and Android projects but I have not been abel to find any information on how to use it for react-native projects.

Update

Looks like there is some work being done on this but it may not be recommended yet.

https://github.com/facebook/nuclide/issues/31#issuecomment-164897170 https://github.com/facebook/buck/tree/master/test/com/facebook/buck/js

Update 2

Product Pains link https://productpains.com/post/react-native/add-buck-as-a-build-option

回答1:

Update 8/6/2017:

I tried following my steps below for integrating React Native into an iOS app with Buck but I ran into issues when using React Native 0.47. Instead I have a new simpler approach for getting React Native working with Buck on iOS by linking to prebuilt libraries. I forked the Buck sample project repo and have it working with React Native in this repo. I also updated the README in that repo with instructions for running the demo Buck React Native iOS app and how to integrate yourself.

Note there are a couple issues with this approach documented in the README that may or may not be a problem for using this in a production app.

That repo also doesn't bundle the JS for production yet.


Older answer:

I got Buck working with an iOS project. It is very much a work in progress, but works. A few notes:

  • I manually copied files from node_modules/react-native/React and node_modules/react-native/Libraries (see folder structure below).
  • I had to add the -w and Wno-error flags to each library because the main project had treat warnings as errors and I didn't want to see all of these React Native warnings in Xcode.
  • You may have to add more libraries following the pattern. It also helps to look at the React Native podspec.
  • There is probably opportunity to clean things up like there is no need for reactnative.xcodeproj in the vendor/reactnative folder (see below).
  • There is probably some work needed to correctly bundle the JS for production. Currently it will only work if the JS is fetched from a server (e.g. Node.js).

Here is my vendor/reactnative/BUCK file:

apple_library(
  name = 'ReactNative',
  srcs = glob([
    'React/**/*.m',
    'React/**/*.mm',
    'React/**/*.c',
    'React/**/*.S',
  ]),
  exported_headers = glob([
    'React/**/*.h',
  ]),
  system_frameworks = [
    'JavaScriptCore'
  ],
  exported_linker_flags = [
    '-lc++',
  ],
  compiler_flags = [
    '-Wno-error',
    '-w'
  ],
  visibility = ['PUBLIC'],
)

apple_library(
  name = 'RCTWebSocket',
  srcs = glob([
    'Libraries/WebSocket/*.m',
  ]),
  headers = glob([
    'React/**/*.h',
  ]),
  exported_headers = glob([
    'Libraries/WebSocket/*.h',
  ]),
  compiler_flags = [
    '-Wno-error',
    '-w'
  ],
  visibility = ['PUBLIC'],
  deps = [
    ':ReactNative',
  ]
)

apple_library(
  name = 'RCTNetwork',
  srcs = glob([
    'Libraries/Network/*.m',
  ]),
  headers = glob([
    'React/**/*.h',
  ]),
  exported_headers = glob([
    'Libraries/Network/*.h',
  ]),
  compiler_flags = [
    '-Wno-error',
    '-w'
  ],
  visibility = ['PUBLIC'],
  deps = [
    ':ReactNative',
  ]
)

apple_library(
  name = 'RCTText',
  srcs = glob([
    'Libraries/Text/*.m',
  ]),
  headers = glob([
    'React/**/*.h',
  ]),
  exported_headers = glob([
    'Libraries/Text/*.h',
  ]),
  compiler_flags = [
    '-Wno-error',
    '-w'
  ],
  visibility = ['PUBLIC'],
  deps = [
    ':ReactNative',
  ]
)

apple_library(
  name = 'RCTImage',
  srcs = glob([
    'Libraries/Image/*.m',
  ]),
  headers = glob([
    'React/**/*.h',
    'Libraries/Network/*.h'
  ]),
  exported_headers = glob([
    'Libraries/Image/*.h',
  ]),
  compiler_flags = [
    '-Wno-error',
    '-w'
  ],
  visibility = ['PUBLIC'],
  deps = [
    ':ReactNative',
    ':RCTNetwork'
  ]
)

Here is the folder structure inside a vendor folder in my project:

vendor/reactnative
├── BUCK
├── Libraries
│   ├── ART
│   ├── ActionSheetIOS
│   ├── AdSupport
│   ├── Animated
│   ├── AppRegistry
│   ├── AppState
│   ├── BatchedBridge
│   ├── BugReporting
│   ├── CameraRoll
│   ├── Components
│   ├── CustomComponents
│   ├── DebugComponentHierarchy
│   ├── Devtools
│   ├── EventEmitter
│   ├── Experimental
│   ├── Fetch
│   ├── Geolocation
│   ├── Image
│   ├── Inspector
│   ├── Interaction
│   ├── JavaScriptAppEngine
│   ├── LayoutAnimation
│   ├── Linking
│   ├── LinkingIOS
│   ├── Modal
│   ├── NativeAnimation
│   ├── NavigationExperimental
│   ├── Network
│   ├── Promise.js
│   ├── PushNotificationIOS
│   ├── QuickPerformanceLogger
│   ├── RCTTest
│   ├── RKBackendNode
│   ├── ReactIOS
│   ├── ReactNative
│   ├── Sample
│   ├── Settings
│   ├── Storage
│   ├── StyleSheet
│   ├── Text
│   ├── Utilities
│   ├── Vibration
│   ├── WebSocket
│   ├── promiseRejectionIsError.js
│   ├── react-native
│   └── vendor
├── React
│   ├── Base
│   ├── Executors
│   ├── Layout
│   ├── Modules
│   ├── Profiler
│   └── Views
└── reactnative.xcodeproj
    ├── project.pbxproj
    └── xcuserdata

Then in the deps of my main BUCK file I add:

'//vendor/reactnative:ReactNative',
'//vendor/reactnative:RCTWebSocket',
'//vendor/reactnative:RCTText',
'//vendor/reactnative:RCTNetwork',
'//vendor/reactnative:RCTImage'


回答2:

There's no official documentation / template for building RN apps with Buck yet but it shouldn't be that hard. You'd need to add a BUCK file that does the equivalent of what your build.gradle file does.

It's mostly just:

  • Declares an Android app with a dependency on React Native from JCenter (Buck has the android_binary rule to do that)
  • In release mode it also bundles the JS into your app's assets folder. You could skip this for a start (in dev mode the app fetches the JS from localhost at runtime) but I believe Buck has built-in support for bundling JS too.