<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>FrankFang (Frank Fang)</title>
    <link>https://ruby-china.org/FrankFang</link>
    <description/>
    <language>en-us</language>
    <item>
      <title>我正在录一套比较深入的 TypeScript 课程，无废话</title>
      <description>&lt;p&gt;话不多说，课程观看链接：&lt;span class="embed-responsive embed-responsive-16by9"&gt;&lt;iframe class="embed-responsive-item" src="//player.bilibili.com/player.html?bvid=1ig411k7pf" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;课程特点：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;体系化讲解而不是碎片化知识，前面 20 节课我通过一张 PPT 串联起来了，目前已经上传了 33 节课&lt;/li&gt;
&lt;li&gt;不照本宣科，我一不按书本上讲，二不照着文档读，而是根据自己多年的经验，讲一些我觉得重要的地方&lt;/li&gt;
&lt;li&gt;普通话清晰，这一点你听一下就知道了&lt;/li&gt;
&lt;li&gt;每周三周五晚 9 点半直播，全称免费（只有录屏、讲义和答疑群收费）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;喜欢的同学请点赞、评论、收藏，不要吝惜你的赞美和批评，这样我才有动力做下一期课程！&lt;/p&gt;</description>
      <author>FrankFang</author>
      <pubDate>Mon, 22 Aug 2022 16:50:17 +0800</pubDate>
      <link>https://ruby-china.org/topics/42605</link>
      <guid>https://ruby-china.org/topics/42605</guid>
    </item>
    <item>
      <title>Ruby 怎么就是网红了？</title>
      <description>&lt;p&gt;我最近看到的一篇叫做《&lt;a href="https://www.36kr.com/p/1648643660768642" rel="nofollow" target="_blank" title=""&gt;不要学习「网红」编程语言&lt;/a&gt;》，里面提到 Ruby 和 Rails 的衰落，并且告诫大家慎重学习 Ruby。&lt;/p&gt;

&lt;p&gt;我看完真的挺想吐槽的……&lt;/p&gt;
&lt;h2 id="Ruby 和 Rails 是网红？"&gt;Ruby 和 Rails 是网红？&lt;/h2&gt;
&lt;p&gt;首先，最近十年中国的网红编程语言怎么排也排不到 Ruby 吧？最红的 Python 已经被培训机构卷成红海，排名第二的网红我不知道应该选 JavaScript 还是 Java，曾经红极一时的 PHP 现在怎么也是网红前三吧？最近一年的网红当属 Go 和 Rust 这对兄弟了。可 Ruby 何时在中国成为网红过？我觉得这篇文章的作者应该是捡软柿子捏，找了个最不红的 Ruby 吐吐槽，可能是以为中国的 Ruby 程序员已经死绝了，可惜我就是 Ruby 程序员……&lt;/p&gt;

&lt;p&gt;好吧，不讲国内只看国外，Ruby 确实在国外红过，但 Ruby 在国外也还没死啊。&lt;/p&gt;

&lt;p&gt;Tiobe 语言排名中 Ruby 还排在 Rust、Dart、Lua、TypeScript、Clojure 前面。&lt;/p&gt;

&lt;p&gt;如果是看趋势，那 PHP 的颓势妥妥地超过了 Ruby：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/FrankFang/ba1f3b24-c015-446a-835d-58e05d315c67.png!large" title="" alt="Stackoverflow 提问量"&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/FrankFang/b7a711cd-826f-43e0-9e64-852c6b6bd54f.png!large" title="" alt="Google 搜索热度"&gt;&lt;/p&gt;

&lt;p&gt;所以在我看来，Ruby 在国内从来没红过，在国外也不是死得最快的，作者只是挑了个粉丝最少的怼。&lt;/p&gt;
&lt;h2 id="不推荐学 Ruby 和 Rails ？"&gt;不推荐学 Ruby 和 Rails？&lt;/h2&gt;
&lt;p&gt;其次，不知道作者为什么不推荐学习 Ruby 和 Rails 却推荐 Node.js 和 Python。我虽然也不是很推荐大家学 Ruby on Rails，但是我「更」不推荐 Node.js 和 Python。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Node.js 的 Express 是借鉴了 Ruby 的 Sinatra，为什么我这么说？因为这是 Express 的作者 TJ 在 Express 1.0 beta 的发布日志中说的原话&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yesterday I released Express 1.0.0beta, a Sinatra inspired Node web development framework.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Python 的 Flask 据说也是受 Sinatra 启发而开发的。（我并没有找到原话）&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js 的 Yarn 借鉴了 Ruby 的 bundler，以及 Rust 的 Cargo 还有 npm&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js 的 SASS 就是从 Ruby 社区拿来的&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Node.js 的 Sails.js 后端框架试图模仿 Rails 但是失败了&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ruby 社区有太多经典设计值得程序员搬运到其他语言了。&lt;/p&gt;

&lt;p&gt;如果有人叫你不要去看 Ruby / Rails，我猜是他不知道 Ruby / Rails 里有多少宝藏。&lt;/p&gt;
&lt;h2 id="学 Ruby 和 Rails 的正确姿势"&gt;学 Ruby 和 Rails 的正确姿势&lt;/h2&gt;
&lt;p&gt;读到这里你可能认为我的意思是推荐大家「学」Ruby 和 Rails。但并不是。&lt;/p&gt;

&lt;p&gt;我的意思是推荐大家用其他语言去「抄」Ruby 和 Rails。&lt;/p&gt;

&lt;p&gt;毕竟用 Ruby 和 Rails 的商业公司很少，所以我推荐大家用 JS、GoLang、Rust、Java 把 Ruby 和 Rails 里面做得好的东西抄袭过来。&lt;/p&gt;

&lt;p&gt;但「抄」的前提是你要了解 Ruby 和 Rails。&lt;/p&gt;

&lt;p&gt;所以你一定要看看 Ruby 和 Rails 里的宝藏，虽然你大概率不可能靠 Ruby 和 Rails 吃饭，但你可以靠「抄」Ruby 和 Rails 晋升。你没有听错。比如我就曾在阿里巴巴看到有后端用 Java 和 Groovy 造出了一个类似 Rails 的框架，极大地提高了开发效率，广受好评，最后晋升（真事儿）。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;后面是我的&lt;a href="https://mp.weixin.qq.com/s/Abn8Y66021p1ATfuqndmZA" rel="nofollow" target="_blank" title=""&gt;新项目课&lt;/a&gt;介绍，就不贴在这里了。&lt;/p&gt;</description>
      <author>FrankFang</author>
      <pubDate>Thu, 07 Apr 2022 17:16:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/42285</link>
      <guid>https://ruby-china.org/topics/42285</guid>
    </item>
    <item>
      <title>Webpack 源码精读视频课</title>
      <description>&lt;p&gt;高级前端面试中经常有这么几道题：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;说一说 loader 和 plugin 的区别&lt;/li&gt;
&lt;li&gt;webpack 构建流程是怎样的&lt;/li&gt;
&lt;li&gt;编写 webpack loader 的思路&lt;/li&gt;
&lt;li&gt;编写 webpack plugin 的思路&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;网上能搜到一些答案，但是这些答案我一一看过了，要么过于肤浅留于表面，要么冗长繁杂难以卒读。&lt;/p&gt;

&lt;p&gt;因此，我花了一个星期把 Webpack 5 的源码逐行扫了一遍，理出了主要脉络。整个阅读过程我录制成了视频，，总时长不到 3 小时，但把 Webpack 的整体架构、打包思路、loader 实现思路、plugin 实现思路、parser 运行流程等都讲到了，最重要的是，通过视频你会掌握「阅读源码的技巧」。&lt;/p&gt;

&lt;p&gt;如果你需要此&lt;a href="https://xiedaimala.com/courses/32694a1c-6f3b-4e3a-b36d-e55a6c1d74a6/random/c930a7592b#/common" rel="nofollow" target="_blank" title=""&gt;视频课程&lt;/a&gt;，请加微信 xiedaimala03 &lt;/p&gt;

&lt;p&gt;接下来是文字教程（文字教程并不适合用来阐述源码，但好在免费）：&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;&lt;img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/637c07e3a8f44808bd479cfc31834e4f~tplv-k3u1fbpfcp-watermark.image" title="" alt="webpack 流程分析.png"&gt;&lt;/p&gt;
&lt;h2 id="webpack-cli 是如何调用 wepack 的"&gt;webpack-cli 是如何调用 wepack 的&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webpack = require('webpack')
compiler = webpack(options, callback)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="hooks.xxx.call 是什么"&gt;hooks.xxx.call 是什么&lt;/h2&gt;
&lt;p&gt;Tapable 是 webpack 团队为了写 Webpack 而写的一个事件/钩子库&lt;/p&gt;

&lt;p&gt;用法&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;定义一个事件/钩子
this.hooks.eventName = new SyncHook(["arg1", "arg2"]);
监听一个事件/钩子
this.hooks.eventName.tap('监听理由', fn)
触发一个事件/钩子
this.hooks.eventName.call('arg1', 'arg2')
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="Webpack 的整体流程是怎样的"&gt;Webpack 的整体流程是怎样的&lt;/h2&gt;
&lt;p&gt;至少有 env init run beforeCompile compile compilation make finishMake seal optimize afterCompile emit 等钩子&lt;/p&gt;
&lt;h2 id="读取 index.js 并分析和收集依赖是在哪个阶段？"&gt;读取 index.js 并分析和收集依赖是在哪个阶段？&lt;/h2&gt;
&lt;p&gt;make - finishMake 阶段&lt;/p&gt;
&lt;h2 id="make - finishMake 之间，做了什么"&gt;make - finishMake 之间，做了什么&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;搜索 make.tap，发现很多地方监听了 make 事件&lt;/li&gt;
&lt;li&gt;凭借我们的直觉，我们直接打开 EntryPlugin&lt;/li&gt;
&lt;li&gt;EntryPlugin 的 addEntry 函数就是 make 阶段最重要的事情之一&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="factory.create 中的 factory 是什么东西？"&gt;factory.create 中的 factory 是什么东西？&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;这个 factory 是哪里来的？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;是从 factorizeModule(options 的 options.factory 来的。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;这个 options.factory 是哪里来的？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;是从 moduleFactory 来的。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;moduleFactory 哪里来的？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;是用 this.dependencyFactories.get(Dep) 得到的。&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;this.dependencyFactories.get(Dep) 是个啥？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;你搜 compilation.tap 就知道，它是 normalModuleFactory，简称 nmf&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;老师，你 TM 怎么知道要搜这个？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我把所有钩子都搜了，搜了半个小时，能不知道吗？&lt;/p&gt;

&lt;p&gt;结论：factory 就是 nmf，所以 factory.create 就是 nmf.craete&lt;/p&gt;
&lt;h2 id="nmf.create 做了什么？"&gt;nmf.create 做了什么？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;nmf.create 得到了一个 module 对象&lt;/li&gt;
&lt;li&gt;后续操作是 addModule 和 buildModule&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="addModule 做了什么？"&gt;addModule 做了什么？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;跟前面课程的思路类似，把 module 添加到 compilation.modules 里&lt;/li&gt;
&lt;li&gt;而且还通过检查 id 防止重复添加&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="buildModule 做了什么？"&gt;buildModule 做了什么？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;看名字就知道是重要操作，它调用了 module.build()&lt;/li&gt;
&lt;li&gt;来到 NormalModule.js 看 build 源码，发现了 runLoaders&lt;/li&gt;
&lt;li&gt;然后来到 processResult()，发现了 _source = ... 和 _ast = null&lt;/li&gt;
&lt;li&gt;这是要做什么？显然是要把 _source 变成 _ast 了！&lt;/li&gt;
&lt;li&gt;来到 doBuild 的回调，发现了 this.parser.parse() ！&lt;/li&gt;
&lt;li&gt;parse 就是把 code 变成 ast&lt;/li&gt;
&lt;li&gt;问题来了，parser 是什么，parse() 的源码在哪？&lt;/li&gt;
&lt;li&gt;继续跟代码会发现 parser 来自于 acorn 库，需要编译原理知识，不跟进了&lt;/li&gt;
&lt;li&gt;如果你想要学习编译原理知识，可以购买我的科班课程&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="Webpack 如何知道 index.js 依赖了哪些文件"&gt;Webpack 如何知道 index.js 依赖了哪些文件&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;blockPreWalkStatement() 对 ImportDeclaration 进行了检查&lt;/li&gt;
&lt;li&gt;一旦发现 import 'xxx'，就会触发钩子，对应的监听函数会处理依赖&lt;/li&gt;
&lt;li&gt;其中 walkStatements() 对 ImportExpression 进行了检查&lt;/li&gt;
&lt;li&gt;一旦发现 import('xxx')，就会触发钩子，对应的监听函数也会处理依赖&lt;/li&gt;
&lt;li&gt;这里不讨论 require，大家有兴趣可以自己研究&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="Webpack 是怎么把 modules 合并成一个文件的？"&gt;Webpack 是怎么把 modules 合并成一个文件的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;看 compilation.seal()，该函数会创建 chunks、为每个 chunk 进行 codeGeneration，然后为每个 chunk 创建 asset&lt;/li&gt;
&lt;li&gt;seal() 之后，emitAssets()、emitFiles() 会创建文件（emit 就是射）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="* 最终得到 dist/main.js 和其他 chunk 文件"&gt;* 最终得到 dist/main.js 和其他 chunk 文件&lt;/h2&gt;
&lt;p&gt;今年，我将研读更多前端项目源码并做成新的视频课程，敬请期待。&lt;/p&gt;

&lt;p&gt;如果有什么开源项目的源码是你想了解的，欢迎留言。&lt;/p&gt;

&lt;p&gt;完。&lt;/p&gt;</description>
      <author>FrankFang</author>
      <pubDate>Thu, 11 Mar 2021 13:09:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/41017</link>
      <guid>https://ruby-china.org/topics/41017</guid>
    </item>
    <item>
      <title>assert_template 被移出 Rails 5 是基于什么考虑？</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/rspec/rspec-rails/issues/1393" rel="nofollow" target="_blank"&gt;https://github.com/rspec/rspec-rails/issues/1393&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我看了这个 issue，但是英文理解能力有限……&lt;/p&gt;

&lt;p&gt;请赐教。&lt;/p&gt;</description>
      <author>FrankFang</author>
      <pubDate>Mon, 28 Nov 2016 20:59:23 +0800</pubDate>
      <link>https://ruby-china.org/topics/31723</link>
      <guid>https://ruby-china.org/topics/31723</guid>
    </item>
    <item>
      <title>如何关联多个第三方登录 (oAuth2)</title>
      <description>&lt;p&gt;最近在学习 Rails，做 oAuth2 登录的时候想不通一个问题。
需求：
User 表示用户，Identity 表示一个第三方认证（Facebook、GitHub 或 Twitter），User has many Identity。
现在希望做到的流程是（问题出在第 5 步）&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;用户用 Facebook 登录（得到一个 Identity 记录），系统生成一个空的 user 记录，提示需要先设置这个 user 的 email 和 password&lt;/li&gt;
&lt;li&gt;于是用户设置了自己的 email 和 password，系统更新 user。&lt;/li&gt;
&lt;li&gt;用户登出&lt;/li&gt;
&lt;li&gt;同一个用户，用 GitHub 登录（有得到一个 Identity 记录）&lt;/li&gt;
&lt;li&gt;系统这是仍然会生成一个空的 user 记录，并提示「需要先设置 user 的 email 和 password」。这样做是有问题的，因为一个用户，对应两个 user 了，难道我以后还要想办法合并这两个 user 吗？&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;我觉得我这样做有问题，但是又不知道怎么解决。
请指教。&lt;/p&gt;</description>
      <author>FrankFang</author>
      <pubDate>Sun, 25 Sep 2016 22:29:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/31165</link>
      <guid>https://ruby-china.org/topics/31165</guid>
    </item>
  </channel>
</rss>
