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

jicheng1014 · 2022年01月16日 · 最后由 flyweights 回复于 2022年01月17日 · 605 次阅读

文章同步发布在了我的 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 本来就是全栈框架,以少的人,达到高产。

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