Updated docs for 0.24

This commit is contained in:
Website Deployment Script
2016-04-19 00:10:32 +00:00
parent cdba3024af
commit 6fda90c4fc
1476 changed files with 386 additions and 117893 deletions
@@ -1,90 +0,0 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><title>Introducing Hot Reloading React Native | A framework for building native apps using React</title><meta name="viewport" content="width=device-width"><meta property="og:title" content="Introducing Hot Reloading React Native | A framework for building native apps using React"><meta property="og:type" content="website"><meta property="og:url" content="http://facebook.github.io/react-native/index.html"><meta property="og:image" content="http://facebook.github.io/react-native/img/opengraph.png?2"><meta property="og:description" content="A framework for building native apps using React"><base href="/react-native/releases/next/"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"><link rel="shortcut icon" href="img/favicon.png?2"><link rel="stylesheet" href="css/react-native.css"><script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script><script type="text/javascript">try{Typekit.load();}catch(e){}</script></head><body><div class="container"><div class="nav-main"><div class="wrap"><a class="nav-home" href=""><img src="img/header_logo.png">React Native</a><a class="nav-version" href="/react-native/versions.html">next</a><div class="nav-site-wrapper"><ul class="nav-site nav-site-internal"><li><a href="docs/getting-started.html" class="">Docs</a></li><li><a href="support.html" class="">Support</a></li><li><a href="showcase.html" class="">Showcase</a></li><li><a href="blog/" class="active">Blog</a></li></ul><div class="algolia-search-wrapper"><input id="algolia-doc-search" type="text" placeholder="Search docs..."></div><ul class="nav-site nav-site-external"><li><a href="https://github.com/facebook/react-native" class="">GitHub</a></li><li><a href="http://facebook.github.io/react" class="">React</a></li></ul></div></div></div><section class="content wrap documentationContent"><div class="nav-docs"><div class="nav-docs-section"><h3>Recent Posts</h3><ul><li><a class="active" href="/react-native/blog/2016/03/24/introducing-hot-reloading.html">Introducing Hot Reloading</a></li></ul></div></div><div class="inner-content"><div><h1>Introducing Hot Reloading</h1><p class="meta">March 24, 2016 by <a target="_blank">Martín Bigio</a></p><hr><div><p>React Native goal is to give you the best possible developer experience. A big part of it is the time it takes between you save a file and be able to see the changes. Our goal is to get this feedback loop to be under 1 second, even as your app grows.</p><p>We got close to this ideal via three main features:</p><ul><li>Use JavaScript as the language doesn&#x27;t have a long compilation cycle time.</li><li>Implement a tool called Packager that transforms es6/flow/jsx files into normal JavaScript that the VM can understand. It was designed as a server that keeps intermediate state in memory to enable fast incremental changes and uses multiple cores.</li><li>Build a feature called Live Reload that reloads the app on save.</li></ul><p>At this point, the bottleneck for developers is no longer the time it takes to reload the app but losing the state of your app. A common scenario is to work on a feature that is multiple screens away from the launch screen. Every time you reload, you&#x27;ve got to click on the same path again and again to get back to your feature, making the cycle multiple-seconds long.</p><h2><a class="anchor" name="hot-reloading"></a>Hot Reloading <a class="hash-link" href="#hot-reloading">#</a></h2><p>The idea behind hot reloading is to keep the app running and to inject new versions of the files that you edited at runtime. This way, you don&#x27;t lose any of your state which is especially useful if you are tweaking the UI.</p><p>A video is worth a thousand words. Check out the difference between Live Reload (current) and Hot Reload (new).</p><span><iframe width="100%" height="315" src="https://www.youtube.com/embed/2uQzVi-KFuc" frameborder="0" allowfullscreen></iframe>
</span><p>If you look closely, you can notice that it is possible to recover from a red box and you can also start importing modules that were not previously there without having to do a full reload.</p><p><strong>Word of warning:</strong> because JavaScript is a very stateful language, hot reloading cannot be perfectly implemented. In practice, we found out that the current setup is working well for a large amount of usual use cases and a full reload is always available in case something gets messed up.</p><p>Hot reloading is available as of 0.22, you can enable it:</p><ul><li>Open the developper menu</li><li>Tap on &quot;Enable Hot Reloading&quot;</li></ul><h2><a class="anchor" name="implementation-in-a-nutshell"></a>Implementation in a nutshell <a class="hash-link" href="#implementation-in-a-nutshell">#</a></h2><p>Now that we&#x27;ve seen why we want it and how to use it, the fun part begins: how does it actually works.</p><p>Hot Reloading is built on top of a feature <a href="https://webpack.github.io/docs/hot-module-replacement-with-webpack.html" target="_blank">Hot Module Replacement</a>, or HMR. It was first introduced by Webpack and we implemented it inside of React Native Packager. HMR makes the Packager watch for file changes and send HMR updates to a thin HMR runtime included on the app.</p><p>In a nutshell, the HMR update contains the new code of the JS modules that changed. When the runtime receives them, it replaces the old modules&#x27; code with the new one:</p><p><img src="/react-native/blog/img/hmr-architecture.png" alt=""></p><p>The HMR update contains a bit more than just the module&#x27;s code we want to change because replacing it, it&#x27;s not enough for the runtime to pick up the changes. The problem is that the module system may have already cached the <em>exports</em> of the module we want to update. For instance, say you have an app composed by these two modules:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// log.js
</span><span class="token keyword">function</span> <span class="token function">log<span class="token punctuation">(</span></span>message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
const time <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;./time&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>`<span class="token punctuation">[</span>$<span class="token punctuation">{</span><span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">]</span> $<span class="token punctuation">{</span>message<span class="token punctuation">}</span>`<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> log<span class="token punctuation">;</span></div><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getTime<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> time<span class="token punctuation">;</span></div><p>The module <code>log</code>, prints out the provided message including the current date provided by the module <code>time</code>.</p><p>When the app is bundled, React Native registers each module on the module system using the <code>__d</code> function. For this app, among many <code>__d</code> definitions, there will one for <code>log</code>:</p><div class="prism language-javascript"><span class="token function">__d<span class="token punctuation">(</span></span><span class="token string">&#x27;log&#x27;</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token comment" spellcheck="true"> // module&#x27;s code
</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></div><p>This invocation wraps each module&#x27;s code into an anonymous function which we generally refer to as the factory function. The module system runtime keeps track of each module&#x27;s factory function, whether it has already been executed, and the result of such execution (exports). When a module is required, the module system either provides the already cached exports or executes the module&#x27;s factory function for the first time and saves the result.</p><p>So say you start your app and require <code>log</code>. At this point, neither <code>log</code> nor <code>time</code>&#x27;s factory functions have been executed so no exports have been cached. Then, the user modifies <code>time</code> to return the date in <code>MM/DD</code>:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">bar<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> date <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> `$<span class="token punctuation">{</span>date<span class="token punctuation">.</span><span class="token function">getMonth<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">}</span><span class="token operator">/</span>$<span class="token punctuation">{</span>date<span class="token punctuation">.</span><span class="token function">getDate<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span>`<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> bar<span class="token punctuation">;</span></div><p>The Packager will send time&#x27;s new code to the runtime (step 1), and when <code>log</code> gets eventually required the exported function gets executed it will do so with <code>time</code>&#x27;s changes (step 2):</p><p><img src="/react-native/blog/img/hmr-step.png" alt=""></p><p>Now say the code of <code>log</code> requires <code>time</code> as a top level require:</p><div class="prism language-javascript">const time <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;./time&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"> // top level require
</span><span class="token comment" spellcheck="true">
// log.js
</span><span class="token keyword">function</span> <span class="token function">log<span class="token punctuation">(</span></span>message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>`<span class="token punctuation">[</span>$<span class="token punctuation">{</span><span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">]</span> $<span class="token punctuation">{</span>message<span class="token punctuation">}</span>`<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> log<span class="token punctuation">;</span></div><p>When <code>log</code> is required, the runtime will cache its exports and <code>time</code>&#x27;s one. (step 1). Then, when <code>time</code> is modified, the HMR process cannot simply finish after replacing <code>time</code>&#x27;s code. If it did, when <code>log</code> gets executed, it would do so with a cached copy of <code>time</code> (old code).</p><p>For <code>log</code> to pick up <code>time</code> changes, we&#x27;ll need to clear its cached exports because one of the modules it depends on was hot swapped (step 3). Finally, when <code>log</code> gets required again, its factory function will get executed requiring <code>time</code> and getting its new code.</p><p><img src="/react-native/blog/img/hmr-log.png" alt=""></p><h2><a class="anchor" name="hmr-api"></a>HMR API <a class="hash-link" href="#hmr-api">#</a></h2><p>HMR in React Native extends the module system by introducing the <code>hot</code> object. This API is based on <a href="https://webpack.github.io/docs/hot-module-replacement.html" target="_blank">Webpack</a>&#x27;s one. The <code>hot</code> object exposes a function called <code>accept</code> which allows you to define a callback that will be executed when the module needs to be hot swapped. For instance, if we would change <code>time</code>&#x27;s code as follows, every time we save time, we&#x27;ll see “time changed” in the console:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token comment" spellcheck="true"> // new code
</span><span class="token punctuation">}</span>
module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept<span class="token punctuation">(</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span><span class="token string">&#x27;time changed&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> time<span class="token punctuation">;</span></div><p>Note that only in rare cases you would need to use this API manually. Hot Reloading should work out of the box for the most common use cases.</p><h2><a class="anchor" name="hmr-runtime"></a>HMR Runtime <a class="hash-link" href="#hmr-runtime">#</a></h2><p>As we&#x27;ve seen before, sometimes it&#x27;s not enough only accepting the HMR update because a module that uses the one being hot swapped may have been already executed and its imports cached. For instance, suppose the dependency tree for the movies app example had a top-level <code>MovieRouter</code> that depended on the <code>MovieSearch</code> and <code>MovieScreen</code> views, which depended on the <code>log</code> and <code>time</code> modules from the previous examples:</p><p><img src="/react-native/blog/img/hmr-diamond.png" alt=""></p><p>If the user access the movies&#x27; search view but not the other one, all the modules but <code>MovieScreen</code> would have cached exports. If a change is made to module <code>time</code>, the runtime will have to clear the exports of <code>log</code> for it to pick up <code>time</code>&#x27;s changes. The process wouldn&#x27;t finish there: the runtime will repeat this process recursively up until all the parents have been accepted. So, it&#x27;ll grab the modules that depend on <code>log</code> and try to accept them. For <code>MovieScreen</code> it can bail, as it hasn&#x27;t been required yet. For <code>MovieSearch</code>, it will have to clear its exports and process its parents recursively. Finally, it will do the same thing for <code>MovieRouter</code> and finish there as no modules depends on it.</p><p>In order to walk the dependency tree, the runtime receives the inverse dependency tree from the Packager on the HMR update. For this example the runtime will receive a JSON object like this one:</p><div class="prism language-javascript"><span class="token punctuation">{</span>
modules<span class="token punctuation">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
name<span class="token punctuation">:</span> <span class="token string">&#x27;time&#x27;</span><span class="token punctuation">,</span>
code<span class="token punctuation">:</span> <span class="token comment" spellcheck="true">/* time&#x27;s new code */</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
inverseDependencies<span class="token punctuation">:</span> <span class="token punctuation">{</span>
MovieRouter<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
MovieScreen<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieRouter&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
MovieSearch<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieRouter&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
log<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieScreen&#x27;</span><span class="token punctuation">,</span> <span class="token string">&#x27;MovieSearch&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
time<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;log&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></div><h2><a class="anchor" name="react-components"></a>React Components <a class="hash-link" href="#react-components">#</a></h2><p>React components are a bit harder to get to work with Hot Reloading. The problem is that we can&#x27;t simply replace the old code with the new one as we&#x27;d loose the component&#x27;s state. For React web applications, <a href="https://twitter.com/dan_abramov" target="_blank">Dan Abramov</a> implemented a babel <a href="http://gaearon.github.io/react-hot-loader/" target="_blank">transform</a> that uses Webpack&#x27;s HMR API to solve this issue. In a nutshell, his solution works by creating a proxy for every single React component on <em>transform time</em>. The proxies hold the component&#x27;s state and delegate the lifecycle methods to the actual components, which are the ones we hot reload:</p><p><img src="/react-native/blog/img/hmr-proxy.png" alt=""></p><p>Besides creating the proxy component, the transform also defines the <code>accept</code> function with a piece of code to force React to re-render the component. This way, we can hot reload rendering code without losing any of the app&#x27;s state.</p><p>The default <a href="https://github.com/facebook/react-native/blob/master/packager/transformer.js#L92-L95" target="_blank">transformer</a> that comes with React Native uses the <code>babel-preset-react-native</code>, which is <a href="https://github.com/facebook/react-native/blob/master/babel-preset/configs/hmr.js#L24-L31" target="_blank">configured</a> to use <code>react-transform</code> the same way you&#x27;d use it on a React web project that uses Webpack.</p><h2><a class="anchor" name="redux-stores"></a>Redux Stores <a class="hash-link" href="#redux-stores">#</a></h2><p>To enable Hot Reloading on <a href="http://redux.js.org/" target="_blank">Redux</a> stores you will just need to use the HMR API similarly to what you&#x27;d do on a web project that uses Webpack:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// configureStore.js
</span>import <span class="token punctuation">{</span> createStore<span class="token punctuation">,</span> applyMiddleware<span class="token punctuation">,</span> compose <span class="token punctuation">}</span> from <span class="token string">&#x27;redux&#x27;</span><span class="token punctuation">;</span>
import thunk from <span class="token string">&#x27;redux-thunk&#x27;</span><span class="token punctuation">;</span>
import reducer from <span class="token string">&#x27;../reducers&#x27;</span><span class="token punctuation">;</span>
export default <span class="token keyword">function</span> <span class="token function">configureStore<span class="token punctuation">(</span></span>initialState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
const store <span class="token operator">=</span> <span class="token function">createStore<span class="token punctuation">(</span></span>
reducer<span class="token punctuation">,</span>
initialState<span class="token punctuation">,</span>
<span class="token function">applyMiddleware<span class="token punctuation">(</span></span>thunk<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span> <span class="token punctuation">{</span>
module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept<span class="token punctuation">(</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
const nextRootReducer <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;../reducers/index&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>default<span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">replaceReducer<span class="token punctuation">(</span></span>nextRootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> store<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></div><p>When you change a reducer, the code to accept that reducer will be sent to the client. Then the client will realize that the reducer doesn&#x27;t know how to accept itself, so it will look for all the modules that refer it and try to accept them. Eventually, the flow will get to the single store, the <code>configureStore</code> module, which will accept the HMR update.</p><h2><a class="anchor" name="conclusion"></a>Conclusion <a class="hash-link" href="#conclusion">#</a></h2><p>If you are interested in helping making hot reloading better, I encourage you to read <a href="https://medium.com/@dan_abramov/hot-reloading-in-react-1140438583bf#.jmivpvmz4" target="_blank">Dan Abramov&#x27;s post around the future of hot reloading</a> and to contribute. For example, Johny Days is going to <a href="https://github.com/facebook/react-native/pull/6179" target="_blank">make it work with multiple connected clients</a>. We&#x27;re relying on you all to maintain and improve this feature.</p><p>With React Native, we have the opportunity to rethink the way we build apps in order to make it a great developer experience. Hot reloading is only one piece of the puzzle, what other crazy hacks can we do to make it better?</p></div></div></div></section><footer class="wrap"><div class="center">© 2016 Facebook Inc.</div></footer></div><div id="fb-root"></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-41298772-2', 'facebook.github.io');
ga('send', 'pageview');
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)
){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
docsearch({
apiKey: '2c98749b4a1e588efec53b2acec13025',
indexName: 'react-native-versions',
inputSelector: '#algolia-doc-search',
algoliaOptions: { facetFilters: [ "tags:master" ], hitsPerPage: 5 }
});
</script><script src="js/scripts.js"></script></body></html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

-90
View File
@@ -1,90 +0,0 @@
<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><title>Blog React Native | A framework for building native apps using React</title><meta name="viewport" content="width=device-width"><meta property="og:title" content="Blog React Native | A framework for building native apps using React"><meta property="og:type" content="website"><meta property="og:url" content="http://facebook.github.io/react-native/index.html"><meta property="og:image" content="http://facebook.github.io/react-native/img/opengraph.png?2"><meta property="og:description" content="A framework for building native apps using React"><base href="/react-native/releases/next/"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"><link rel="shortcut icon" href="img/favicon.png?2"><link rel="stylesheet" href="css/react-native.css"><script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script><script type="text/javascript">try{Typekit.load();}catch(e){}</script></head><body><div class="container"><div class="nav-main"><div class="wrap"><a class="nav-home" href=""><img src="img/header_logo.png">React Native</a><a class="nav-version" href="/react-native/versions.html">next</a><div class="nav-site-wrapper"><ul class="nav-site nav-site-internal"><li><a href="docs/getting-started.html" class="">Docs</a></li><li><a href="support.html" class="">Support</a></li><li><a href="showcase.html" class="">Showcase</a></li><li><a href="blog/" class="active">Blog</a></li></ul><div class="algolia-search-wrapper"><input id="algolia-doc-search" type="text" placeholder="Search docs..."></div><ul class="nav-site nav-site-external"><li><a href="https://github.com/facebook/react-native" class="">GitHub</a></li><li><a href="http://facebook.github.io/react" class="">React</a></li></ul></div></div></div><section class="content wrap documentationContent"><div class="nav-docs"><div class="nav-docs-section"><h3>Recent Posts</h3><ul><li><a class="" href="/react-native/blog/2016/03/24/introducing-hot-reloading.html">Introducing Hot Reloading</a></li></ul></div></div><div class="inner-content"><div><h1>Introducing Hot Reloading</h1><p class="meta">March 24, 2016 by <a target="_blank">Martín Bigio</a></p><hr><div><p>React Native goal is to give you the best possible developer experience. A big part of it is the time it takes between you save a file and be able to see the changes. Our goal is to get this feedback loop to be under 1 second, even as your app grows.</p><p>We got close to this ideal via three main features:</p><ul><li>Use JavaScript as the language doesn&#x27;t have a long compilation cycle time.</li><li>Implement a tool called Packager that transforms es6/flow/jsx files into normal JavaScript that the VM can understand. It was designed as a server that keeps intermediate state in memory to enable fast incremental changes and uses multiple cores.</li><li>Build a feature called Live Reload that reloads the app on save.</li></ul><p>At this point, the bottleneck for developers is no longer the time it takes to reload the app but losing the state of your app. A common scenario is to work on a feature that is multiple screens away from the launch screen. Every time you reload, you&#x27;ve got to click on the same path again and again to get back to your feature, making the cycle multiple-seconds long.</p><h2><a class="anchor" name="hot-reloading"></a>Hot Reloading <a class="hash-link" href="#hot-reloading">#</a></h2><p>The idea behind hot reloading is to keep the app running and to inject new versions of the files that you edited at runtime. This way, you don&#x27;t lose any of your state which is especially useful if you are tweaking the UI.</p><p>A video is worth a thousand words. Check out the difference between Live Reload (current) and Hot Reload (new).</p><span><iframe width="100%" height="315" src="https://www.youtube.com/embed/2uQzVi-KFuc" frameborder="0" allowfullscreen></iframe>
</span><p>If you look closely, you can notice that it is possible to recover from a red box and you can also start importing modules that were not previously there without having to do a full reload.</p><p><strong>Word of warning:</strong> because JavaScript is a very stateful language, hot reloading cannot be perfectly implemented. In practice, we found out that the current setup is working well for a large amount of usual use cases and a full reload is always available in case something gets messed up.</p><p>Hot reloading is available as of 0.22, you can enable it:</p><ul><li>Open the developper menu</li><li>Tap on &quot;Enable Hot Reloading&quot;</li></ul><h2><a class="anchor" name="implementation-in-a-nutshell"></a>Implementation in a nutshell <a class="hash-link" href="#implementation-in-a-nutshell">#</a></h2><p>Now that we&#x27;ve seen why we want it and how to use it, the fun part begins: how does it actually works.</p><p>Hot Reloading is built on top of a feature <a href="https://webpack.github.io/docs/hot-module-replacement-with-webpack.html" target="_blank">Hot Module Replacement</a>, or HMR. It was first introduced by Webpack and we implemented it inside of React Native Packager. HMR makes the Packager watch for file changes and send HMR updates to a thin HMR runtime included on the app.</p><p>In a nutshell, the HMR update contains the new code of the JS modules that changed. When the runtime receives them, it replaces the old modules&#x27; code with the new one:</p><p><img src="/react-native/blog/img/hmr-architecture.png" alt=""></p><p>The HMR update contains a bit more than just the module&#x27;s code we want to change because replacing it, it&#x27;s not enough for the runtime to pick up the changes. The problem is that the module system may have already cached the <em>exports</em> of the module we want to update. For instance, say you have an app composed by these two modules:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// log.js
</span><span class="token keyword">function</span> <span class="token function">log<span class="token punctuation">(</span></span>message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
const time <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;./time&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>`<span class="token punctuation">[</span>$<span class="token punctuation">{</span><span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">]</span> $<span class="token punctuation">{</span>message<span class="token punctuation">}</span>`<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> log<span class="token punctuation">;</span></div><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getTime<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> time<span class="token punctuation">;</span></div><p>The module <code>log</code>, prints out the provided message including the current date provided by the module <code>time</code>.</p><p>When the app is bundled, React Native registers each module on the module system using the <code>__d</code> function. For this app, among many <code>__d</code> definitions, there will one for <code>log</code>:</p><div class="prism language-javascript"><span class="token function">__d<span class="token punctuation">(</span></span><span class="token string">&#x27;log&#x27;</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token comment" spellcheck="true"> // module&#x27;s code
</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></div><p>This invocation wraps each module&#x27;s code into an anonymous function which we generally refer to as the factory function. The module system runtime keeps track of each module&#x27;s factory function, whether it has already been executed, and the result of such execution (exports). When a module is required, the module system either provides the already cached exports or executes the module&#x27;s factory function for the first time and saves the result.</p><p>So say you start your app and require <code>log</code>. At this point, neither <code>log</code> nor <code>time</code>&#x27;s factory functions have been executed so no exports have been cached. Then, the user modifies <code>time</code> to return the date in <code>MM/DD</code>:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">bar<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> date <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> `$<span class="token punctuation">{</span>date<span class="token punctuation">.</span><span class="token function">getMonth<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">}</span><span class="token operator">/</span>$<span class="token punctuation">{</span>date<span class="token punctuation">.</span><span class="token function">getDate<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span>`<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> bar<span class="token punctuation">;</span></div><p>The Packager will send time&#x27;s new code to the runtime (step 1), and when <code>log</code> gets eventually required the exported function gets executed it will do so with <code>time</code>&#x27;s changes (step 2):</p><p><img src="/react-native/blog/img/hmr-step.png" alt=""></p><p>Now say the code of <code>log</code> requires <code>time</code> as a top level require:</p><div class="prism language-javascript">const time <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;./time&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true"> // top level require
</span><span class="token comment" spellcheck="true">
// log.js
</span><span class="token keyword">function</span> <span class="token function">log<span class="token punctuation">(</span></span>message<span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>`<span class="token punctuation">[</span>$<span class="token punctuation">{</span><span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">]</span> $<span class="token punctuation">{</span>message<span class="token punctuation">}</span>`<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> log<span class="token punctuation">;</span></div><p>When <code>log</code> is required, the runtime will cache its exports and <code>time</code>&#x27;s one. (step 1). Then, when <code>time</code> is modified, the HMR process cannot simply finish after replacing <code>time</code>&#x27;s code. If it did, when <code>log</code> gets executed, it would do so with a cached copy of <code>time</code> (old code).</p><p>For <code>log</code> to pick up <code>time</code> changes, we&#x27;ll need to clear its cached exports because one of the modules it depends on was hot swapped (step 3). Finally, when <code>log</code> gets required again, its factory function will get executed requiring <code>time</code> and getting its new code.</p><p><img src="/react-native/blog/img/hmr-log.png" alt=""></p><h2><a class="anchor" name="hmr-api"></a>HMR API <a class="hash-link" href="#hmr-api">#</a></h2><p>HMR in React Native extends the module system by introducing the <code>hot</code> object. This API is based on <a href="https://webpack.github.io/docs/hot-module-replacement.html" target="_blank">Webpack</a>&#x27;s one. The <code>hot</code> object exposes a function called <code>accept</code> which allows you to define a callback that will be executed when the module needs to be hot swapped. For instance, if we would change <code>time</code>&#x27;s code as follows, every time we save time, we&#x27;ll see “time changed” in the console:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// time.js
</span><span class="token keyword">function</span> <span class="token function">time<span class="token punctuation">(</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token comment" spellcheck="true"> // new code
</span><span class="token punctuation">}</span>
module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept<span class="token punctuation">(</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span><span class="token string">&#x27;time changed&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> time<span class="token punctuation">;</span></div><p>Note that only in rare cases you would need to use this API manually. Hot Reloading should work out of the box for the most common use cases.</p><h2><a class="anchor" name="hmr-runtime"></a>HMR Runtime <a class="hash-link" href="#hmr-runtime">#</a></h2><p>As we&#x27;ve seen before, sometimes it&#x27;s not enough only accepting the HMR update because a module that uses the one being hot swapped may have been already executed and its imports cached. For instance, suppose the dependency tree for the movies app example had a top-level <code>MovieRouter</code> that depended on the <code>MovieSearch</code> and <code>MovieScreen</code> views, which depended on the <code>log</code> and <code>time</code> modules from the previous examples:</p><p><img src="/react-native/blog/img/hmr-diamond.png" alt=""></p><p>If the user access the movies&#x27; search view but not the other one, all the modules but <code>MovieScreen</code> would have cached exports. If a change is made to module <code>time</code>, the runtime will have to clear the exports of <code>log</code> for it to pick up <code>time</code>&#x27;s changes. The process wouldn&#x27;t finish there: the runtime will repeat this process recursively up until all the parents have been accepted. So, it&#x27;ll grab the modules that depend on <code>log</code> and try to accept them. For <code>MovieScreen</code> it can bail, as it hasn&#x27;t been required yet. For <code>MovieSearch</code>, it will have to clear its exports and process its parents recursively. Finally, it will do the same thing for <code>MovieRouter</code> and finish there as no modules depends on it.</p><p>In order to walk the dependency tree, the runtime receives the inverse dependency tree from the Packager on the HMR update. For this example the runtime will receive a JSON object like this one:</p><div class="prism language-javascript"><span class="token punctuation">{</span>
modules<span class="token punctuation">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
name<span class="token punctuation">:</span> <span class="token string">&#x27;time&#x27;</span><span class="token punctuation">,</span>
code<span class="token punctuation">:</span> <span class="token comment" spellcheck="true">/* time&#x27;s new code */</span>
<span class="token punctuation">}</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
inverseDependencies<span class="token punctuation">:</span> <span class="token punctuation">{</span>
MovieRouter<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
MovieScreen<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieRouter&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
MovieSearch<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieRouter&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
log<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;MovieScreen&#x27;</span><span class="token punctuation">,</span> <span class="token string">&#x27;MovieSearch&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
time<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string">&#x27;log&#x27;</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span></div><h2><a class="anchor" name="react-components"></a>React Components <a class="hash-link" href="#react-components">#</a></h2><p>React components are a bit harder to get to work with Hot Reloading. The problem is that we can&#x27;t simply replace the old code with the new one as we&#x27;d loose the component&#x27;s state. For React web applications, <a href="https://twitter.com/dan_abramov" target="_blank">Dan Abramov</a> implemented a babel <a href="http://gaearon.github.io/react-hot-loader/" target="_blank">transform</a> that uses Webpack&#x27;s HMR API to solve this issue. In a nutshell, his solution works by creating a proxy for every single React component on <em>transform time</em>. The proxies hold the component&#x27;s state and delegate the lifecycle methods to the actual components, which are the ones we hot reload:</p><p><img src="/react-native/blog/img/hmr-proxy.png" alt=""></p><p>Besides creating the proxy component, the transform also defines the <code>accept</code> function with a piece of code to force React to re-render the component. This way, we can hot reload rendering code without losing any of the app&#x27;s state.</p><p>The default <a href="https://github.com/facebook/react-native/blob/master/packager/transformer.js#L92-L95" target="_blank">transformer</a> that comes with React Native uses the <code>babel-preset-react-native</code>, which is <a href="https://github.com/facebook/react-native/blob/master/babel-preset/configs/hmr.js#L24-L31" target="_blank">configured</a> to use <code>react-transform</code> the same way you&#x27;d use it on a React web project that uses Webpack.</p><h2><a class="anchor" name="redux-stores"></a>Redux Stores <a class="hash-link" href="#redux-stores">#</a></h2><p>To enable Hot Reloading on <a href="http://redux.js.org/" target="_blank">Redux</a> stores you will just need to use the HMR API similarly to what you&#x27;d do on a web project that uses Webpack:</p><div class="prism language-javascript"><span class="token comment" spellcheck="true">// configureStore.js
</span>import <span class="token punctuation">{</span> createStore<span class="token punctuation">,</span> applyMiddleware<span class="token punctuation">,</span> compose <span class="token punctuation">}</span> from <span class="token string">&#x27;redux&#x27;</span><span class="token punctuation">;</span>
import thunk from <span class="token string">&#x27;redux-thunk&#x27;</span><span class="token punctuation">;</span>
import reducer from <span class="token string">&#x27;../reducers&#x27;</span><span class="token punctuation">;</span>
export default <span class="token keyword">function</span> <span class="token function">configureStore<span class="token punctuation">(</span></span>initialState<span class="token punctuation">)</span> <span class="token punctuation">{</span>
const store <span class="token operator">=</span> <span class="token function">createStore<span class="token punctuation">(</span></span>
reducer<span class="token punctuation">,</span>
initialState<span class="token punctuation">,</span>
<span class="token function">applyMiddleware<span class="token punctuation">(</span></span>thunk<span class="token punctuation">)</span><span class="token punctuation">,</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span> <span class="token punctuation">{</span>
module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept<span class="token punctuation">(</span></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=</span><span class="token operator">&gt;</span> <span class="token punctuation">{</span>
const nextRootReducer <span class="token operator">=</span> <span class="token function">require<span class="token punctuation">(</span></span><span class="token string">&#x27;../reducers/index&#x27;</span><span class="token punctuation">)</span><span class="token punctuation">.</span>default<span class="token punctuation">;</span>
store<span class="token punctuation">.</span><span class="token function">replaceReducer<span class="token punctuation">(</span></span>nextRootReducer<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> store<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span></div><p>When you change a reducer, the code to accept that reducer will be sent to the client. Then the client will realize that the reducer doesn&#x27;t know how to accept itself, so it will look for all the modules that refer it and try to accept them. Eventually, the flow will get to the single store, the <code>configureStore</code> module, which will accept the HMR update.</p><h2><a class="anchor" name="conclusion"></a>Conclusion <a class="hash-link" href="#conclusion">#</a></h2><p>If you are interested in helping making hot reloading better, I encourage you to read <a href="https://medium.com/@dan_abramov/hot-reloading-in-react-1140438583bf#.jmivpvmz4" target="_blank">Dan Abramov&#x27;s post around the future of hot reloading</a> and to contribute. For example, Johny Days is going to <a href="https://github.com/facebook/react-native/pull/6179" target="_blank">make it work with multiple connected clients</a>. We&#x27;re relying on you all to maintain and improve this feature.</p><p>With React Native, we have the opportunity to rethink the way we build apps in order to make it a great developer experience. Hot reloading is only one piece of the puzzle, what other crazy hacks can we do to make it better?</p></div></div><div class="docs-prevnext"></div></div></section><footer class="wrap"><div class="center">© 2016 Facebook Inc.</div></footer></div><div id="fb-root"></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-41298772-2', 'facebook.github.io');
ga('send', 'pageview');
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)
){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
docsearch({
apiKey: '2c98749b4a1e588efec53b2acec13025',
indexName: 'react-native-versions',
inputSelector: '#algolia-doc-search',
algoliaOptions: { facetFilters: [ "tags:master" ], hitsPerPage: 5 }
});
</script><script src="js/scripts.js"></script></body></html>
-1
View File
@@ -973,7 +973,6 @@ small code, li code, p code {
}
.modal-button-open-img {
background: #05A5D1;
height: 358px;
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+16 -13
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+6 -5
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+7 -6
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -3
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+25 -3
View File
File diff suppressed because one or more lines are too long
+7 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
File diff suppressed because one or more lines are too long
+4 -4
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3 -3
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More