Ruby 为何 我从 Webpacker 切换 到 js-bundling 和 css-bundling

jicheng1014 · 2022年01月16日 · 最后由 yetrun 回复于 2022年10月13日 · 781 次阅读

文章同步发布在了我的 blog http://blog.3qruok.com/posts/12

之前在自己的项目中一直使用的 rails 自带的 webpacker 用来处理下面的前端策略: 用 webpacker 处理:tailwindcss + scss + turbo + stimulusjs + action cable 的结构。随着 rails 7.0 的正式发布,再参看了 DHH 的对新处理前端的方式的介绍,我觉得 他提供的第二种访问,即 jsbundling,cssbundling 的处理方式,比较适合我现在的项目。

为何我会抛弃 webpacker?理由主要有如下几点:

  1. webpacker 处在专业前端看不懂,不专业的后端配不了的尴尬位置。虽然说 webpacker 尽量做到了开箱可用,但是仍然有时候我需要去对齐进行调整。在这个时候我就是完全懵逼的状态,这个时候我让专业的前端来看,却因为 webpacker 的封装的原因,我的同事无法提供有效的帮助。
  2. webpacker 运行起来比较卡。这也许是我机器的原因,webpacker 封装的 webpack 在 16G 内存感觉下还是不太行。但是同等情况下使用 vite 来搞纯前端 vue 就没这种感觉。
  3. webpacker 已不是 rails 推荐的方式了。作为 rails 的重要生态组成部分,一旦不被 rails 推荐,可能以后收到的维护会变少。而前端方案变化太快了,日新月异,虽然现在 仍然是 webpack 的天下,但是谁也不好说以后前端打包方案会不会倒向 rollup 或者退回到 grunt 啥的。

那又说到了,为啥要转化到 jsbundling 和 cssbundling,而不是 rails 官方最推荐的默认方式:importmap 呢?

那就要分析 importmap 的优缺点了。这是我总结的 importmap 的优劣。

优势: 因为 importmap 是完全基于浏览器的,所以启动一个完整的项目,是可以脱离 nodejs 环境的。即我们可以完全通过 importmap 对应的 cdn 地址,也可以实现不同 npm 包,直接的 import 引用。另外由于不需要本地处理 js,也就没有裁剪,压缩啥的在本地运行,会大大加速了开发的速度。

劣势:

  1. 兼容性。虽然说 现在主流的浏览器都支持了 import map,但是我没办法确认是否老版本的 android, ios,特别是老版本的微信内置的浏览器,是否支持 importmap
  2. 目前 importmap 暂时不能自动引入依赖文件,如果有某个 js 依赖其他 js,则需要一直手动调用,会比较麻烦。
  3. 无法快速支持 react 的 jsx 或者 vue 的 .vue 文件。如果本身引用了这种前端框架,因为 import map 由于是浏览器级别的引入,所以对这种非 js 标准模式的文件的时候会有一定的问题。虽然可以通过引入其他 js,换一种方式写 jsx 语法之类的来解决这个问题,但是这东西又需要额外的成本了。

所以我选择了第二种方式 js-bundling 和 css-bundling 来解决我前端问题。

js-bundling 和 css-bundling 是如何解决这些前端的问题的呢? 其实就是 他们只做为 rails 与前端世界的桥梁,专业的事交给专业的工具来做,bundling 只提供将这些产物于 rails 的传统前端做一个链接。

其实 js-bundling 和 css-bundling 只是一些脚手架脚本,他们唯一做的事情,就是将 你用专业的前端工具生成的产物,连接到 rails 的 sprocket 中去。

我们以 js-bundling 为例,当你使用 js-bundling 之后,他会推荐你使用 esbuild 或者 rollup 或者 webpack 来处理你的 js,之后将处理好的产物放在 assets/builds/ 中 之后同时 js-bundling 也会生成一个 assets/config/manifest.js 文件,在这里指定 所有的 assets/builds 映射到 assets/ 上。最重要的是,js-bundling 会在你的 assets:precompile 中做一个钩子,在你 assets:precompile 的时候调用 package.json 中的 对前端的 build 指令,你可以打开 package.json 看 到,这里的 dev 实际上就是用 你选择的 或 esbuild, 或 rollup 或 webpack, 将你的前端文件,最后打包到 assets/builds 文件夹里去。

最后,就是 rails 4 时代大家比较熟悉的事情。将你生成的前端文件,算 hash,生成文件,丢到 public/assets 下。

css-bundling 和 js-bundling 的效果几乎一样,唯一的区别是,他的脚手架代码 换成了 build 时候使用 sass 或者 tailwindcss 或者 postcss 而已。

那么,js-bundling,css-bundling 的优势是什么呢?

  1. 我认为最大的好处就是 合理解耦了现代前端工具与 rails 框架。现代前端方案变的太快了,百花齐放百家争鸣,谁也不知道最后的赢家是谁,与其挨个适配,不如万变不离其宗,就抓住所有的前端打包工具的最终目的,都是打包出产物,我就处理好产物与 rails 的关系即可。
  2. 专业的事情交给专业的工具,遇到问题,交给专业的人,比如我 jsbundling 选择 webpack 来处理产物,webpack 遇到的问题就是 webpack 的知识体系内的问题,找个 webpack 配置工程师就解决战斗了,这个人甚至可以不需要懂 ruby 懂 rails。
  3. 可以灵活的更换前端打包规则。比如我嫌弃 webpack 运算速度慢,就可以使用 esbuild,我嫌 esbuild 兼容性差,我也可以开发的时候用 esbuild,production 环境用 rollup,只要我将最后的产物扔到 assets/builds 文件夹里就行。

那有没有劣势呢?我觉得有以下几点值得注意:

  1. 你需要一个比较完备的知识体系,需要了解现代 前端打包的本质目的是什么。
  2. 你需要保持清醒,js-bundling 或者 css-bundling 只是胶水,真正起作用的,是 esbuild, 或者 webpack,如果打包出问题了,你需要了解这些前端的打包知识,或者你有一个能够提供前端打包支持的同事

当我确认我能够客服这些劣势后,我认为 js-bundling 和 css-bundling 给我带来的优势是非常大的,于是我选择了这种前端模式

最后,我采取的模式是 js-bundling 配套 esbuild 处理 js , css-bundling 结合 postcss 处理 css。

在这里需要额外说明的是,当我使用了 esbuild 后,原来默认的 webpack 的读取文件的方式就不可用了。在我的架构中,主要影响的是 stimulujs 的引用和 channels 的引用。原来那种获取当前目录下的所有文件,以及批量导入当前目录所有文件的语法,实际是基于 webpack 的,现在都需要手动将每个文件引用,抽空我再写下这个改造过程。

我看了 bundling 内部实现之后第一想法是这么简单,早这么干就好了。

Rei 回复

可能之前为了实习开箱即用,结果反而搞复杂了。。

Rails 7 这次选择其实以退为进,可以看看来。感觉是挺好,就是现在一把梭的这些模式接受度不高了

非常赞同这个观点。我的理解是:Rails 定位就是快速开发原型然后迭代,为了适配前端变化有点舍本求末的意思,顶多就是通过 api 来适配呗,为啥非要搞那么复杂的前端。

rails 这几年围着前端换来换去的.....

huobazi 回复

Web 前端的小年轻们输出能力爆棚太能造了

huobazi 回复

所以 jsbundling 之后 就万变不离其宗了

iquoyi 回复

非常赞同这个观点。rails 本来就是全栈框架,以少的人,达到高产。

都已经 10 月 13 日,我才知道还能这么搞。那么我选择 WebPack.

需要 登录 后方可回复, 如果你还没有账号请 注册新账号