<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jason Lee</title>
    <description>The latest articles on DEV Community by Jason Lee (@huacnlee).</description>
    <link>https://dev.to/huacnlee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F476045%2F8b392ae4-108a-4d15-9cfd-c2e9fd0c2fe8.png</url>
      <title>DEV Community: Jason Lee</title>
      <link>https://dev.to/huacnlee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/huacnlee"/>
    <language>en</language>
    <item>
      <title>Turbolinks extend prefetch to speed up your website </title>
      <dc:creator>Jason Lee</dc:creator>
      <pubDate>Fri, 09 Oct 2020 16:26:46 +0000</pubDate>
      <link>https://dev.to/huacnlee/turbolinks-extend-prefetch-to-make-your-website-speed-up-245d</link>
      <guid>https://dev.to/huacnlee/turbolinks-extend-prefetch-to-make-your-website-speed-up-245d</guid>
      <description>&lt;p&gt;This article shares an extension of Turbolinks for accelerating web page access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Recently, I discovered &lt;a href="http://instantclick.io"&gt;InstantClick&lt;/a&gt;, a small technique for pre-loading web pages, which can effectively improve the speed of website access.&lt;/p&gt;

&lt;p&gt;The general principle is that when the user mouses over the link, the web page will be pre-loaded in the cache by Ajax in advance, and when the user clicks, it will be directly rendered with the previous cache.&lt;/p&gt;

&lt;p&gt;So I also tweeted about this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/huacnlee/status/1310180334059749378"&gt;https://twitter.com/huacnlee/status/1310180334059749378&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/huacnlee/status/1310209510514909184"&gt;https://twitter.com/huacnlee/status/1310209510514909184&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rails built-in Turbolinks actually has a similar cache mechanism. When the user clicks the page back and forth, it will use the cache to pre-render it, but it does not preprocess it when the user's mouse is hovered.&lt;/p&gt;

&lt;p&gt;I checked and found that Turbolinks' Issue also discussed this &lt;a href="https://github.com/turbolinks/turbolinks/issues/313"&gt;turbolinks/turbolinks#313&lt;/a&gt;, and I found an implementation &lt;a href="//https:/%20/gist.github.com/hopsoft/ab500a3b584e2878c83137cb539abb32"&gt;Reference&lt;/a&gt;, so I encapsulated it, and made improvements to implement an extension of Turbolinks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/huacnlee/turbolinks-prefetch"&gt;https://github.com/huacnlee/turbolinks-prefetch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the same time, I have additionally adjusted the &lt;code&gt;visit&lt;/code&gt; action of Turbolinks in the implementation. If there is already a prefetch action, it will be rendered directly without requesting the page again.&lt;/p&gt;

&lt;p&gt;As you can see, currently Ruby China has enabled this feature (Hong Kong server). When the prefetch has an effect, the page is basically opened like a local web page.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Turbolinks Prefetch works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hover --&amp;gt; [prefetch] --&amp;lt;no cache&amp;gt;--&amp;gt; [XHR fetch] -&amp;gt; [Turbolinks cache.put]
              |
          &amp;lt;exist cache / in fetching&amp;gt;
              |
            ignore

click --&amp;lt;check cache&amp;gt;-- exist --&amp;gt; [isPrefetch] -&amp;gt; [Turbolinks.visit advance] ---&amp;gt; [render page]
             | | |
             | | --async-&amp;gt; [fetch background] -&amp;gt; [render if updated]
             | |
             | &amp;lt;Yes&amp;gt;
             | |--- [Turbolinks.visit restore] --&amp;gt; render -&amp;gt; nothing
          No cahce
             |
             ---&amp;gt; [Turbolinks.visit]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ yarn add turbolinks-prefetch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Turbolinks from 'turbolinks';
window.Turbolinks = Turbolinks;

import TurbolinksPrefetch from 'turbolinks-prefetch';
TurbolinksPrefetch.start();

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a Prefetch request is made, an additional HTTP header of &lt;code&gt;Purpose: prefetch&lt;/code&gt; will be sent. If you need to ignore certain actions, you can use it.&lt;/p&gt;

&lt;p&gt;For example, actions such as updating the reading status and the number of visits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TopicsController &amp;lt; ApplicationController
  def show
    if request.headers["Purpose"] != "prefetch"
      # Do not update visits during prefetch
      @topic.increment_hit
    end
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Disable Prefetch for some links
&lt;/h3&gt;

&lt;p&gt;By default, Turbolinks Prefetch will turn on the behavior for all links.&lt;/p&gt;

&lt;p&gt;Except for the following situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Links to different websites (Host / Origin are different);&lt;/li&gt;
&lt;li&gt;There is a link to open a new window &lt;code&gt;target="_blank"&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Links with &lt;code&gt;data-remote&lt;/code&gt; attribute;&lt;/li&gt;
&lt;li&gt;There are links with &lt;code&gt;data-method&lt;/code&gt; attributes;&lt;/li&gt;
&lt;li&gt;Links with &lt;code&gt;data-prefetch="false"&lt;/code&gt; attribute;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It should be said that you don't need to deal with most of the default situations. The default behaviors like Rails UJS are already handled in Turbolinks Prefetch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So you can disable prefetch for some links like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;a href="https://google.com"&amp;gt;Google&amp;lt;/&amp;gt;
&amp;lt;a href="/topics/123" target="_blank"&amp;gt;Open in new window&amp;lt;/a&amp;gt;
&amp;lt;a href="/topics/123" data-method="PUT" data-remote&amp;gt;Put&amp;lt;/a&amp;gt;
&amp;lt;a href="/topics/123" data-method="DELETE"&amp;gt;Delete&amp;lt;/a&amp;gt;
&amp;lt;a href="/topics/123" data-prefetch="false"&amp;gt;Disable by directly&amp;lt;/a&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GitHub
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;🎊 Don't hesitate, immediately use it in your projects that already use Tubrolinks, basically seamless support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://github.com/huacnlee/turbolinks-prefetch"&gt;https://github.com/huacnlee/turbolinks-prefetch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>turbolinks</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Enumize - 扩展 ActiveRecord::Enum 增加实用方法</title>
      <dc:creator>Jason Lee</dc:creator>
      <pubDate>Mon, 24 Jun 2019 06:32:01 +0000</pubDate>
      <link>https://dev.to/huacnlee/enumize-activerecord-enum-1mf7</link>
      <guid>https://dev.to/huacnlee/enumize-activerecord-enum-1mf7</guid>
      <description>&lt;p&gt;Rails 4.2 (如果没记错）给我们带来了官方的 Enum 解决方案，目前大家都在使用它了。&lt;/p&gt;

&lt;p&gt;比如：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Book
  enum status: %i[draft published archived]
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然而我们在使用的时候会发现，往往我们需要将 &lt;code&gt;status&lt;/code&gt; 字段用中文或其他的方式在界面上显示，而不是一个 &lt;code&gt;draft / published / archived&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;于是很多人可能会这样：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Book
  enum status: %i[draft published archived]

  def status_name
    case status
    when "draft" then "草稿"
    when "published" then "已发布"
    when "archived" then "归档"
    end
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然后随着项目的推进，你会发现你的 Model 里面大量有这种函数。&lt;/p&gt;

&lt;p&gt;为了解决这个问题，我们最初在自己的项目里面实现了一个扩展，用于代替 &lt;code&gt;enum&lt;/code&gt; 的定义，给它增加一些函数扩展，现在提取成一个 Gem，可以方便以后使用。&lt;/p&gt;




&lt;h2&gt;
  
  
  使用方法
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gem "enumize"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;然后你的原来的 enum 定义不需要改变，这个 Gem 已经覆盖了那个方法。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J3U04LJ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://twemoji.ruby-china.com/2/svg/1f6a8.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J3U04LJ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://twemoji.ruby-china.com/2/svg/1f6a8.svg" alt="🚨" title=":rotating\_light:"&gt;&lt;/a&gt; 所以，你可以认为这个 Gem 的引入不会改变 ActiveRecord::Enum 的原有使用方式，你可以无缝的集成到你的项目中！&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Book
  enum status: %i[draft published archived]
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;现在你有了 &lt;code&gt;status_name&lt;/code&gt;, &lt;code&gt;status_color&lt;/code&gt;, &lt;code&gt;status_value&lt;/code&gt; 以及 &lt;code&gt;Book.status_options&lt;/code&gt; 这些方法:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;#{attribute}_name&lt;/code&gt; - 返回 name 的 I18n 信息，用于显示&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#{attribute}_color&lt;/code&gt; - 返回从 I18n 里面读取 color 的信息（如果你项目用不到可以忽略它）&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#{attribute}_value&lt;/code&gt; - 返回原始的数据库值，用来代替 &lt;code&gt;Book.statuses[@book.status]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Book.#{attribute}_options&lt;/code&gt; - 返回一个 Array，用于 &lt;code&gt;select&lt;/code&gt; tag，比如 &lt;code&gt;&amp;lt;%= f.select :status, Book.status_options %&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;配置 I18n:&lt;/p&gt;

&lt;p&gt;config/locales/en.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;en:
  activerecord:
    enums:
      book:
        status:
          draft: Drafting
          published: Published
          archived: Archived
        status_color:
          draft: "#999999"
          published: "green"
          archived: "red"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;config/locales/zh-CN.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;zh-CN:
  activerecord:
    enums:
      book:
        status:
          draft: "草稿"
          published: "已发布"
          archived: "归档"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;下面是使用的演示：&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb&amp;gt; @book = Book.new(status: :draft)
irb&amp;gt; @book.status
"draft"
irb&amp;gt; @book.draft?
true
irb&amp;gt; @book.published?
false
irb&amp;gt; @book.status_value
0
irb&amp;gt; @book.status_name
"草稿"
irb&amp;gt; @book.status_color
"#999999"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;status_options&lt;/code&gt; 方法用在 View 里面的演示:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;% form_for(@book) do |f| %&amp;gt;
  &amp;lt;%= f.text_field :name %&amp;gt;
  &amp;lt;%= f.select :status, Book.status_options %&amp;gt;
  &amp;lt;%= f.submit %&amp;gt;
&amp;lt;% end &amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  项目地址
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/huacnlee/enumize"&gt;https://github.com/huacnlee/enumize&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
