Rails Turbolinks 后端逻辑分析 (更新总集篇)

Rei · 2013年07月03日 · 最后由 steven_lv 回复于 2018年06月05日 · 13991 次阅读
本帖已被管理员设置为精华贴

Turbolinks 是个好东西,但是目前只能搭配 Rails 框架使用。在这里分析一下它的后端处理逻辑,其他框架的开发者有兴趣可以实现自己的后端模块,将 Turbolinks 移植到自己的框架。

http://chloerei.com/2013/06/30/turbolinks-backend/


Turbolinks 并不糟糕

http://chloerei.com/2013/06/30/turbolinks-is-not-bad/


Turbolinks 向导

http://chloerei.com/2013/07/14/turbolinks-guide/

先收藏,准备学习,谢谢 Rei

推荐 Web Languages and VMs: Fast Code is Always in Fashion. (V8, Dart) - Google I/O 2013 可以了解很多 V8 内部,以及 Dart 已经何等出色了..

我同意对方辩友的观点。Turbolinks 只是一个加速器,不能取代客户端框架。如果一个页面页内逻辑特别复杂,自然要用上客户端框架。但是对于已有的 Rails 应用,引入 Turbolniks 比用客户端重写要容易多了。

#7 楼 @Saito total agree.

  • Turbolinks 的出现是为了给 Rails Asset Pipeline 擦屁股,Asset Pipeline 解决了前端相关的大部分问题(减少 http 请求,压缩/混淆,缓存失效),但是引人的问题是增加了 js 和 css 的渲染时间(Assets Pipline 的最佳实践是所有静态文件打一个包)。Tubolinks 的描述是Turbolinks makes following links in your web application faster (use with Rails Asset Pipeline)

  • Turbolinks 把客户端 JS 改造成像 Ruby 这种常驻进程方式执行,解决了 Asset Pipeline 带来的增加了渲染时间的问题。同时带来的新问题是内存泄漏、学习曲线增高、隐藏太多复杂性、事件绑定方式变化。Tubolinks 282 行代码却开了 245 个 issue ,这些 issue 大部分是解决 turbolinks 和其他插件适配的。我觉得如果不是 DHH 发起的,这项目早就挂了..

分久必合,合久必分啊

#10 楼 @hooopo 内存泄漏、学习曲线增高、隐藏太多复杂性、事件绑定,这些是单页应用都有的。框架声称能处理,是因为开发的时候需要按照框架的规范来写,这跟用 Turbolinks 的情况一样,不能用以前假设每个页面只执行一次的思路来写 js。

#12 楼 @Rei 这个要结合 Rails 默认开启 Turbolinks 来理解.. 并不是每个项目都是单页应用。

#10 楼 @hooopo 我正想接着吐槽 Sprockets.

Sprockets 的出现是为了解决什么问题?

  • 连接 ( 其他都是附带的。

前端开发到底需要的是什么?

难道真的需要一个打包工具?据我所知,在荒蛮的开发大地上,我们的前端朋友们用 Ant 也打了不少年的包了,这东西真不稀奇,打包不是他们的痛点。

前端开发的痛点是组织代码,怎么写都不爽才是问题。因为没有标准的模块化。所以大家折腾各种 CMD/AMD 的标准。这下写的爽了.. 也没 Sprockets 什么事了。因为 module 天然有 require 的属性,所以必然是通过 module 来判断哪些文件被引用了,然后一起打包。Sprockets 帮不上什么忙。

而 SASS 则更是没 Sprockets 什么事,因为 SASS 天然的支持 partials, 默认就是这样 build 在一起的。

所以 Sprockets 在现在的开发模式下,有用的功能几乎为 0 . ( 不过在当时这些 模块定义 AMD/CMD 还没有被大家广泛接受的时候是有用的,不过仅限于 Javascript.

Sprockets 希望你将 Javascript lib 打包成 Gem 来做管理,本来就是一个 Anti Pattern. 因为这与开发阶段完全脱离,非常依赖第三方人员升级 Gem. lib 与 作者结合的发布方式才是对的。例如 bower ( 方向对了,但是实现的不好。

#13 楼 @hooopo Rails 喜欢给开发者“吃我 XX 啦”,然后再提供方法删掉,传统来了,以前 coffee 也是这样,结果写了半年 js 发现 coffee 还真好。要删掉 Turbolinks 只要删两行。

#14 楼 @Saito Sprockets 有点用的,话说,我第一份工作就是写过发布之前打包+压缩静态文件的脚本。Rails 框架提供了这个功能,一夜之间 Rails 项目都是压缩合并的了,想起以前一些搞 PHP 的同事为怎么打包 JS 和 CSS 还争论了半天觉得好笑(最后项目 css 和 js 是否打包就不清楚了..)。

你的并不好都是针对专业前端框架来说的,但 Rails 是后端方案或者是一站式方案,也不能苛求太多。

#14 楼 @Saito js 可以用 git submodule 放到 vendor/assets 下面,不过这有点像以前的 plugin 管理,最终会废弃。如果 js 有统一的包管理器,以后也能为 Sprockets 所用。

#16 楼 @hooopo 我们现在使用的还是 Sprockets 做前端的开发,只不过越来越觉得没用。现在它的处境很尴尬..

我在 Sprockets 上做了很多扩展,他现在对于我来说有用的是 preprocess Coffee SASS 跟 压缩。其他都没用。编译是 sass 跟 node coffee 做的,压缩是 uglify 跟 yui 做的。它提供了很方便的接口.. 不然我要自己去适配这些东西。想自己写,又觉得烦... 现在是这种状态。

#18 楼 @Saito sass 和 coffee 也算是解决了一些问题,然后带来一些新问题的东西..

#17 楼 @Rei Sprockets 在 2.6.0 的时候就支持 bower 了,不过副作用很大。这个是跟我之前说的 bower 实现的不好有关。

很多的 Javascript 库都加入了 bower 的支持,但是 component.json/bower.json 写的都不对,要不然不支持 semver, 要不然就是没写 ignore 的文件列表 要不然就是没有 main. 而 bower 每次都要 clone 整个 git 的 repo 下来然后 checkout 到某一个 tag 也是实现上的大问题。导致 components/ 文件夹里面内容很多,间接就导致了 Sprockets build 变的很慢。

Sprockets 2.6.0 开始支持的 bower 也依赖于 bower.json 的 main 这个配置项,如果没写就会导致 http://ruby-china.org/topics/12020 第三个管太多的问题。

bower 如果以后可以跟 github 的新的 release workflow 结合的话会非常好。这个还是要整个社区推动才行。

#20 楼 @Saito 我目前没有 gem 包或者 star 人数少的就直接下载放到 vendor 了。感觉很多包管理器都可以迁到 github release 了。马上有人提了 https://github.com/bower/bower/issues/584

#21 楼 @Rei 嗯,新的回复里面提出类似 npm publish 之类的,这种最好了,release workflow 也可以是一个备选。

匿名 #23 2013年07月04日

其实,我感觉对于 rails 的使用,没有必要紧跟最新的版本,作为一种开源项,完全可以按照自己的喜好或需求进行修改,甚至修改里面的原代码,所以 Turbolinks 的好与坏,因人而异吧

我用 rails 3.2.13 用了 turbolinks 没加入 jquery.turbolinks 可 jquery 的 ready 是能工作的。

#24 楼 @huobazi 你可以试试通过 turbolink 加载的页面或者 dom, jQuery.ready 绑定的事件是无效的 哦 我说的是 Rails 4,Rails 3 没验证过

反正我用 Python,不用关心这些问题

#14 楼 @Saito

前端开发的痛点是组织代码, 怎么写都不爽才是问题.

说的好!

#25 楼 @fresh_fish 我有几个站都在跑着,木问题啊 我的跟该页面/view 有关的 ready 代码都是写在 view 里


<script type="text/javascript">
$(document).ready(function(){
  console.log('xxx');
});
</script>

#28 楼 @huobazi 点到别的页面,ready 里面的代码就不会执行了。

#29 楼 @Rei 别的页面为什么要执行不属于自己页面该执行的 ready 代码。

#31 楼 @huobazi 意思是 ready 在 Turbolinks.visit 的时候是不触发的,如果另一个页面的逻辑是写在 ready 里面,那么不会执行。如果能执行,可能 Turbolinks 没起作用。能把网站发我看看吗?

#32 楼 @Rei 发你邮箱了

我是不会用什么 Turbolinks 的。不解释,简直就是鸡肋。

#26 楼 @bhuztez 如果还没遇到浏览器成为性能瓶颈的情况,就没必要关心这个...

#35 楼 @luikore 越来越不容易成为瓶颈了...

#32 楼 @Rei 仔细读了您的日志,感谢你写的这么全面细致。让后来者减少了很多踩坑的机会。但似乎在文章里面你没有提到 coffee script 如何专为 turbolinks 绑定事件的写法。下面有一个我在书里看到的例子,可以更新在你的文章里面么?

$(document).on "ready page:change", ->
  $('.store .entry > img').click ->
    $(this).parent().find(':submit').click()

书中的原话是

The function with two events: ready and page:change. ready is the event that fires if people navigate to your page from outside of your site, and page:change is the event that Turbolinks4 fires if people navigate to your page from within your site. Associating the script to both makes sure that you are covered either way.

绑定 page:change 应该能解决不少上面回复中提到的所谓坑。

#7 楼 @Saito 同样很喜欢 Ember JS 的鹿过。

#37 楼 @Victor 书是最新版的 Agile Web development with Ruby on Rails 4

#7 楼 @Saito 没搞懂 Turbolinks 的学习瓶颈在哪里?当黑盒使用的话,似乎没有学习成本。比 assets precompile 的坑少多了。不需要的话,直接注释掉就了事。

至于有没有必要用,还是得看应用类型的。最典型的如 Github 上浏览代码,此时使用 turbolinks 获取的收益是很大的。如果应用本身就是 js 重度应用,那当然也不需要这玩意。而类似 ruby-china 这样的应用,打不打开区别就不太大了。

未来的发展方向是事在人为的。而且如 DHH 所说,宣称会作为一种趋势杀死 server、html 的工具曾经有很多,Java applet、Flash、Flex 等等,但近二十年下来,Web 的主体依然是 HTML。

Turbolinks 向导

http://blog.chloerei.com/articles/48-turbolinks-guide

这是总集篇,包含了之前的所有实践总结,估计我近期不需要再写 Turbolinks 了。

链接已经变化了,从 google 进来的,比如第三篇链接应该是 http://chloerei.com/2013/07/14/turbolinks-guide/

#43 楼 @zoker 好,都修复了。

链接都是失效了。@Rei

Rei Turbolinks 并不糟糕 提及了此话题。 04月03日 10:57
需要 登录 后方可回复, 如果你还没有账号请 注册新账号