原文发布在 https://geeknote.net/Rei/posts/1224
有留意 Rails 更新的人应该会注意到,Rails 7 新增了一个组件选项 Propshaft。
$ rails new --help
-a, [--asset-pipeline=ASSET_PIPELINE] # Choose your asset pipeline [options: sprockets (default), propshaft]
# Default: sprockets
Assets Pipeline 是 Rails 从 3.1 开始内置的前端文件处理机制,它内部实现的库叫做 Sprockets。过去谈论 Assets Pipeline 跟 Sprockets 几乎不做区分,因为两者几乎重叠。而 Rails 7 开始 Assets Pipeline 提供另一个实现,那就是 Propshaft。
Sprockets 是一个完整的前端构建工具,它可以对 js,css 进行编译、打包、最小化等处理,支持 CoffeeScript,Sass 编译器,还有一套自制的链接声明。如果只使用 CoffeeScript 和 Sass,并且所需的库都有对应的 gem 包,那么它的工作一直良好。
到了 Rails 7,新的前端方案是 Assets Pipeline + JS/CSSbundling,静态文件的编译、打包、最小化等处理都在 Assets Pipeline 之前进行,Pipeline 只需要做文件名哈希和提供文件名映射,这时 Sprockets 的功能就变得冗余了。
引申阅读:Rails 7 前端方案前瞻
功能的冗余有时会导致 Bug,例如已经编译好的 js 文件,再经过 Sprockets 处理会在末尾插入一个 ;
,有时会导致问题(Issue #24)。目前 Sprockets 内部有大量预设的处理器,很多都用不上。理想情况下,Sprockets 应该提供配置方法关闭内置的处理器。也许是 Sprockets 的代码历史包袱太重,DHH 选择了新建一个简化版的 Sprockets——也就是现在的 Propshaft。
Propshaft 只做最精简的功能,包括:
以下功能并不包含在 Propshaft 中:
这些功能应该使用外部的编译工具完成。
对于新项目,使用以下命令就可以自动配置 Propshaft:
$ rails new myapp -a propshaft
对于已有项目,先要确保不依赖 Sprockets 提供的编译功能,例如换用 Sass 编译 css,用 esbuild 打包 js。
完成 bundling 迁移后,按以下步骤迁移 propshaft:
sprockets-rails
,添加 propshaft
。bundle
。asset/config/manifest.js
。image_url
,asset_url
等 helper 换成 url
。完成。
Sprockets 在 CSS 上下文提供了一些 assets helper,例如 image_url
,asset_url
来引用静态资源。在 Propshaft 中不需要这些 helper,直接用标准的 url
,它会自行替换。
例如:
- background: image_url('hero.jpg');
+ background: url('hero.jpg');
在 view 中引用静态资源依然使用 image_url
和 asset_url
这些方法。
Sprockets 提供了 asset/config/manifest.js
和 Rails.application.config.assets.precompile
两个方法设置编译目标。Propshaft 不提供这个设置,而是把 assets.paths
里面的所有文件当作编译目标。
你可以用以下命令检查 Propshaft 会编译生成哪些文件:
$ rake assets:reveal
如无意外,你会发现很多不需要的文件也被当作编译目标了,例如 app/assets/stylesheets
下的 scss 源文件。
可以用以下配置排除一些目录:
Rails.application.config.assets.excluded_paths = [
Rails.root.join("app/assets/stylesheets")
]
Sprockets 对于已经使用的项目依然可以工作,为了兼容第三方 gem,Sprockets 还会维护很长时间,所以不必急着迁移。
如果项目正在往 bundling 方案迁移,那么不妨一同迁移 Propshaft,让 Assets Pipeline 的流程更精简,减少 bug。