Awesome
react-native-webpack-server
react-native-webpack-server is a development server that leverages the Webpack Dev Server and the React Packager to enable building React Native JavaScript bundles with webpack. This allows you to use the existing webpack ecosystem when targeting React Native.
LOOKING FOR A MAINTAINER
RNWS is not actively maintained; if you'd like to help, leave a comment on #143!
Installing
npm install --save-dev react-native-webpack-server
Using
Use --help
for all CLI options:
node_modules/.bin/rnws --help
node_modules/.bin/rnws start --help
node_modules/.bin/rnws bundle --help
Setup
By default React Native will look for index.ios.js and index.android.js at the root of the project. Delete these files and add entries in your webpack config:
entry: {
'index.ios': ['./src/main.js'],
'index.android': ['./src/main.js']
}
Start react-native-webpack-server using rnws start
. You might want to put this in your package.json
:
"scripts": {
"bundle": "rnws bundle",
"start": "rnws start"
}
This will start the server on port 8080.
On iOS, change the URL of your application bundle in AppDelegate.m
, changing 8081 to 8080:
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8080/index.ios.bundle?platform=ios&dev=true"];
On Android, start your emulator or connect your device and run adb reverse tcp:8081 tcp:8080
. This causes the device to connect to RNWS on port 8080 when it tries to download to http://localhost:8081/index.android.bundle?platform=android. Ensure that you also set Dev Settings -> Debug server host for device to "localhost":
Note: No debugger or hot module replacement support is available yet for Android.
Checkout some of the Examples to get started.
Bundling for release
When you are ready to ship your app, you will want to generate a minified bundle and package it in the binary. Similar to the React Native packager, you can generate an offline JS bundle to use your app without a development server:
rnws bundle
For all options, see:
rnws bundle --help
In your webpack config, you will likely want to enable the UglifyJsPlugin
. The sample apps are configured to enable minification when process.env.NODE_ENV
is set to production
. See the BabelES6 webpack config for an example.
Source Maps
Current solutions for building React Native bundles with Webpack lose source maps. This is because the Webpack bundle is first built and then passed off to the React Packager which constructs the source map by hand. This is done for speed, but it also means you can only use transforms that map lines 1 to 1.
React Native Webpack Server enables source maps by generating the react-native and application bundles separately and then combining their source maps.
Hot Module Replacement
Note: HMR currently does not work using React Native >=0.12. See #103 for a temporary workaround.
Since this is built on Webpack you can now leverage the growing ecosystem of addons such as React hot module replacement via react-transform-hmr.
To enable hot reload, make sure you first install babel-plugin-react-transform and react-transform-hmr, then start the server with --hot
.
You'll also need to configure Webpack. See the Babel+ES6 config for an example.
NOTE: hot reload currently only works with the Chrome web socket executor (hit CMD+D in the simulator). If you regurlarly use this feature, you might want to default to the web socket executor in development:
RCTBridge.m:
- (void)setUp
{
Class executorClass = _executorClass ?: _globalExecutorClass ?: [RCTContextExecutor class];
#if DEBUG
executorClass = NSClassFromString(@"RCTWebSocketExecutor");
#endif
...
}
FAQ
I can't import 3rd party modules in my project.
Most react-native 3rd party modules are published to npm in ES6+ since the react-native packager handles transpiling. You may need to whitelist these modules in your webpack config, as the default configuration in the example excludes all of node_modules. See issue #34.
I get the red box of death when using hot reload even after fixing the exception.
Your code is still executing. Dismiss the red box using the Esc
key.
Why is hot reload using a no-op setInterval() in my app?
It's a terrible hack to jump back onto the React Native runloop when a module is changed. If you have a better idea, please open a PR :)
Source map generation is really slow on io.js.
On a late-2012 Macbook Pro, it takes about 1.5 seconds to generate the source map for react-native on io.js. On stable node (0.12.x) it takes around 200ms. I originally thought this was an issue with source-map but in an isolated test with the entirety of react-native I found io.js and node.js (stable) to be about the same. If you have any ideas, please let me know. In the meantime, it's best to use the latest stable version of node.js.
My .babelrc
configuration is not working
The react-native packager will cache its babel configuration, causing any subsequent changes to .babelrc
to have no effect. Try using the --resetCache
option to clear the RN packager cache:
rnws start --resetCache
See also: #63, facebook/react-native#1924