这是我在 [北京] [2019 年 3 月 9 日] Ruby Saturday 的讲稿
Webpacker 是 Rails 官方团队提出的一套在 Rails 上集成 Webpack 的方案
慢、不支持最新的 ES 标准、接入现代风格的 NPM 包困难
对于新创建的应用,可以使用 --skip-sprockets
对于旧应用,将 config/application.rb
中默认的 require 'rails/all'
修改成
require "rails"
%w(
active_record/railtie
active_storage/engine
action_controller/railtie
action_view/railtie
action_mailer/railtie
active_job/railtie
action_cable/engine
action_mailbox/engine
action_text/engine
rails/test_unit/railtie
sprockets/railtie
).each do |railtie|
begin
require railtie
rescue LoadError
end
end
(实际上就是 rails/all
的源码)
然后删除 sprockets/railtie
搜索 config
目录下,文本搜索所有 assets
关键字,注释或删除
参考 config/webpacker.yml
的注释,将 resolved_paths: []
修改成 resolved_paths: ['app/assets']
以此将 Rails 的 app/assets
目录加入到 Webpack 的查找路径
参考 Webpack 文档 Dependency Management 中提到的 require.context
函数,从其文档中摘抄
const importAll = (r) => r.keys().map(r)
importAll(require.context('images', false, /\.(png|jpe?g|svg)$/i));
到 javascript/application.js
即可
用 Webpack 提供的 import
,如果迁移自 Sprockets,样式文件在 assets/stylesheets
的话,代码形如 import "stylesheets/application"
stylesheet_tag
=> stylesheet_pack_tag
javascript_tag
=> javascript_pack_tag
asset_path
=> asset_pack_path
image_tag
=> image_pack_tag
asset_url
=> asset_pack_url
Webpacker 额外提供了 stylesheet_packs_with_chunks_tag 用于暴露 Webpack 的 SplitChunksPlugin
Rails 会把模型验证失败的字段的 <input>
用 <div class="field_with_errors">
包裹,这会破坏一些前端框架的行为
这个行为是 ActionView::Base.field_error_proc
的默认实现,可以覆盖他屏蔽掉这个行为,参考:
https://github.com/jasl/cybros_core/blob/master/config/initializers/action_view.rb
一个来自官方指南 Rails Guide 的隐藏技巧
https://edgeguides.rubyonrails.org/engines.html#overriding-models-and-controllers
利用 class_eval
特性实现的 Override pattern
参考
这段代码增强了 form helpers 的行为,增加了 class_for_error
参数,当字段验证失败时渲染指定的 class
,并且增加了 error_message
helper 当字段错误时渲染错误信息。
这样强化过的 form helpers 使得 simple_form
在通常情况下不在需要(当然我在示例中没有做太重的封装),并且让代码保持干爽。
效果形如:https://github.com/jasl/cybros_core/blob/master/app/views/admin/users/_form.html.erb
https://github.com/jasl/cybros_core
一些几年没有更新的库,有可能 import 后为 null 的情况,需要检查这个库是否使用 js 的 export 进行导出,如果不是则无法用在 webpack 中。
window
对象在 webpack 的 entry 中引入的库,都无法在外部可见,这会影响大多数 jQuery 插件,
因为很多时候我们需要在 HTML 中插入 <script>
所以你需要通过这种方式将 jQuery 导出到 window
对象,以便 HTML 中的 <script>
工作正常
window.$ = window.jQuery = require("jquery");
涉及引用静态资源的库,需要做一些处理,才能正确的让 webpack 包含这些静态资源, 比如示例应用中包含了 web font 引入的 Font Awesome,参考
https://github.com/jasl/cybros_core/blob/master/app/assets/stylesheets/application.scss#L5
遇到这种库,需要分析一下其源码,如果其路径不可定制,则可能无法引入到 webpack 中,这里不下定论,需要具体问题具体分析
作为初级前端,我仍然推崇 Turbolinks,因为无需特别处理,即可达到前后端分离的无闪屏页面切换体验,但是,一些新的库会与其冲突。
Font Awesome 的 JS 引入方式的效果是其 JS 会监视 DOM 变化,发现是图标的标签则将其替换成 SVG(这里不讨论这样设计的意义), 这种方式在 Turbolinks 下,有可能造成闪屏,建议使用传统 Web font 方式引入。
在 Turbolinks 下直接使用 React 时,页面切换会导致 React 的状态不重置并且重复执行,有一些解决相关问题的库,如 https://github.com/renchap/webpacker-react