PageSourceSearch

https://shakacode.com/component---src-template-doc-article-tsx-con…tures-turbolinks-md-a5cb79de7453368ba285.js

js shakacode.com collected 2026-10-04 00:29:12 UTC 60,698 bytes, 2 lines download raw bytes

1"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[3563],{92592:function(e,n,a){a.r(n),a.d(n,{Head:function(){return h},default:function(){return m}});var t=a(28453),s=a(96540);function l(e){const n=Object.assign({h1:"h1",a:"a",span:"span",h2:"h2",ul:"ul",li:"li",p:"p",h3:"h3",strong:"strong",ol:"ol",blockquote:"blockquote",em:"em",h4:"h4",h5:"h5",div:"div",svg:"svg",path:"path",img:"img"},(0,t.R)(),e.components);return s.createElement(s.Fragment,null,s.createElement(n.h1,{id:"turbolinks-and-turbo-support",style:{position:"relative"}},s.createElement(n.a,{href:"#turbolinks-and-turbo-support","aria-label":"turbolinks and turbo support permalink",className:"anchor before"},s.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>'}})),"Turbolinks and Turbo Support"),"\n",s.createElement(n.h2,{id:"react-on-rails-updated-to-support-turbo-august-2024",style:{position:"relative"}},s.createElement(n.a,{href:"#react-on-rails-updated-to-support-turbo-august-2024","aria-label":"react on rails updated to support turbo august 2024 permalink",className:"anchor before"},s.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>'}})),"React on Rails Updated to support Turbo, August 2024"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,"See ",s.createElement(n.a,{href:"https://github.com/shakacode/react_on_rails/pull/1620"},"PR 1620"),"."),"\n",s.createElement(n.li,null,"See ",s.createElement(n.a,{href:"https://github.com/shakacode/react_on_rails/pull/1374"},"PR 1374"),"."),"\n",s.createElement(n.li,null,"Ability to use with ",s.createElement(n.a,{href:"https://turbo.hotwired.dev/"},"Turbo (",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">@hotwired/turbo</code>'}}),")"),", as Turbolinks becomes obsolete."),"\n"),"\n",s.createElement(n.h2,{id:"using-turbo",style:{position:"relative"}},s.createElement(n.a,{href:"#using-turbo","aria-label":"using turbo permalink",className:"anchor before"},s.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>'}})),"Using Turbo"),"\n",s.createElement(n.p,null,"Turbo is the modern replacement for Turbolinks, providing fast navigation through your Rails app without full page reloads."),"\n",s.createElement(n.h3,{id:"basic-setup",style:{position:"relative"}},s.createElement(n.a,{href:"#basic-setup","aria-label":"basic setup permalink",className:"anchor before"},s.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>'}})),"Basic Setup"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"1. Install Turbo")),"\n",s.createElement(n.p,null,"Add the Turbo Rails gem and JavaScript package:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="bash"><pre class="language-bash"><code class="language-bash"><span class="token comment">
1# Gemfile</span>\ngem <span class="token string">"turbo-rails"</span>\n\n<span class="token comment"># JavaScript</span>\n<span class="token function">yarn</span> <span class="token function">add</span> @hotwired/turbo-rails\n<span class="token comment"># or: npm install @hotwired/turbo-rails</span>\n<span class="token comment"># or: pnpm add @hotwired/turbo-rails</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"2. Enable Turbo in React on Rails")),"\n",s.createElement(n.p,null,"Import Turbo and configure React on Rails to work with it:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token comment">// app/javascript/packs/application.js</span>\n<span class="token keyword">import</span> <span class="token string">\'@hotwired/turbo-rails\'</span><span class="token punctuation">;</span>\n\nReactOnRails<span class="token punctuation">.</span><span class="token function">setOptions</span><span class="token punctuation">(</span><span class="token punctuation">{</span>\n  <span class="token literal-property property">turbo</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token comment">// Enable Turbo support (not auto-detected)</span>\n<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"3. Use Turbo Frames")," (works out of the box)"),"\n",s.createElement(n.p,null,"Turbo Frames work with React components without any special configuration:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb"><span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># app/views/items/index.html.erb </span></span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> turbo_frame_tag <span class="token string-literal"><span class="token string">\'item-list\'</span></span> <span class="token keyword">do</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> react_component<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">"ItemList"</span></span><span class="token punctuation">,</span> <span class="token symbol">props</span><span class="token operator">:</span> <span class="token variable">@items</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"> <span class="token keyword">end</span> </span><span class="token delimiter punctuation">%></span></span>\n\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Clicking a link that responds with another turbo_frame_tag will update just that frame </span></span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.h3,{id:"turbo-with-auto-bundling",style:{position:"relative"}},s.createElement(n.a,{href:"#turbo-with-auto-bundling","aria-label":"turbo with auto bundling permalink",className:"anchor before"},s.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>'}})),"Turbo with Auto-Bundling"),"\n",s.createElement(n.p,null,"When using React on Rails' ",s.createElement(n.a,{href:"/linked-assets/68f6de8da33e5ea5631565673247b660/auto-bundling-file-system-based-automated-bundle-generation.md"},"auto-bundling feature")," (",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">auto_load_bundle: true</code>'}}),") with Turbo, there's a specific ordering requirement to address:"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"The Challenge:")),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Turbo's requirement"),": Turbo must be loaded in the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;head></code>'}})," to avoid script re-evaluation warnings during page navigation"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Auto-registration's behavior"),": ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})," with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">auto_load_bundle: true</code>'}})," calls ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">append_javascript_pack_tag</code>'}})," during body rendering"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Shakapacker's requirement"),": All ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">append_javascript_pack_tag</code>'}})," calls must occur before the final ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">javascript_pack_tag</code>'}})),"\n"),"\n",s.createElement(n.p,null,"This creates a conflict: the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;head></code>'}})," (with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">javascript_pack_tag</code>'}}),") renders before the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;body></code>'}})," (where ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})," triggers auto-appends)."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"The Solution: ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">content_for :body_content</code>'}})," Pattern")),"\n",s.createElement(n.p,null,"Use ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">content_for</code>'}})," to render your body content first, capturing auto-appends before the head renders:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb"><span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Step 1: Capture body content FIRST - this triggers all auto-appends </span></span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"> content_for <span class="token symbol">:body_content</span> <span class="token keyword">do</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> react_component <span class="token string-literal"><span class="token string">"NavigationBarApp"</span></span><span class="token punctuation">,</span> <span class="token symbol">prerender</span><span class="token operator">:</span> <span class="token boolean">true</span> </span><span class="token delimiter punctuation">%></span></span>\n\n  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>\n    <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> <span class="token keyword">yield</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>\n\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> react_component <span class="token string-literal"><span class="token string">"Footer"</span></span><span class="token punctuation">,</span> <span class="token symbol">prerender</span><span class="token operator">:</span> <span class="token boolean">true</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> redux_store_hydration_data </span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"> <span class="token keyword">end</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span><span class="token punctuation">></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> csrf_meta_tags </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> csp_meta_tag </span><span class="token delimiter punctuation">%></span></span>\n\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Optional: Explicitly load non-React packs (Stimulus, shared stores, etc.) </span></span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># React component bundles are already auto-appended by react_component calls above </span></span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Do NOT manually append component bundles here - they\'re already included </span></span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> append_stylesheet_pack_tag<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">\'stimulus-bundle\'</span></span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> append_javascript_pack_tag<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">\'stimulus-bundle\'</span></span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> append_javascript_pack_tag<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">\'stores-registration\'</span></span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Step 2: Pack tags now include all component bundles from auto-appends above </span></span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> stylesheet_pack_tag<span class="token punctuation">(</span><span class="token symbol">media</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">\'all\'</span></span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> javascript_pack_tag<span class="token punctuation">(</span><span class="token symbol">defer</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># Step 3: Output the captured body content </span></span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> <span class="token keyword">yield</span> <span class="token symbol">:body_content</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span>\n<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Why This Works:")),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,"Rails processes the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">content_for</code>'}})," block first, which executes all ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})," calls"),"\n",s.createElement(n.li,null,"Each ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})," with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">auto_load_bundle: true</code>'}})," triggers ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">append_javas
1cript_pack_tag</code>'}})),"\n",s.createElement(n.li,null,"When the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;head></code>'}})," renders, ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">javascript_pack_tag</code>'}})," includes all accumulated appends"),"\n",s.createElement(n.li,null,"Turbo loads early in ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;head></code>'}}),", satisfying its requirement"),"\n",s.createElement(n.li,null,"Component bundles load in the correct order"),"\n"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Note:")," While defining body content before ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">&lt;!DOCTYPE html></code>'}})," may look unusual, Rails processes ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">content_for</code>'}})," blocks during template evaluation, not document output order. The final HTML is correctly structured."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Common Pitfalls:")),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,"❌ Don't place ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">javascript_pack_tag</code>'}})," before ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">content_for</code>'}})," blocks that call ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})),"\n",s.createElement(n.li,null,"❌ Don't manually append component bundles if using ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">auto_load_bundle: true</code>'}})),"\n",s.createElement(n.li,null,"✅ Do let ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_component</code>'}})," handle bundle appending automatically"),"\n"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Additional Resources:")),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"https://github.com/shakacode/shakapacker/blob/main/docs/preventing_fouc.md#the-content_for-body_content-pattern"},"Shakapacker Preventing FOUC guide")),"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"https://turbo.hotwired.dev/handbook/building#working-with-script-elements"},"Turbo Handbook - Working with Script Elements")),"\n"),"\n",s.createElement(n.h3,{id:"turbo-streams-requires-react-on-rails-pro",style:{position:"relative"}},s.createElement(n.a,{href:"#turbo-streams-requires-react-on-rails-pro","aria-label":"turbo streams requires react on rails pro permalink",className:"anchor before"},s.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>'}})),"Turbo Streams (Requires React on Rails Pro)"),"\n",s.createElement(n.blockquote,null,"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"⚡️ React on Rails Pro Feature")),"\n",s.createElement(n.p,null,"Turbo Streams rely on Pro's early hydration behavior, which hydrates components as soon as they are inserted into the DOM. This is a ",s.createElement(n.a,{href:"/linked-assets/5f3eacdd52b97cebdce257aa7836a6e1/react-on-rails-pro.md"},"React on Rails Pro")," licensed feature that is always on for Pro users."),"\n"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Why Turbo Streams Need Special Handling:")),"\n",s.createElement(n.p,null,"Unlike Turbo Frames, Turbo Streams don't dispatch the normal ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">turbo:render</code>'}})," events that React on Rails uses to hydrate components. Instead, they directly manipulate the DOM. React on Rails Pro hydrates components immediately when they are inserted into the DOM, without waiting for page load events, so Turbo Stream updates work out of the box."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Example: Create a Turbo Stream Response")),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb"><span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># app/views/items/index.html.erb - Initial page with frame </span></span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> turbo_frame_tag <span class="token string-literal"><span class="token string">\'item-list\'</span></span> <span class="token keyword">do</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> button_to <span class="token string-literal"><span class="token string">"Load Items"</span></span><span class="token punctuation">,</span> items_path<span class="token punctuation">,</span> <span class="token symbol">method</span><span class="token operator">:</span> <span class="token symbol">:post</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"> <span class="token keyword">end</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb"><span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"><span class="token comment"># app/views/items/create.turbo_stream.erb - Turbo Stream response </span></span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> turbo_stream<span class="token punctuation">.</span>update <span class="token string-literal"><span class="token string">\'item-list\'</span></span> <span class="token keyword">do</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> react_component<span class="token punctuation">(</span><span class="token string-literal"><span class="token string">"ItemList"</span></span><span class="token punctuation">,</span> <span class="token symbol">props</span><span class="token operator">:</span> <span class="token variable">@items</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%</span><span class="token ruby language-ruby"> <span class="token keyword">end</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"What Happens:")),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,'User 
1clicks "Load Items" button'),"\n",s.createElement(n.li,null,"Rails responds with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">create.turbo_stream.erb</code>'}})),"\n",s.createElement(n.li,null,"Turbo Stream updates the ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">item-list</code>'}})," frame with the new React component"),"\n",s.createElement(n.li,null,"React on Rails Pro hydrates the inserted component immediately"),"\n"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Learn More:")),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,"See ",s.createElement(n.a,{href:"/linked-assets/36f649125c45c80a71092e7283f882be/streaming-server-rendering.md"},"Streaming Server Rendering")," for another Pro use case"),"\n",s.createElement(n.li,null,"Working example in codebase: ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">react_on_rails/spec/dummy/app/views/pages/turbo_stream_send_hello_world.turbo_stream.erb</code>'}})),"\n",s.createElement(n.li,null,"See ",s.createElement(n.a,{href:"https://pro.reactonrails.com/"},"pro.reactonrails.com")," for React on Rails Pro licensing"),"\n"),"\n",s.createElement(n.h2,{id:"legacy-turbolinks-support",style:{position:"relative"}},s.createElement(n.a,{href:"#legacy-turbolinks-support","aria-label":"legacy turbolinks support permalink",className:"anchor before"},s.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>'}})),"Legacy Turbolinks Support"),"\n",s.createElement(n.p,null,s.createElement(n.em,null,"The following documentation covers older Turbolinks versions (2.x and 5.x). While still supported by React on Rails, we recommend migrating to Turbo when possible.")),"\n",s.createElement(n.p,null,"React on Rails currently supports:"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Turbolinks 5.x")," (e.g., 5.0.0+) - Auto-detected"),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Turbolinks 2.x")," (Classic) - Auto-detected"),"\n",s.createElement(n.li,null,"See ",s.createElement(n.a,{href:"https://github.com/rails/turbolinks"},"Turbolinks on Github")),"\n"),"\n",s.createElement(n.p,null,"You may include Turbolinks either via npm/yarn/pnpm (recommended) or via the gem."),"\n",s.createElement(n.h3,{id:"why-turbolinks",style:{position:"relative"}},s.createElement(n.a,{href:"#why-turbolinks","aria-label":"why turbolinks permalink",className:"anchor before"},s.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 Turbolinks?"),"\n",s.createElement(n.p,null,"As you switch between Rails HTML controller requests, you will only load the HTML and you will not reload JavaScript and stylesheets.\nThis definitely can make an app perform better, even if the JavaScript and stylesheets are cached by the browser, as they will still require parsing."),"\n",s.createElement(n.h3,{id:"requirements-for-using-turbolinks",style:{position:"relative"}},s.createElement(n.a,{href:"#requirements-for-using-turbolinks","aria-label":"requirements for using turbolinks permalink",className:"anchor before"},s.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>'}})),"Requirements for Using Turbolinks"),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,"Either ",s.createElement(n.strong,null,"avoid using ",s.createElement(n.a,{href:"https://reactrouter.com/"},"React Router"))," or be prepared to deal with any conflicts between it and Turbolinks."),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Use one JS and one CSS file")," throughout your app. Otherwise, you will have to figure out how best to handle multiple JS and CSS files throughout the app given Turbolinks."),"\n"),"\n",s.createElement(n.h3,{id:"why-not-turbolinks",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#why-not-turbolinks","aria-label":"why not turbolinks permalink",className:"anchor before"},s.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 Not Turbolinks"),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,s.createElement(n.a,{href:"https://reactrouter.com/"},"React Router")," handles the back and forward buttons, as does Turbolinks. You ",s.createElement(n.em,null,"might")," be able to make this work. ",s.createElement(n.em,null,"Please share your findings.")),"\n",s.createElement(n.li,null,"You want to do code splitting to minimize the JavaScript loaded."),"\n"),"\n",s.createElement(n.h3,{id:"installation",style:{position:"relative"}},s.createElement(n.a,{href:"#installation","aria-label":"installation permalink",className:"anchor before"},s.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>'}})),"Installation"),"\n",s.createElement(n.h4,{id:"install-checklist",style:{position:"relative"}},s.createElement(n.a,{href:"#install-checklist","aria-label":"install checklist permalink",className:"anchor before"},s.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>'}})),"Install Checklist"),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,"Include turbolinks via your package manager as shown in the ",s.createElement(n.a,{href:"https://github.com/shakacode/react-webpack-rails-tutorial/blob/8a6c8aa2e3b7ae5b08b0a9744fb3a63a2fe0f002/client/webpack.client.base.config.js#L22"},"react-webpack-rails-tutorial"),' or include the gem "turbolinks".'),"\n",s.createElement(n.li,null,'Included the proper "track" tags when you include the javascript and stylesheet:'),"\n"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"For Turbolinks 5.x:")),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb">  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> stylesheet_link_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token symbol">media</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">\'all\'</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">\'data-turbolinks-track\'</span></span> <span class="token operator">=></span> <span class="token string-literal"><span class="token string">\'reload\'</span></span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> javascript_include_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">\'data-turbolinks-track\'</span></span> <span class="token operator">=></span> <span class="token string-literal"><span class="token string">
1\'reload\'</span></span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"For Turbolinks 2.x (Classic):")),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb">  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> stylesheet_link_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token symbol">media</span><span class="token operator">:</span> <span class="token string-literal"><span class="token string">\'all\'</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">\'data-turbolinks-track\'</span></span> <span class="token operator">=></span> <span class="token boolean">true</span> </span><span class="token delimiter punctuation">%></span></span>\n  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> javascript_include_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">\'data-turbolinks-track\'</span></span> <span class="token operator">=></span> <span class="token boolean">true</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Note:")," If you're using modern Turbo (recommended), use ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'data-turbo-track' => 'reload'</code>"}})," instead of ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:"<code class=\"language-text\">'data-turbolinks-track'</code>"}}),'. See the "Using Turbo" section at the top of this document.'),"\n",s.createElement(n.ol,null,"\n",s.createElement(n.li,null,"Add turbolinks to your ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">application.js</code>'}})," file:","\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="javascript"><pre class="language-javascript"><code class="language-javascript"><span class="token comment">//= require turbolinks</span></code></pre></div>'}}),"\n"),"\n"),"\n",s.createElement(n.h4,{id:"turbolinks-from-npm",style:{position:"relative"}},s.createElement(n.a,{href:"#turbolinks-from-npm","aria-label":"turbolinks from npm permalink",className:"anchor before"},s.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>'}})),"Turbolinks from NPM"),"\n",s.createElement(n.p,null,"See the ",s.createElement(n.a,{href:"https://github.com/turbolinks/turbolinks#installation-using-npm"},"instructions on installing from NPM"),"."),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">import</span> Turbolinks <span class="token keyword">from</span> <span class="token string">\'turbolinks\'</span><span class="token punctuation">;</span>\nTurbolinks<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.h5,{id:"async-script-loading",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#async-script-loading","aria-label":"async script loading permalink",className:"anchor before"},s.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>'}})),"Async script loading"),"\n",s.createElement(n.p,null,"Async script loading can be done like this (starting with Shakapacker 8.2):"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb">  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> javascript_include_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token symbol">async</span><span class="token operator">:</span> Rails<span class="token punctuation">.</span>env<span class="token punctuation">.</span>production<span class="token operator">?</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"If you use ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">document.addEventListener("turbolinks:load", function() {...});</code>'}})," somewhere in your code, you will notice that Turbolinks 5 does not fire ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">turbolinks:load</code>'}})," on initial page load. A quick workaround for React on Rails earlier than 15 is to use ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">defer</code>'}})," instead of ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">async</code>'}}),":"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb">  <span class="token erb language-erb"><span class="token delimiter punctuation">&lt;%=</span><span class="token ruby language-ruby"> javascript_include_tag <span class="token string-literal"><span class="token string">\'application\'</span></span><span class="token punctuation">,</span> <span class="token symbol">defer</span><span class="token operator">:</span> Rails<span class="token punctuation">.</span>env<span class="token punctuation">.</span>production<span class="token operator">?</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"More information on this issue can be found here: ",s.createElement(n.a,{href:"https://github.com/turbolinks/turbolinks/issues/28"},"https://github.com/turbolinks/turbolinks/issues/28")),"\n",s.createElement(n.p,null,"When loading your scripts asynchronously your components may not be registered correctly. Call ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">ReactOnRails.reactOnRailsPageLoaded()</code>'}})," to re-initialize like so:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js">document<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">\'turbolinks:load\'</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>\n  ReactOnRails<span class="token punctuation">.</span><span class="token function">reactOnRailsPageLoaded</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>\n<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"React on Rails 15 fixes both issues, so if you still have the listener it can be removed (and should be as ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">reactOnRailsPageLoaded()</code>'}})," is now async)."),"\n",s.createElement(n.div,{className:"markdown-alert markdown-alert-warning",dir:"auto"},"\n",s.createElement(n.p,{className:"markdown-alert-title",dir:"auto"},s.createElement(n.svg,{className:"octicon",viewBox:"0 0 16 16",width:"16",height:"16","aria-hidden":"true"},s.createElement(n.path,{d:"M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"})),"WARNING"),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Async Scripts with Turbolinks Require Pro")),"\n",s.createElement(n.p,null,"If you use async script loading with Turbolinks, you need Pro's early hydration behavior to prevent race conditions. This is a React on Rails Pro licensed feature."),"\n",s.createElement(n.p,null,"Without Pro's early hydration, async scripts may not be ready when Turbolinks fires navigation events, causing components to fail hydration."),"\n",s.createElement(n.p,null,s.createElement(n.strong,null,"Alternatives:")),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,"Use ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">defer</code>'}})," instead of ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">async</code>'}})," (waits for full page load before hydration)"),"\n",s.createElement(n.li,null,"Upgrade to modern Turbo (recommended)"),"\n",s.createElement(n.li,null,"Use React on Rails Pro (early hydration is automatic for Pro users)"),"\n"),"\n"),"\n",s.createElement(n.h3,{id:"turbolinks-5-specific-information",style:{position:"relative"}}
1,s.createElement(n.a,{href:"#turbolinks-5-specific-information","aria-label":"turbolinks 5 specific information permalink",className:"anchor before"},s.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>'}})),"Turbolinks 5 Specific Information"),"\n",s.createElement(n.p,null,"React on Rails will automatically detect which version of Turbolinks you are using (2.x or 5.x) and use the correct event handlers."),"\n",s.createElement(n.p,null,"For more information on Turbolinks 5: ",s.createElement(n.a,{href:"https://github.com/turbolinks/turbolinks"},"https://github.com/turbolinks/turbolinks")),"\n",s.createElement(n.h3,{id:"technical-details-and-troubleshooting",style:{position:"relative"}},s.createElement(n.a,{href:"#technical-details-and-troubleshooting","aria-label":"technical details and troubleshooting permalink",className:"anchor before"},s.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>'}})),"Technical Details and Troubleshooting"),"\n",s.createElement(n.h4,{id:"csrf-and-mime-type-handling",style:{position:"relative"}},s.createElement(n.a,{href:"#csrf-and-mime-type-handling","aria-label":"csrf and mime type handling permalink",className:"anchor before"},s.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>'}})),"CSRF and MIME Type Handling"),"\n",s.createElement(n.ul,null,"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"CSRF tokens"),": Turbolinks 5 changes the head element by JavaScript (not only body) on page changes with the correct csrf meta tag. Be thorough checking CSRF tokens, especially when multiple windows are opened, as the CSRF helper in ReactOnRails needs to work with Turbolinks5."),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"MIME type handling"),": Turbolinks 5 sends requests with ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Accept: text/html</code>'}})," only (not ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Accept: */*</code>'}}),"), which makes Rails behave differently compared to normal requests. For more details on the special handling of ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">*/*</code>'}})," you can read ",s.createElement(n.a,{href:"http://blog.bigbinary.com/2010/11/23/mime-type-resolution-in-rails.html"},"Mime Type Resolution in Rails"),"."),"\n",s.createElement(n.li,null,s.createElement(n.strong,null,"Multiple Webpack bundles"),": If you're using multiple Webpack bundles, make sure that there are no name conflicts between JS objects or Redux store paths."),"\n"),"\n",s.createElement(n.h4,{id:"debugging-turbolinks-events",style:{position:"relative"}},s.createElement(n.a,{href:"#debugging-turbolinks-events","aria-label":"debugging turbolinks events permalink",className:"anchor before"},s.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>'}})),"Debugging Turbolinks Events"),"\n",s.createElement(n.p,null,"To turn on tracing of Turbolinks events, put this in your registration file, where you register your components."),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js">ReactOnRails<span class="token punctuation">.</span><span class="token function">setOptions</span><span class="token punctuation">(</span><span class="token punctuation">{</span>\n  <span class="token literal-property property">traceTurbolinks</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>\n  <span class="token literal-property property">turbo</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>\n<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"Rather than setting the value to true, you could set it to TRACE_TURBOL
1INKS, and then you could place this in your ",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">webpack.client.base.config.js</code>'}}),":"),"\n",s.createElement(n.p,null,"Define this const at the top of the file:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js"><span class="token keyword">const</span> devBuild <span class="token operator">=</span> process<span class="token punctuation">.</span>env<span class="token punctuation">.</span><span class="token constant">NODE_ENV</span> <span class="token operator">!==</span> <span class="token string">\'production\'</span><span class="token punctuation">;</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"Add this DefinePlugin option:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="js"><pre class="language-js"><code class="language-js">  <span class="token literal-property property">plugins</span><span class="token operator">:</span> <span class="token punctuation">[</span>\n   <span class="token keyword">new</span> <span class="token class-name">webpack<span class="token punctuation">.</span>DefinePlugin</span><span class="token punctuation">(</span><span class="token punctuation">{</span>\n     <span class="token constant">TRACE_TURBOLINKS</span><span class="token operator">:</span> devBuild<span class="token punctuation">,</span>\n   <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">,</span></code></pre></div>'}}),"\n",s.createElement(n.p,null,"At Webpack compile time, the value of devBuild is inserted into your file."),"\n",s.createElement(n.p,null,"Once you do that, you'll see messages prefixed with ",s.createElement(n.strong,null,"TURBO:")," like this in the browser console:"),"\n",s.createElement(n.p,null,"Turbolinks Classic:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">TURBO: WITH TURBOLINKS: document page:before-unload and page:change handlers installed. (program)\nTURBO: reactOnRailsPageLoaded</code></pre></div>'}}),"\n",s.createElement(n.p,null,"Turbolinks 5:"),"\n",s.createElement(n.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="text"><pre class="language-text"><code class="language-text">TURBO: WITH TURBOLINKS 5: document turbolinks:before-render and turbolinks:render handlers installed. (program)\nTURBO: reactOnRailsPageLoaded</code></pre></div>'}}),"\n",s.createElement(n.p,null,"We've noticed that Turbolinks doesn't work if you use the RubyGem versions of jQuery and jQuery ujs. Therefore, we recommend using the JS packages instead. See the ",s.createElement(n.a,{href:"https://github.com/shakacode/react-webpack-rails-tutorial"},"tutorial app")," for how to accomplish this."),"\n",s.createElement(n.img,{src:"https://cloud.githubusercontent.com/assets/1118459/12760060/6546e254-c999-11e5-828b-a8aaa473e5bd.png",alt:"Show we only install the Turbolinks handlers once"}))}var o=function(e){void 0===e&&(e={});const{wrapper:n}=Object.assign({},(0,t.R)(),e.components);return n?s.createElement(n,e,s.createElement(l,e)):l(e)},r=a(63679),c=a(95197),p=a(47388),i=a(23690),u=a(14487);const d=r.default.p.withConfig({displayName:"doc-article__RedirectFallback",componentId:"sc-tic2w5-0"})(["padding:2rem;"]),g=e=>{let{data:n,location:a,children:t}=e;const{headings:l}=n.article.childMdx,o=(0,c.X9)(a.pathname),[r,i]=s.useState(null),g=a.pathname.split("/"),m=g.indexOf("docs"),h=-1===m?a.pathname.length:g.slice(0,m+1).join("/").length,k=a.pathname.slice(0,h),b=a.pathname.slice(h+1).replace(/\/$/,"").split("/").filter((e=>""!==e)),y=b.length>1?b.slice(0,-1).join("/"):"";s.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 E=null===o||null===r?null:""+o+r;return s.createElement(s.Fragment,null,null!==E?s.createElement(d,{role:"status","aria-live":"polite"},"Redirecting..."," ",s.createElement("a",{href:E,target:"_blank",rel:"noopener noreferrer"},"Click here if not redirected.")):s.createElement(p.A,{main:s.createElement(u.A,{body:t,headings:l,transformUrl:e=>{if(e.startsWith("http")||e.startsWith("#"))return e;const n=e.replace(/\.md$/,"/");
1if(n.startsWith("./"))return k+(""===y?"":"/"+y)+n.slice(1);if(n.startsWith("../")){if(""===y)return""+k+n.slice(2);const e=y.split("/").slice(0,-1).join("/");return k+(""===e?"":"/"+e)+n.slice(2)}return k+"/"+(""===y?"":y+"/")+n}})}))};function m(e){return s.createElement(g,e,s.createElement(o,e))}const h=e=>{let{data:n,location:a,pageContext:t}=e;const{headings:l}=n.article.childMdx,{siteUrl:o}=n.site.siteMetadata,{repoDisplayName:r}=t,p=l.find((e=>1===e.depth)),u=(0,c.X9)(a.pathname)||""+o.replace(/\/+$/,"")+a.pathname;return s.createElement(i.A,{title:p?p.value:r,description:p?p.value:r+" 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-turbolinks-md-a5cb79de7453368ba285.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.