Comments (28)
By the way, I'm sorry if this is something you don't plan to consider, I totally understand that.
I'm just saying it's a shame we'll have a different "push code updates" system on React Native because, if it is implemented, I expect it to only support "refresh" signals, whereas an existing Webpack solution supports Hot Module Replacement. Hot Module Replacement is vastly superior to a "refresh" signal system but supports it as a degraded simple case, so it's usable from day one.
Many React developers consider hot replacement useful. It's not trivial to implement, so if we're not reusing Webpack's HMR runtime, we likely won't get it soon..
from react-native.
Just to chime in, I would <3 to see this collaboration happen, since I've experienced similar perf problems. Makes me so happy to see a big company like facebook drive an existing project to be better :) (though I totally get why you did your own in the first place)
from react-native.
Yes. We need to port that over. Expect it in a few days/weeks.
from react-native.
I was thinking about this yesterday. A solution (although not optimal) would be to run a server locally in the simulator and have some process watch the local files and tell the simulator server that it should refresh. I was specifically looking at swisspol/GCDWebServer.
from react-native.
cc @amasad
from react-native.
@a2 this is an interesting approach. We already have a solid filewatcher on the server so it might be easier to do it there. The current solution that we have is that the client keeps polling the package and checking for changes. It works well. But it's a little bit janky. If we can open a persistent connection to the server and the server can ping the client to refresh once a file changes (and a package has been updated) would be ideal. In the future, this would also help us in doing things like hot code swapping.
from react-native.
Why not leverage existing solutions like Webpack and webpack-dev-server? It does what you described. It uses chokidar for watching. The client code learns by a socket that update is available and either refreshes (without hot reloading), or does the hot reloading thing if it's configured.
See also #10 (comment) where I also rant about not using Webpack.
from react-native.
Webpack doesn't understand our module infrastructure out of the box. We have plans to support different module formats and different compilers. Additionally chokidar has so many problems but it's suffice to say it doesn't work on large codebases like ours. Regardless, we should get to a place where you decide what packager/module to use on the server.
from react-native.
Webpack doesn't understand our module infrastructure out of the box.
Do you mean custom stuff like package-scoped βglobalβ filenames? This can probably be done with a plugin. Or is it too vastly different?
Additionally chokidar has so many problems but it's suffice to say it doesn't work on large codebases like ours.
They fixed a lot of issues in 1.0. I used to find it unreliable for months, but I suggest you give it another try unless you're absolutely sure.
from react-native.
Also Webpack does not depend on chokidar itself, its new default watching plugin does. It's entirely possible to plug another watcher implementation, but have exactly the same infrastructure for hot updates, etc.
from react-native.
I think we want to be flexible enough for users to make their own choices and maybe support some of the popular things out of the box. I'm on mobile now but I'll reply later with some of the constraints we had when building this and why we couldn't pick one of the ready made solutions.
from react-native.
Thank you, appreciated!
It would be awesome if you exposed a way to reload a page and a way to "inject a script" to JS side. Then we'd be able to use any server and any (hot or not) reloading solution.. I think.
from react-native.
In addition to having a proprietary module format, and because we have a large codebase and needed to use watchman for high performance and more reliable file watching, performance was a big concern. We needed the compiler to work in parallel and we even hand optimized source map generation so we can give error stacks on the client with correct line numbers. Maybe everything can be written as a plugin to webpack but at what point you're reimplementing the program you're supposed to be plugging into. Finally, our vision to what our server should be doing is beyond packaging. We want to integrate Jest testing, Flow type checking, code optimization (dead code elimination, inlining etc).
That shouldn't mean that external react-native users shouldn't or can't use webpack, or for that matter shouldn't replace any of the things I mentioned. You should be able to use Mocha instead of Jest, or 6to5 instead of jstransform etc.
Anyways things are still pretty much work in progress, and feedback like this helps. Thanks
from react-native.
I'm curious if you guys think it would help for us to provide support for webpack's loader and plugin API out of the box for our packaging system?
That would give us access to most of webpack's module ecosystem while still giving us flexibility to implement features that webpack may not be designed for - particularly features around testing, code intelligence, flow integration, etc.
from react-native.
I'm sure Webpack's plugin API would be very hard (it's very tied to how Webpack processes modules, down to compilation phases) so it's probably entirely out of the question.
Implementing Webpack loader support is easier, but only for trivial things like transforming files. It's a lot more work for complex loader features (pitching loaders, async transformers, marking dependencies, require.resolve, etc). RN packager could implement a subset of those, but it is not worth it in my opinion, as it would only cause fragmentation in Webpack ecosystem (is that particular loader supported by RN?) and I doubt RN team wants to be constrained by Webpack APIs.
A more sustainable alternative, in my opinion, is to let users choose a bundler, and add whatever polyfills/bridges we may need for Webpack to work with RN:
WebSocket
API or equivalent- An equivalent of
window.reload()
- An equivalent of loading
<script>
tag dynamically
I really wish @sokra was with us in this discussion!
from react-native.
@sokra I heard you have access to this repo now, care to weigh in?
from react-native.
Hi,
it looks like react-native just expects a URL to the bundle file, which is provided by the packager. Technically the packager could be replaced with webpack.
react-native also uses a non-standard way to append the SourceMap to the source (RAW_SOURCE_MAP = ...
is appended). This could be implemented as webpack plugin. Or react-native could be changed to use the standard //#sourceMappingURL
(errorToString
may need to be changed to be async, because it need to fetch the SourceMap from the server).
I also think it's better to use webpack, because the current packager may only support a subset of npm modules (there are really weird modules that need to be parsed).
So until now, nothing complex...
For Code Splitting and Hot Module Replacement we need something to eval a javascript from a remote URL. Best is when react-native exposes a way to do that. i. e. importScripts
like in a WebWorker or even better something async.
Hot Module Replacement also need to do a full reload of the app. This need to be accessible from the js side. (Looks like this is currently not possible)
If we got this, Hot Module Replacement would work, but only with polling... For a live experience we need a server to react-native connection, i. e. a WebSocket (Or we could use long polling).
The version from reactconf seem to have at least something for server to react-native notification, because saving causes a reload in the video...
from react-native.
The version from reactconf seem to have at least something for server to react-native notification, because saving causes a reload in the video...
I think an earlier comment by @amasad says that:
The current solution that we have is that the client keeps polling the package and checking for changes.
from react-native.
@sokra @gaearon So initial experimentation looks good. However, like I expected, perf is the biggest concern:
- It takes ~45 seconds to build our bundle.
- It takes ~8 seconds to rebuild anytime a file is changed (with sourcemaps, without it's very fast)
Here is what I want:
- I want loaders to run in parallel so that initial build doesn't take forever. I can do it in the loader code, when I get a request I send it to my worker farm. Is this the best way to do it?
- Combining source maps and inlining it in the file (which is what we need to do) adds too much overhead. What we do in our packager is we hand build the sourcemap after creating the bundle which ends up being incredibly fast. How do we do that in Webpack? is there a way to hook into the last step of the bundle creation?
- Is there a way to cache loader results on disk so on startup we won't have to build the whole thing? We just stat the files to see if they changed.
from react-native.
I want loaders to run in parallel so that initial build doesn't take forever. I can do it in the loader code, when I get a request I send it to my worker farm. Is this the best way to do it?
I had the feature that loaders can run in a separate process in webpack 0.6 or so, but spawning a separate processes was pretty expensive and sending source code between processes too. Now better alternatives envolved in the node.js community like https://github.com/xk/node-threads-a-gogo and we could try it again with threads.
It takes ~8 seconds to rebuild anytime a file is changed (with sourcemaps, without it's very fast)
Combining source maps and inlining it in the file (which is what we need to do) adds too much overhead. What we do in our packager is we hand build the sourcemap after creating the bundle which ends up being incredibly fast. How do we do that in Webpack? is there a way to hook into the last step of the bundle creation?
Yeah... (high quality) SourceMaps are pretty slow. They are complex and the source-map
lib is slow.
The current implementation in react-native is faster, because it only maps lines 1 to 1 (note: the jsx transformer keeps line numbers)... Maybe a similar alternative SourceMap devtool could be added to webpack. (More people would like that)
webpack also use some cools tricks to get faster SourceMaps:
devtool: "eval-source-map"
Wraps every module ineval("... //#sourceMappingURL=data:...")
. So we can create the SourceMap once and cache the result for recompilations.devtool: "eval"
Wrapps every module ineval("... //#sourceURL=...")
. This doesn't show original sources, but at least give the module a proper name. (That's really fast.)
Of couse this is not supported by react-native currently...
from react-native.
Is there a way to cache loader results on disk so on startup we won't have to build the whole thing? We just stat the files to see if they changed.
from react-native.
Now better alternatives envolved in the node.js community like https://github.com/xk/node-threads-a-gogo and we could try it again with threads.
Doesn't look like this project is actively supported. And looks like there is no windows support. Not that we currently support windows but we want to be able to.
node-worker-farm works really well and super easy to manage. https://github.com/rvagg/node-worker-farm
Maybe a similar alternative SourceMap devtool could be added to webpack. (More people would like that)
Is source map devtool currently pluggable? Is there documentation on how to write the plugin?
Cool. It seems that you want to be able to cache your entire state? But I can say from experience that caching just the transformation (loader results in webpack lingo) should get you a lot of the benefits.
from react-native.
Is source map devtool currently pluggable? Is there documentation on how to write the plugin?
Yeah, absolutely, it's pluggable. Here's the default SourceMapDevToolPlugin
:
https://github.com/webpack/webpack/blob/master/lib/SourceMapDevToolPlugin.js
Here's Webpack plugin API:
http://webpack.github.io/docs/plugins.html
You can remove devtool
from config and instead put your plugin in plugins
.
from react-native.
Or react-native could be changed to use the standard //#sourceMappingURL (errorToString may need to be changed to be async, because it need to fetch the SourceMap from the server).
Actually we started with this approach, but then tried including source maps inline and it turned out to be a better dev experience.
from react-native.
@amasad I used the easter holydays to implement new SourceMaps for webpack. devtool: "cheap-inline-source-map"
should be much faster (or devtool: "cheap-module-inline-source-map"
if you want source mappings to jsx). Still experimental, but you can try it.
http://webpack.github.io/docs/configuration.html#devtool
It uses a similar approach as react-native: it only maps lines and avoids recomputing base64vlc numbers.
from react-native.
Thanks @sokra! πππ
We are not yet able to process all react-native
project files with webpack
because MessageQueue module uses dynamic require in a way not supported by webpack
at the moment. The fact that all react-native
modules internally use flattened module names (ex: require('ModuleName')
) makes it even trickier (or impossible) to hack with ContextReplacementPlugin
. A hybrid approach (using react-native's packager
for node_modules/react-native/**/*
and webpack
for the rest) is one way to use webpack
but we cannot test the new cheap-inline-source-map
devtool option with that approach because packager
only cares about the code, not the source map.
I believe we need more powerful way to handle dynamic requires in webpack
that works with aliased module names in order to process all files with webpack
unless react-native
changes its code to support webpack
.
from react-native.
Thanks @sokra. What @pilwon said about how we're not ready to completely switch to a standard webpack. But I have some ideas on how we can integrate webpack as a frontend and have our packager be plugged in as loader and resolver. Anyways, what you did should come in handy
from react-native.
The way we currently communicate for Obj-C to JavaScript is by doing eval('require("ModuleName").methodName(arguments)');
. Fortunately, most of it is abstracted away in only 7 methods. What we need to do is to change the call to eval('ReactNativeJSExposedMethods.call('ModuleName', 'MethodName', arguments)')
and have all those methods register themselves before being called.
RCTEventEmitter.receiveTouches
RCTNativeAppEventEmitter.emit
RCTEventEmitter.receiveEvent
ReactIOS.unmountComponentAtNodeAndRemoveContainer
AppRegistry.runApplication
RCTJSTimers.callTimers
RCTDeviceEventEmitter.emit
This is on my todo list but I'm unlikely going to be able to get to it this week if someone wants to pick it up
from react-native.
Related Issues (20)
- [!] Invalid hermes-engine.podspec file: [!] Unable to locate the executable cmake. HOT 8
- Android native module rejections are not instanceof Error HOT 1
- Could not find com.facebook.react:react-android:.:0.72.1 HOT 9
- Build issues with 0.71 RNSha256 XCode 15.3 HOT 4
- `fontVariant` doesn't work on iOS when using the new architecture
- UI problem with iOS floating keyboard in iPad. HOT 5
- TouchableWithoutFeedback does not support style HOT 1
- Cannot find EventEmitter for receivedTouches EventName[topTouchMove, topTouchEnd] on native library HOT 5
- RCTNativeAnimatedNodesManager.mm props is not a node HOT 1
- Unexpected scroll behaviors when using FlatList HOT 7
- When I integration react native with Existing Android Apps,I got a autolinking question. HOT 2
- Symbol not found: (_JSGlobalContextSetInspectable) HOT 1
- The directory ****/ios contains 2 projects HOT 3
- textInput props textAlign will cause long text to be cut off after the hyphen when out of focus and focus again
- close the first modal with animation, then open the second modal immediately, the second modal can't be showed HOT 2
- UI updates made from layout effect are flushed in separate UI transaction HOT 4
- Blob constructor is not spec compliant HOT 1
- [!] CocoaPods could not find compatible versions for pod "React-RCTAnimation": In Podfile: React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) HOT 3
- Build error in 0.73.6 HOT 3
- Fatal error "available height is undefined" when editing textinput the app closes HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-native.