1"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[374],{51709:function(e,n,a){a.r(n),a.d(n,{Head:function(){return g},default:function(){return m}});var s=a(28453),t=a(96540);function l(e){const n=Object.assign({h1:"h1",a:"a",span:"span",blockquote:"blockquote",p:"p",strong:"strong",h2:"h2",ol:"ol",li:"li",h3:"h3",h4:"h4"},(0,s.R)(),e.components);return t.createElement(t.Fragment,null,t.createElement(n.h1,{id:"bundle-caching",style:{position:"relative"}},t.createElement(n.a,{href:"#bundle-caching","aria-label":"bundle caching permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Bundle Caching"),"\n",t.createElement(n.blockquote,null,"\n",t.createElement(n.p,null,t.createElement(n.strong,null,"Pro Feature")," â Available with ",t.createElement(n.a,{href:"/linked-assets/5f3eacdd52b97cebdce257aa7836a6e1/react-on-rails-pro.md"},"React on Rails Pro"),".\nFree in development, test, CI, and staging, and in production for small organizations, charities, schools, and hospitals; larger organizations subscribe at ",t.createElement(n.a,{href:"https://pro.reactonrails.com/"},"https://pro.reactonrails.com/")," ($1,800 per year per organization). No license key is needed to run Pro."),"\n"),"\n",t.createElement(n.p,null,"Bundle caching avoids redundant webpack builds by caching bundles based on a digest of source files."),"\n",t.createElement(n.h2,{id:"why",style:{position:"relative"}},t.createElement(n.a,{href:"#why","aria-label":"why permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Why?"),"\n",t.createElement(n.p,null,"Building webpack bundles is often time-consuming, and the same bundles are built many times.\nFor example, you might build the production bundles during CI, then for a Review app, then\nfor Staging, and maybe even for Production. Or you might want to deploy a small Ruby-only\nchange to production, but you will have to wait minutes for your bundles to be built again."),"\n",t.createElement(n.h2,{id:"solution",style:{position:"relative"}},t.createElement(n.a,{href:"#solution","aria-label":"solution permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Solution"),"\n",t.createElement(n.p,null,"React on Rails 2.1.0 introduces bundle caching based on a digest of all the source files, defined\nin the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config/shakapacker.yml</code>'}})," file, plus other files defined with ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.dependency_globs</code>'}})," and\nexcluding any files from ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.excluded_dependency_globs</code>'}}),". Creating this hash key takes at most a\nfew seconds for even large projects. Additionally, the cache key includes"),"\n",t.createElement(n.ol,null,"\n",t.createElement(n.li,null,"NODE_ENV"),"\n",t.createElement(n.li,null,"Version of React on Rails Pro"),"\n",t.createElement(n.li,null,"Configurable additional env values by supplying an array in method cache_keys on the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">remote_bundle_cache_adapter</code>'}}),". See examples below."),"\n"),"\n",t.createElement(n.p,null,"This cache key is used for saving files to some remote storage, typically S3."),"\n",t.createElement(n.h2,{id:"bonus-for-local-development-with-multiple-directories-building-production-builds",style:{position:"relative"}}
1,t.createElement(n.a,{href:"#bonus-for-local-development-with-multiple-directories-building-production-builds","aria-label":"bonus for local development with multiple directories building production builds permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Bonus for local development with multiple directories building production builds"),"\n",t.createElement(n.p,null,"Bundle caching can help save time if you have multiple directories for the same repository."),"\n",t.createElement(n.p,null,"The bundles are cached in ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">Rails.root.join('tmp', 'bundle_cache')</code>"}})),"\n",t.createElement(n.p,null,"So, if you have sibling directories for the same project, you can make a sym link so both directories use the same bundle cache directory."),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="bash"><pre class="language-bash"><code class="language-bash"><span class="token builtin class-name">cd</span> my_project2/tmp\n<span class="token function">ln</span> <span class="token parameter variable">-s</span> <span class="token punctuation">..</span>/<span class="token punctuation">..</span>/my_project/tmp/bundle_cache</code></pre></div>'}}),"\n",t.createElement(n.h2,{id:"configuration",style:{position:"relative"}},t.createElement(n.a,{href:"#configuration","aria-label":"configuration permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Configuration"),"\n",t.createElement(n.h3,{id:"1-react-on-rails-configuration",style:{position:"relative"}},t.createElement(n.a,{href:"#1-react-on-rails-configuration","aria-label":"1 react on rails configuration permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"1. React on Rails Configuration"),"\n",t.createElement(n.p,null,"First, we need to tell React on Rails to use a custom build module. In\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config/initializers/react_on_rails</code>'}}),", set this value:"),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby">config<span class="token punctuation">.</span>build_production_command <span class="token operator">=</span> ReactOnRailsPro<span class="token double-colon punctuation">::</span>AssetsPrecompile</code></pre></div>'}}),"\n",t.createElement(n.p,null,"Alternatively, if you need to run something after the files are built or extracted from the cache, you can do something like this:"),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby">ReactOnRails<span class="token punctuation">.</span>configure <span class="token keyword">do</span> <span class="token operator">|</span>config<span class="token operator">|</span>\n <span class="token comment"># This configures the script to run to build the production assets by webpack. Set this to nil</span>\n <span class="token comment"># if you don\'t want react_on_rails building this file for you.</span>\n config<span class="token punctuation">.</span>build_production_command <span class="token operator">=</span> CustomBuildCommand\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(n.p,null,"And define it like this:"),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">module</span> <span class="token class-name">CustomBuildCommand</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">
1self</span><span class="token punctuation">.</span><span class="token function">call</span></span>\n ReactOnRailsPro<span class="token double-colon punctuation">::</span>AssetsPrecompile<span class="token punctuation">.</span>call\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(n.h3,{id:"2-react-on-rails-pro-configuration",style:{position:"relative"}},t.createElement(n.a,{href:"#2-react-on-rails-pro-configuration","aria-label":"2 react on rails pro configuration permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"2. React on Rails Pro Configuration"),"\n",t.createElement(n.p,null,"Next, we need to configure the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config/initializers/react_on_rails_pro.rb</code>'}})," with some module,\nsay called S3BundleCacheAdapter."),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby">config<span class="token punctuation">.</span>remote_bundle_cache_adapter <span class="token operator">=</span> S3BundleCacheAdapter</code></pre></div>'}}),"\n",t.createElement(n.p,null,"This module needs four class methods: ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">cache_keys</code>'}})," (optional), ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">build</code>'}}),", ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">fetch</code>'}}),", ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">upload</code>'}}),". See two\nexamples of this below."),"\n",t.createElement(n.p,null,"Also, add whatever file the remote_bundle_cache_adapter module is defined in to ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.dependency_globs</code>'}}),"."),"\n",t.createElement(n.p,null,"If there are any other files for which changes should bust the fragment cache for\ncached_react_component and cached_react_component_hash, add those as well to ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.dependency_globs</code>'}}),". This should include any files used to generate the JSON props, webpack and/or Shakapacker configuration files, and package lockfiles."),"\n",t.createElement(n.p,null,"To simplify your configuration, entire directories can be added to ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.dependency_globs</code>'}})," & then any irrelevant files or subdirectories can be added to ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.excluded_dependency_globs</code>'}})),"\n",t.createElement(n.p,null,"For example:"),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"> config<span class="token punctuation">.</span>dependency_globs <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token builtin">File</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>Rails<span class="token punctuation">.</span>root<span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"app"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"views"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"**"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"*.jbuilder"</span></span><span class="token punctuation">)</span> <span class="token punctuation">]</span>\n config<span class="token punctuation">.</span>excluded_dependency_globs <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token builtin">File</span><span class="token punctuation">.</span>join<span class="token punctuation">(</span>Rails<span class="token punctuation">.</span>root<span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"app"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"views"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"**"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"dont_hash_this.jbuilder"</span></span><span class="token punctuation">)</span> <span class="token punctuation">]</span></code></pre></div>'}}),"\n",t.createElement(n.p,null,"will hash all files in ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">app/views</code>'}})," that have the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">jbuilder</code>'}})," extension except for any file named ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">dont_hash_this.jbuilder</code>'}}),"."),"\n",t.createElement(n.p,null,"The goal is that Ruby only changes that don't affect your webpack bundles don't change the cache keys, and anything that could affect the bundles MUST change the cache keys!"),"\n",t.createElement(n.h3,{id:"3-remove-any-call-to-rake-task-react_on_rails_propre_stage_bundle_for_node_renderer",style:{position:"relative"}}
1,t.createElement(n.a,{href:"#3-remove-any-call-to-rake-task-react_on_rails_propre_stage_bundle_for_node_renderer","aria-label":"3 remove any call to rake task react_on_rails_propre_stage_bundle_for_node_renderer permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"3. Remove any call to rake task ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_on_rails_pro:pre_stage_bundle_for_node_renderer</code>'}})),"\n",t.createElement(n.p,null,"This task is called automatically if you're using bundle caching. The automatic staging uses the same bundle-hash cache layout as the renderer's runtime upload flow and the copy-based ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_on_rails_pro:pre_seed_renderer_cache</code>'}})," task used for Docker/image-build workflows."),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"> <span class="token comment"># Remove this line â pre-staging is now automatic when bundle caching is enabled.</span>\n Rake<span class="token double-colon punctuation">::</span>Task<span class="token punctuation">[</span><span class="token string-literal"><span class="token string">\'react_on_rails_pro:pre_stage_bundle_for_node_renderer\'</span></span><span class="token punctuation">]</span><span class="token punctuation">.</span>invoke</code></pre></div>'}}),"\n",t.createElement(n.h4,{id:"custom-env-cache-keys",style:{position:"relative"}},t.createElement(n.a,{href:"#custom-env-cache-keys","aria-label":"custom env cache keys permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Custom ENV cache keys"),"\n",t.createElement(n.p,null,"Check your webpack config for the webpack.DefinePlugin. That allows JS code to use\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">process.env.MY_ENV_VAR</code>'}})," resulting in bundles that differ depending on the ENV value set."),"\n",t.createElement(n.p,null,"Thus, if you access these ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">process.env.MY_ENV_VAR</code>'}})," in your JS code, then you need to include such\nENV vars in return value of the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">cache keys</code>'}})," method."),"\n",t.createElement(n.p,null,"A much better approach than accessing ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">process.env</code>'}})," is to use the\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config/initializers/react_on_rails.rb</code>'}})," setting for the",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">config.rendering_extension</code>'}})," to always\npass some values into the rendering props."),"\n",t.createElement(n.p,null,"See ",t.createElement(n.a,{href:"/linked-assets/437539654674ca3b3c8e166e0056e147/render-functions-and-railscontext.md"},"our railsContext docs")," for more details."),"\n",t.createElement(n.p,null,"Also, if your webpack build process depends on any ENV values, then you will also need to add those\nto return value of the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">cache_keys</code>'}})," method."),"\n",t.createElement(n.p,null,"Note, the NODE_ENV value is always included in the cache_keys."),"\n",t.createElement(n.p,null,"Another use of the ENV values would be a cache version, so incrementing this ENV value\
1nwould force a new cache value."),"\n",t.createElement(n.h2,{id:"disabling-via-an-env-value",style:{position:"relative"}},t.createElement(n.a,{href:"#disabling-via-an-env-value","aria-label":"disabling via an env value permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Disabling via an ENV value"),"\n",t.createElement(n.p,null,'Once configured for bundle caching, ReactOnRailsPro::AssetsPrecompile\'s caching functionality\ncan be disabled by setting ENV["DISABLE_PRECOMPILE_CACHE"] equal to "true"'),"\n",t.createElement(n.h2,{id:"examples-of-remote_bundle_cache_adapter",style:{position:"relative"}},t.createElement(n.a,{href:"#examples-of-remote_bundle_cache_adapter","aria-label":"examples of remote_bundle_cache_adapter permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Examples of ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">remote_bundle_cache_adapter</code>'}}),":"),"\n",t.createElement(n.h3,{id:"s3bundlecacheadapter",style:{position:"relative"}},t.createElement(n.a,{href:"#s3bundlecacheadapter","aria-label":"s3bundlecacheadapter permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"S3BundleCacheAdapter"),"\n",t.createElement(n.p,null,"Example of a module for custom methods for the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">remote_bundle_cache_adapter</code>'}}),"."),"\n",t.createElement(n.p,null,"Note, S3UploadService is your own code that fetches and uploads."),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">S3BundleCacheAdapter</span>\n <span class="token comment"># Optional</span>\n <span class="token comment"># return an Array of Strings that should get added to the cache key.</span>\n <span class="token comment"># These are values to put in the cache key based on either using the webpack.DefinePlugin</span>\n <span class="token comment"># or webpack compilation varying by the ENV values.</span>\n <span class="token comment"># See the use of the webpack.DefinePlugin. That allows JS code to use</span>\n <span class="token comment"># process.env.MY_ENV_VAR resulting in bundles that differ depending on the ENV value set</span>\n <span class="token comment"># when building the bundles.</span>\n <span class="token comment"># Note, NODE_ENV is automatically included in the default cache key.</span>\n <span class="token comment"># Also, we can have an ENV value be a cache version, so incrementing this ENV value</span>\n <span class="token comment"># would force a new cache value.</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">
1self</span><span class="token punctuation">.</span><span class="token function">cache_keys</span></span>\n <span class="token punctuation">[</span>Rails<span class="token punctuation">.</span>env<span class="token punctuation">,</span> <span class="token constant">ENV</span><span class="token punctuation">[</span><span class="token string-literal"><span class="token string">\'SOME_ENV_VALUE\'</span></span><span class="token punctuation">]</span><span class="token punctuation">]</span>\n <span class="token keyword">end</span>\n\n <span class="token comment"># return value is unused</span>\n <span class="token comment"># This command should build the bundles</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">build</span></span>\n Rake<span class="token punctuation">.</span>sh<span class="token punctuation">(</span>ReactOnRails<span class="token double-colon punctuation">::</span>Utils<span class="token punctuation">.</span>prepend_cd_node_modules_directory<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">\'yarn start build.prod\'</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span>to_s<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n\n <span class="token comment"># parameter zipped_bundles_filename will be a string</span>\n <span class="token comment"># should return the zipped file as a string if successful & nil if not</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">fetch</span></span><span class="token punctuation">(</span><span class="token symbol">zipped_bundles_filename</span><span class="token operator">:</span><span class="token punctuation">)</span>\n result <span class="token operator">=</span> <span class="token class-name">S3UploadService</span><span class="token punctuation">.</span><span class="token keyword">new</span><span class="token punctuation">.</span>fetch_object<span class="token punctuation">(</span>zipped_bundles_filename<span class="token punctuation">)</span>\n result<span class="token punctuation">.</span>get<span class="token punctuation">.</span>body<span class="token punctuation">.</span>read <span class="token keyword">if</span> result\n <span class="token keyword">end</span>\n\n <span class="token comment"># Optional: method to return an array of extra files paths, that require caching.</span>\n <span class="token comment"># These files get placed at the `extra_files` directory at the top of the zipfile</span>\n <span class="token comment"># and are moved to the original places after unzipping the bundles.</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">extra_files_to_cache</span></span>\n <span class="token punctuation">[</span> Rails<span class="token punctuation">.</span>root<span class="token punctuation">.</span>join<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">"app"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"javascript"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"utils"</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"operationStore.json"</span></span><span class="token punctuation">)</span> <span class="token punctuation">]</span>\n <span class="token keyword">end</span>\n\n <span class="token comment"># parameter zipped_bundles_filepath will be a Pathname</span>\n <span class="token comment"># return value is unused</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">
1self</span><span class="token punctuation">.</span><span class="token function">upload</span></span><span class="token punctuation">(</span><span class="token symbol">zipped_bundles_filepath</span><span class="token operator">:</span><span class="token punctuation">)</span>\n <span class="token keyword">return</span> <span class="token keyword">unless</span> <span class="token constant">ENV</span><span class="token punctuation">[</span><span class="token string-literal"><span class="token string">\'UPLOAD_BUNDLES_TO_S3\'</span></span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string-literal"><span class="token string">\'true\'</span></span>\n\n zipped_bundles_filename <span class="token operator">=</span> zipped_bundles_filepath<span class="token punctuation">.</span>basename<span class="token punctuation">.</span>to_s\n puts <span class="token string-literal"><span class="token string">"Bundles are being uploaded to s3 as </span><span class="token interpolation"><span class="token delimiter punctuation">#{</span><span class="token content">zipped_bundles_filename</span><span class="token delimiter punctuation">}</span></span><span class="token string">"</span></span>\n starting <span class="token operator">=</span> Process<span class="token punctuation">.</span>clock_gettime<span class="token punctuation">(</span>Process<span class="token double-colon punctuation">::</span><span class="token constant">CLOCK_MONOTONIC</span><span class="token punctuation">)</span>\n <span class="token class-name">S3UploadService</span><span class="token punctuation">.</span><span class="token keyword">new</span><span class="token punctuation">.</span>upload_object<span class="token punctuation">(</span>zipped_bundles_filename<span class="token punctuation">,</span>\n <span class="token builtin">File</span><span class="token punctuation">.</span>read<span class="token punctuation">(</span>zipped_bundles_filepath<span class="token punctuation">,</span> <span class="token symbol">mode</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">\'rb\'</span></span><span class="token punctuation">)</span><span class="token punctuation">,</span>\n <span class="token string-literal"><span class="token string">\'application/zip\'</span></span><span class="token punctuation">,</span> <span class="token symbol">expiration_months</span><span class="token operator">:</span> <span class="token number">12</span><span class="token punctuation">)</span>\n ending <span class="token operator">=</span> Process<span class="token punctuation">.</span>clock_gettime<span class="token punctuation">(</span>Process<span class="token double-colon punctuation">::</span><span class="token constant">CLOCK_MONOTONIC</span><span class="token punctuation">)</span>\n elapsed <span class="token operator">=</span> <span class="token punctuation">(</span>ending <span class="token operator">-</span> starting<span class="token punctuation">)</span><span class="token punctuation">.</span>round<span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span>\n puts <span class="token string-literal"><span class="token string">"Bundles uploaded to s3 as </span><span class="token interpolation"><span class="token delimiter punctuation">#{</span><span class="token content">zipped_bundles_filename</span><span class="token delimiter punctuation">}</span></span><span class="token string"> in </span><span class="token interpolation"><span class="token delimiter punctuation">#{</span><span class="token content">elapsed</span><span class="token delimiter punctuation">}</span></span><span class="token string"> seconds"</span></span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(n.h3,{id:"localbundlecacheadapter",style:{position:"relative"}},t.createElement(n.a,{href:"#localbundlecacheadapter","aria-label":"localbundlecacheadapter permalink",className:"anchor before"},t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"LocalBundleCacheAdapter"),"\n",t.createElement(n.p,null,"Example of a module for custom methods for the ",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">remote_bundle_cache_adapter</code>'}})," that does not save files\nremotely. Only local files are used."),"\n",t.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">LocalBundleCacheAdapter</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">
1self</span><span class="token punctuation">.</span><span class="token function">cache_keys</span></span>\n <span class="token comment"># if no additional cache keys, return an empty array</span>\n <span class="token punctuation">[</span><span class="token punctuation">]</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">build</span></span>\n Rake<span class="token punctuation">.</span>sh<span class="token punctuation">(</span>ReactOnRails<span class="token double-colon punctuation">::</span>Utils<span class="token punctuation">.</span>prepend_cd_node_modules_directory<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">\'yarn start build.prod\'</span></span><span class="token punctuation">)</span><span class="token punctuation">.</span>to_s<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">fetch</span></span><span class="token punctuation">(</span><span class="token symbol">zipped_bundles_filename</span><span class="token operator">:</span><span class="token punctuation">)</span>\n <span class="token comment"># no-op</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token function">upload</span></span><span class="token punctuation">(</span><span class="token symbol">zipped_bundles_filepath</span><span class="token operator">:</span><span class="token punctuation">)</span>\n <span class="token comment"># no-op</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}))}var o=function(e){void 0===e&&(e={});const{wrapper:n}=Object.assign({},(0,s.R)(),e.components);return n?t.createElement(n,e,t.createElement(l,e)):l(e)},c=a(63679),p=a(95197),r=a(47388),i=a(23690),u=a(14487);const d=c.default.p.withConfig({displayName:"doc-article__RedirectFallback",componentId:"sc-tic2w5-0"})(["padding:2rem;"]),h=e=>{let{data:n,location:a,children:s}=e;const{headings:l}=n.article.childMdx,o=(0,p.X9)(a.pathname),[c,i]=t.useState(null),h=a.pathname.split("/"),m=h.indexOf("docs"),g=-1===m?a.pathname.length:h.slice(0,m+1).join("/").length,k=a.pathname.slice(0,g),_=a.pathname.slice(g+1).replace(/\/$/,"").split("/").filter((e=>""!==e)),f=_.length>1?_.slice(0,-1).join("/"):"";t.useEffect((()=>{if(!o)return;const{hash:e}=window.location;i(e);const n=""+o+e;window.location.href!==n&&window.location.replace(n)}),[o]);const y=null===o||null===c?null:""+o+c;return t.createElement(t.Fragment,null,null!==y?t.createElement(d,{role:"status","aria-live":"polite"},"Redirecting..."," ",t.createElement("a",{href:y,target:"_blank",rel:"noopener noreferrer"},"Click here if not redirected.")):t.createElement(r.A,{main:t.createElement(u.A,{body:s,headings:l,transformUrl:e=>{if(e.startsWith("http")||e.startsWith("#"))return e;const n=e.replace(/\.md$/,"/");if(n.startsWith("./"))return k+(""===f?"":"/"+f)+n.slice(1);if(n.startsWith("../")){if(""===f)return""+k+n.slice(2);const e=f.split("/").slice(0,-1).join("/");return k+(""===e?"":"/"+e)+n.slice(2)}return k+"/"+(""===f?"":f+"/")+n}})}))};function m(e){return t.createElement(h,e,t.createElement(o,e))}const g=e=>{let{data:n,location:a,pageContext:s}=e;const{headings:l}=n.article.childMdx,{siteUrl:o}=n.site.siteMetadata,{repoDisplayName:c}=s,r=l.find((e=>1===e.depth)),u=(0,p.X9)(a.pathname)||""+o.replace(/\/+$/,"")+a.pathname;return t.createElement(i.A,{title:r?r.value:c,description:r?r.value:c+" documentation",isArticle:!0,canonical:u,pathname:a.pathname})}}}]); 2//# sourceMappingURL=component---src-template-doc-article-tsx-content-file-path-cache-gatsby-source-git-react-on-rails-docs-oss-building-features-bundle-caching-md-191acc3df66f64945f08.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.