Turbo介绍
Introduction
Turbo bundles several techniques for creating fast, modern, progressively enhanced web applications without using much JavaScript. It offers a simpler alternative to the prevailing client-side frameworks which put all the logic in the front-end and confine the server side of your app to being little more than a JSON API.
Turbo 捆绑了几个技术去创建 快速的、最新的、逐步加强的web应用而不需要JavaScript。
他提供一个简单的替换主流的prevailing 将逻辑放在前端的客户端框架,这限定confine服务器端成为一个JSON API。
Turbo 捆绑了几个技术去创建 快速的、最新的、逐步加强的web应用而不需要JavaScript。
他提供一个简单的替换主流的prevailing 将逻辑放在前端的客户端框架,这限定confine服务器端成为一个JSON API。
With Turbo, you let the server deliver HTML directly, which means all the logic for checking permissions, interacting directly with your domain model, and everything else that goes into programming an application can happen more or less exclusively within your favorite programming language. You’re no longer mirroring logic on both sides of a JSON divide. All the logic lives on the server, and the browser deals just with the final HTML.
使用Turbo,你让服务器直接deliver HTML,那就意味着所有的检查权限的逻辑、直接与域模型交互的逻辑、以及用于编程应用程序的其他一切都可以或多或少只在你喜欢的编程语言中实现。
使用Turbo,你让服务器直接deliver HTML,那就意味着所有的检查权限的逻辑、直接与域模型交互的逻辑、以及用于编程应用程序的其他一切都可以或多或少只在你喜欢的编程语言中实现。
You can read more about the benefits of this HTML-over-the-wire approach on the Hotwire site. What follows are the techniques that Turbo brings to make this possible.
你可以阅读更多的好处。。。HTML-over-the-wire approach (Hotwire= HTML Over The Wire)
你可以阅读更多的好处。。。HTML-over-the-wire approach (Hotwire= HTML Over The Wire)
﹟Turbo Drive: Navigate within a persistent process
A key attraction with traditional single-page applications, when compared with the old-school, separate-pages approach, is the speed of navigation. SPAs get a lot of that speed from not constantly tearing down the application process, only to reinitialize it on the very next page.
传统的单页应用程序的一个关键吸引力是导航速度,与传统的单独页面方法相比。SPA之所以能获得如此快的速度,是因为他们没有不断地破坏应用程序进程,而是在下一页重新初始化它。
传统的单页应用程序的一个关键吸引力是导航速度,与传统的单独页面方法相比。SPA之所以能获得如此快的速度,是因为他们没有不断地破坏应用程序进程,而是在下一页重新初始化它。
Turbo Drive gives you that same speed by using the same persistent-process model, but without requiring you to craft your entire application around the paradigm. There’s no client-side router to maintain, there’s no state to carefully manage. The persistent process is managed by Turbo, and you write your server-side code as though you were living back in the early aughts – blissfully isolated from the complexities of today’s SPA monstrosities!
This happens by intercepting all clicks on <a href> links to the same domain. When you click an eligible link, Turbo Drive prevents the browser from following it, changes the browser’s URL using the History API, requests the new page using fetch, and then renders the HTML response.
Same deal with forms. Their submissions are turned into fetch requests from which Turbo Drive will follow the redirect and render the HTML response.
During rendering, Turbo Drive replaces the current <body> element outright and merges the contents of the <head> element. The JavaScript window and document objects, and the <html> element, persist from one rendering to the next.
While it’s possible to interact directly with Turbo Drive to control how visits happen or hook into the lifecycle of the request, the majority of the time this is a drop-in replacement where the speed is free just by adopting a few conventions.
TurboDrive通过使用相同的持久化过程模型为您提供了相同的速度,但不需要您围绕该范例创建整个应用程序。没有需要维护的客户端路由器,也没有需要仔细管理的状态。持久化进程由Turbo管理,您编写服务器端代码时就像回到了早期一样——与当今SPA怪兽的复杂性完美隔离!
这是通过拦截指向同一域的<a href>链接上的所有点击来实现的。当您单击符合条件的链接时,Turbo Drive会阻止浏览器跟踪它,使用历史API更改浏览器的URL,使用fetch请求新页面,然后呈现HTML响应。
Form也一样。他们的提交被转化为提取请求,Turbo Drive将从中遵循重定向并呈现HTML响应。
在渲染过程中,Turbo Drive会完全替换当前的<body>元素,并合并<head>元素的内容。JavaScript窗口和文档对象,以及<html>元素,从一个渲染持续到下一个渲染。
虽然可以直接与Turbo Drive交互,以控制访问的发生方式或与请求的生命周期挂钩,但大多数情况下,这只是一种替代,只需采用一些约定即可实现速度自由。
TurboDrive通过使用相同的持久化过程模型为您提供了相同的速度,但不需要您围绕该范例创建整个应用程序。没有需要维护的客户端路由器,也没有需要仔细管理的状态。持久化进程由Turbo管理,您编写服务器端代码时就像回到了早期一样——与当今SPA怪兽的复杂性完美隔离!
这是通过拦截指向同一域的<a href>链接上的所有点击来实现的。当您单击符合条件的链接时,Turbo Drive会阻止浏览器跟踪它,使用历史API更改浏览器的URL,使用fetch请求新页面,然后呈现HTML响应。
Form也一样。他们的提交被转化为提取请求,Turbo Drive将从中遵循重定向并呈现HTML响应。
在渲染过程中,Turbo Drive会完全替换当前的<body>元素,并合并<head>元素的内容。JavaScript窗口和文档对象,以及<html>元素,从一个渲染持续到下一个渲染。
虽然可以直接与Turbo Drive交互,以控制访问的发生方式或与请求的生命周期挂钩,但大多数情况下,这只是一种替代,只需采用一些约定即可实现速度自由。
﹟Turbo Frames: Decompose complex pages
Most web applications present pages that contain several independent segments. For a discussion page, you might have a navigation bar on the top, a list of messages in the center, a form at the bottom to add a new message, and a sidebar with related topics. Generating this discussion page normally means generating each segment in a serialized manner, piecing them all together, then delivering the result as a single HTML response to the browser.
With Turbo Frames, you can place those independent segments inside frame elements that can scope their navigation and be lazily loaded. Scoped navigation means all interaction within a frame, like clicking links or submitting forms, happens within that frame, keeping the rest of the page from changing or reloading.
To wrap an independent segment in its own navigation context, enclose it in a <turbo-frame> tag. For example:
大多数web应用程序呈现的页面包含几个独立的部分。对于讨论页面,您可能在顶部有一个导航栏,在中心有一个消息列表,在底部有一个用于添加新消息的表单,以及一个带有相关主题的侧边栏。生成此讨论页面通常意味着以序列化方式生成每个片段,将它们拼接在一起,然后将结果作为单个HTML响应传递给浏览器。
使用Turbo Frames,您可以将这些独立的片段放置在frame元素中,以scope their 导航范围并lazily加载。Scoped导航意味着框架内的所有交互,如单击链接或提交表单,都发生在该框架内,防止页面的其余部分更改或重新加载。
要将独立段包装在其自己的导航上下文中,请将其封装在<turbo-frame>标记中。例如:
大多数web应用程序呈现的页面包含几个独立的部分。对于讨论页面,您可能在顶部有一个导航栏,在中心有一个消息列表,在底部有一个用于添加新消息的表单,以及一个带有相关主题的侧边栏。生成此讨论页面通常意味着以序列化方式生成每个片段,将它们拼接在一起,然后将结果作为单个HTML响应传递给浏览器。
使用Turbo Frames,您可以将这些独立的片段放置在frame元素中,以scope their 导航范围并lazily加载。Scoped导航意味着框架内的所有交互,如单击链接或提交表单,都发生在该框架内,防止页面的其余部分更改或重新加载。
要将独立段包装在其自己的导航上下文中,请将其封装在<turbo-frame>标记中。例如:
<turbo-frame id="new_message"> <form action="/messages" method="post"> ... </form> </turbo-frame>
When you submit the form above, Turbo extracts the matching <turbo-frame id="new_message"> element from the redirected HTML response and swaps its content into the existing new_message frame element. The rest of the page stays just as it was.
当您提交上面的表单时,Turbo从重定向的HTML响应中提取匹配的<Turbo frame id=“new_message”>元素,并将其内容替换为现有的new_mesage frame元素。页面的其余部分保持原样。
当您提交上面的表单时,Turbo从重定向的HTML响应中提取匹配的<Turbo frame id=“new_message”>元素,并将其内容替换为现有的new_mesage frame元素。页面的其余部分保持原样。
Frames can also defer loading their contents in addition to scoping navigation. To defer loading a frame, add a src attribute whose value is the URL to be automatically loaded. As with scoped navigation, Turbo finds and extracts the matching frame from the resulting response and swaps its content into place:
除了范围导航之外,框架还可以延迟加载其内容。要延迟加载帧,请添加一个src属性,该属性的值是要自动加载的URL。与范围导航一样,Turbo从结果响应中查找并提取匹配帧,并将其内容交换到位:
除了范围导航之外,框架还可以延迟加载其内容。要延迟加载帧,请添加一个src属性,该属性的值是要自动加载的URL。与范围导航一样,Turbo从结果响应中查找并提取匹配帧,并将其内容交换到位:
<turbo-frame id="messages" src="/messages"> <p>This message will be replaced by the response from /messages.</p> </turbo-frame>
This may sound a lot like old-school frames, or even <iframe>s, but Turbo Frames are part of the same DOM, so there’s none of the weirdness or compromises associated with “real” frames. Turbo Frames are styled by the same CSS, part of the same JavaScript context, and are not placed under any additional content security restrictions.
In addition to turning your segments into independent contexts, Turbo Frames affords you:
这听起来很像老派的frames,甚至<iframe>s,但Turbo帧是同一DOM的一部分,因此没有任何与“真实”帧相关的奇怪或妥协。Turbo Frames由相同的CSS进行样式设置,属于相同的JavaScript上下文的一部分,并且不受任何额外的内容安全限制。
除了将您的片段转换为独立的上下文之外,Turbo Frames还为您提供:
这听起来很像老派的frames,甚至<iframe>s,但Turbo帧是同一DOM的一部分,因此没有任何与“真实”帧相关的奇怪或妥协。Turbo Frames由相同的CSS进行样式设置,属于相同的JavaScript上下文的一部分,并且不受任何额外的内容安全限制。
除了将您的片段转换为独立的上下文之外,Turbo Frames还为您提供:
- Efficient caching. In the discussion page example above, the related topics sidebar needs to expire whenever a new related topic appears, but the list of messages in the center does not. When everything is just one page, the whole cache expires as soon as any of the individual segments do. With frames, each segment is cached independently, so you get longer-lived caches with fewer dependent keys.
- Parallelized execution. Each defer-loaded frame is generated by its own HTTP request/response, which means it can be handled by a separate process. This allows for parallelized execution without having to manually manage the process. A complicated composite page that takes 400ms to complete end-to-end can be broken up with frames where the initial request might only take 50ms, and each of three defer-loaded frames each take 50ms. Now the whole page is done in 100ms because the three frames each taking 50ms run concurrently rather than sequentially.
- Ready for mobile. In mobile apps, you usually can’t have big, complicated composite pages. Each segment needs a dedicated screen. With an application built using Turbo Frames, you’ve already done this work of turning the composite page into segments. These segments can then appear in native sheets and screens without alteration (since they all have independent URLs).
高效缓存。在上面的讨论页面示例中,每当出现新的相关主题时,相关主题侧边栏都需要过期,但中心的消息列表不会过期。当所有内容都只是一个页面时,只要有任何一个单独的片段,整个缓存就会过期。对于帧,每个片段都是独立缓存的,因此您可以使用较少的从属关键帧获得更长的缓存寿命。
并行执行。每个延迟加载的帧由其自己的HTTP请求/响应生成,这意味着它可以由单独的进程处理。这允许并行执行,而无需手动管理流程。一个复杂的复合页面需要400毫秒才能端到端完成,可以将其拆分为多个帧,其中初始请求可能只需要50毫秒,三个延迟加载的帧中的每一个都需要50毫秒。现在,整个页面在100毫秒内完成,因为三个帧每一个都需要50毫秒,而不是按顺序运行。
适用于移动设备。在移动应用程序中,通常不能有大而复杂的复合页面。每个片段都需要一个专用屏幕。在使用Turbo Frames构建的应用程序中,您已经完成了将复合页面转换为片段的工作。然后,这些片段可以出现在本机工作表和屏幕中而无需更改(因为它们都有独立的URL)。
并行执行。每个延迟加载的帧由其自己的HTTP请求/响应生成,这意味着它可以由单独的进程处理。这允许并行执行,而无需手动管理流程。一个复杂的复合页面需要400毫秒才能端到端完成,可以将其拆分为多个帧,其中初始请求可能只需要50毫秒,三个延迟加载的帧中的每一个都需要50毫秒。现在,整个页面在100毫秒内完成,因为三个帧每一个都需要50毫秒,而不是按顺序运行。
适用于移动设备。在移动应用程序中,通常不能有大而复杂的复合页面。每个片段都需要一个专用屏幕。在使用Turbo Frames构建的应用程序中,您已经完成了将复合页面转换为片段的工作。然后,这些片段可以出现在本机工作表和屏幕中而无需更改(因为它们都有独立的URL)。
﹟Turbo Streams: Deliver live page changes
Making partial page changes in response to asynchronous actions is how we make the application feel alive. While Turbo Frames give us such updates in response to direct interactions within a single frame, Turbo Streams let us change any part of the page in response to updates sent over a WebSocket connection, SSE or other transport. (Think an imbox that automatically updates when a new email arrives.)
Turbo Streams introduces a <turbo-stream> element with seven basic actions: append, prepend, replace, update, remove, before, and after. With these actions, along with the target attribute specifying the ID of the element you want to operate on, you can encode all the mutations needed to refresh the page. You can even combine several stream elements in a single stream message. Simply include the HTML you’re interested in inserting or replacing in a template tag and Turbo does the rest:
响应异步操作进行部分页面更改是我们让应用程序感觉活跃的方式。虽然Turbo Frames为我们提供此类更新,以响应单个帧内的直接交互,但Turbo Streams允许我们更改页面的任何部分,以响应通过WebSocket连接、SSE或其他传输发送的更新。(想想一个在新邮件到达时自动更新的inbox。)
Turbo Streams引入了一个具有七个基本操作的<Turbo stream>元素:追加、前置、替换、更新、删除、之前和之后。通过这些操作,以及指定要操作的元素ID的目标属性,您可以对刷新页面所需的所有mutation进行编码。您甚至可以在单个流消息中组合多个流元素。只需将您感兴趣的HTML插入或替换到模板标签中,Turbo即可完成以下操作:
响应异步操作进行部分页面更改是我们让应用程序感觉活跃的方式。虽然Turbo Frames为我们提供此类更新,以响应单个帧内的直接交互,但Turbo Streams允许我们更改页面的任何部分,以响应通过WebSocket连接、SSE或其他传输发送的更新。(想想一个在新邮件到达时自动更新的inbox。)
Turbo Streams引入了一个具有七个基本操作的<Turbo stream>元素:追加、前置、替换、更新、删除、之前和之后。通过这些操作,以及指定要操作的元素ID的目标属性,您可以对刷新页面所需的所有mutation进行编码。您甚至可以在单个流消息中组合多个流元素。只需将您感兴趣的HTML插入或替换到模板标签中,Turbo即可完成以下操作:
<turbo-stream action="append" target="messages"> <template> <div id="message_1">My new message!</div> </template> </turbo-stream>
This stream element will take the div with the new message and append it to the container with the ID messages. It’s just as simple to replace an existing element:
<turbo-stream action="replace" target="message_1"> <template> <div id="message_1">This changes the existing message!</div> </template> </turbo-stream>
This is a conceptual continuation of what in the Rails world was first called RJS and then called SJR, but realized without any need for JavaScript. The benefits remain the same:
这是Rails世界中最初被称为RJS,后来被称为SJR的概念的延续,但实现时不需要任何JavaScript。好处不变:
这是Rails世界中最初被称为RJS,后来被称为SJR的概念的延续,但实现时不需要任何JavaScript。好处不变:
- Reuse the server-side templates: Live page changes are generated using the same server-side templates that were used to create the first-load page.
- HTML over the wire: Since all we’re sending is HTML, you don’t need any client-side JavaScript (beyond Turbo, of course) to process the update. Yes, the HTML payload might be a tad larger than a comparable JSON, but with gzip, the difference is usually negligible, and you save all the client-side effort it takes to fetch JSON and turn it into HTML.
- Simpler control flow: It’s really clear to follow what happens when messages arrive on the WebSocket, SSE or in response to form submissions. There’s no routing, event bubbling, or other indirection required. It’s just the HTML to be changed, wrapped in a single tag that tells us how.
Now, unlike RJS and SJR, it’s not possible to call custom JavaScript functions as part of a Turbo Streams action. But this is a feature, not a bug. Those techniques can easily end up producing a tangled mess when way too much JavaScript is sent along with the response. Turbo focuses squarely on just updating the DOM, and then assumes you’ll connect any additional behavior using Stimulus actions and lifecycle callbacks.
复用服务器端模板:使用用于创建第一个加载页面的相同服务器端模板生成实时页面更改。
HTML over the wire:因为我们发送的都是HTML,所以您不需要任何客户端JavaScript(当然,除了Turbo)来处理更新。是的,HTML有效载荷可能比类似的JSON大一点,但使用gzip,差异通常可以忽略不计,而且您可以节省客户端获取JSON并将其转换为HTML所需的所有工作。
更简单的控制流程:当消息到达WebSocket、SSE或响应表单提交时,很清楚会发生什么。不需要路由、事件冒泡或其他间接寻址。它只是要更改的HTML,包装在一个告诉我们如何更改的标签中。
SSE ( Server-sent Events )是 WebSocket 的一种轻量代替方案,使用 HTTP 协议。
现在,与RJS和SJR不同,在Turbo Streams操作中不可能调用自定义JavaScript函数。但这是一个特性,而不是一个错误。当过多的JavaScript和响应一起发送时,这些技术很容易导致混乱。Turbo完全专注于更新DOM,然后假设您将使用Stimulus操作和生命周期回调连接任何其他行为。
复用服务器端模板:使用用于创建第一个加载页面的相同服务器端模板生成实时页面更改。
HTML over the wire:因为我们发送的都是HTML,所以您不需要任何客户端JavaScript(当然,除了Turbo)来处理更新。是的,HTML有效载荷可能比类似的JSON大一点,但使用gzip,差异通常可以忽略不计,而且您可以节省客户端获取JSON并将其转换为HTML所需的所有工作。
更简单的控制流程:当消息到达WebSocket、SSE或响应表单提交时,很清楚会发生什么。不需要路由、事件冒泡或其他间接寻址。它只是要更改的HTML,包装在一个告诉我们如何更改的标签中。
SSE ( Server-sent Events )是 WebSocket 的一种轻量代替方案,使用 HTTP 协议。
现在,与RJS和SJR不同,在Turbo Streams操作中不可能调用自定义JavaScript函数。但这是一个特性,而不是一个错误。当过多的JavaScript和响应一起发送时,这些技术很容易导致混乱。Turbo完全专注于更新DOM,然后假设您将使用Stimulus操作和生命周期回调连接任何其他行为。
﹟Turbo Native: Hybrid apps for iOS & Android
混合模式的好处,以及节约出时间用来将客户端本地的控件做的更好。
Turbo Native is ideal for building hybrid apps for iOS and Android. You can use your existing server-rendered HTML to get baseline coverage of your app’s functionality in a native wrapper. Then you can spend all the time you saved on making the few screens that really benefit from high-fidelity native controls even better.
An application like Basecamp has hundreds of screens. Rewriting every single one of those screens would be an enormous task with very little benefit. Better to reserve the native firepower for high-touch interactions that really demand the highest fidelity. Something like the “New For You” inbox in Basecamp, for example, where we use swipe controls that need to feel just right. But most pages, like the one showing a single message, wouldn’t really be any better if they were completely native.
Going hybrid doesn’t just speed up your development process, it also gives you more freedom to upgrade your app without going through the slow and onerous app store release processes. Anything that’s done in HTML can be changed in your web application, and instantly be available to all users. No waiting for Big Tech to approve your changes, no waiting for users to upgrade.
Turbo Native assumes you’re using the recommended development practices available for iOS and Android. This is not a framework that abstracts native APIs away or even tries to let your native code be shareable between platforms. The part that’s shareable is the HTML that’s rendered server-side. But the native controls are written in the recommended native APIs.
See the Turbo Native: iOS and Turbo Native: Android repositories for more documentation. See the native apps for HEY on iOS and Android to get a feel for just how good you can make a hybrid app powered by Turbo.
Turbo Native是构建iOS和Android混合应用程序的理想选择。您可以使用现有的服务器渲染的HTML在本机包装器中获取应用程序功能的基线覆盖率。然后,您可以将节省下来的所有时间用于使少数真正受益于高保真本机控件的屏幕变得更好。
像Basecamp这样的应用程序有数百个屏幕。重写这些屏幕中的每一个都将是一项巨大的任务,但收益甚微。最好保留本地火力,用于真正要求最高逼真度的高触摸交互。例如,类似于Basecamp中的“New For You”收件箱,我们使用需要感觉恰到好处的滑动控件。但大多数页面,比如显示一条消息的页面,如果完全是本地的,就不会更好了。
采用混合模式不仅可以加快你的开发进程,还可以让你更自由地升级你的应用,而无需经历缓慢而繁琐的应用商店发布过程。在HTML中所做的任何事情都可以在web应用程序中更改,并立即对所有用户可用。无需等待Big Tech批准您的更改,无需等待用户升级。
Turbo Native假设您正在使用适用于iOS和Android的推荐开发实践。这不是一个将本机API抽象出来,甚至试图让本机代码在平台之间共享的框架。可共享的部分是服务器端呈现的HTML。但是本机控件是用推荐的本机API编写的。
有关更多文档,请参见Turbo Native:iOS和Turbo Native:Android存储库。在iOS和Android上查看HEY的原生应用程序,了解如何制作一个由Turbo驱动的混合应用程序。
Turbo Native是构建iOS和Android混合应用程序的理想选择。您可以使用现有的服务器渲染的HTML在本机包装器中获取应用程序功能的基线覆盖率。然后,您可以将节省下来的所有时间用于使少数真正受益于高保真本机控件的屏幕变得更好。
像Basecamp这样的应用程序有数百个屏幕。重写这些屏幕中的每一个都将是一项巨大的任务,但收益甚微。最好保留本地火力,用于真正要求最高逼真度的高触摸交互。例如,类似于Basecamp中的“New For You”收件箱,我们使用需要感觉恰到好处的滑动控件。但大多数页面,比如显示一条消息的页面,如果完全是本地的,就不会更好了。
采用混合模式不仅可以加快你的开发进程,还可以让你更自由地升级你的应用,而无需经历缓慢而繁琐的应用商店发布过程。在HTML中所做的任何事情都可以在web应用程序中更改,并立即对所有用户可用。无需等待Big Tech批准您的更改,无需等待用户升级。
Turbo Native假设您正在使用适用于iOS和Android的推荐开发实践。这不是一个将本机API抽象出来,甚至试图让本机代码在平台之间共享的框架。可共享的部分是服务器端呈现的HTML。但是本机控件是用推荐的本机API编写的。
有关更多文档,请参见Turbo Native:iOS和Turbo Native:Android存储库。在iOS和Android上查看HEY的原生应用程序,了解如何制作一个由Turbo驱动的混合应用程序。
﹟Integrate with backend frameworks
You don’t need any backend framework to use Turbo. All the features are built to be used directly, without further abstractions. But if you have the opportunity to use a backend framework that’s integrated with Turbo, you’ll find life a lot simpler. We’ve created a reference implementation for such an integration for Ruby on Rails.
使用Turbo不需要任何后端框架。所有特性都是直接使用的,无需进一步抽象。但是,如果你有机会使用与Turbo集成的后端框架,你会发现生活简单得多。我们为RubyonRails的这种集成创建了一个参考实现。
阅读量: 650
发布于:
修改于:
发布于:
修改于: