Rails 6.0 详细介绍全面切换 assets pipeline 到 webpacker

rails

本文首发于 RubyChina,这里是我私人博客,如需讨论,建议移步 RubyChina 对应帖子,帖子地址

开篇说明:本文力争成为介绍和开始使用 webpacker 最好用的中文入门文档,欢迎各位提出改进建议。

Rails 6 默认启用了 webpacker 作为 Javascript 文件的管理方案,但使用起来与 assets pipeline 颇有不同,但 webpacker 的优点非常明显,所以强烈建议各位 Railser 切换,故此这里详细介绍。

在文尾,我们 dao42 团队准备了开箱即用的初始化新项目方案,有兴趣动手的朋友可以研究一番。

webpacker 的好处

  1. webpacker 编译很快,可以让你节省大量开发成本。
  2. webpacker 是目前前端界标准事实的打包工具,从此引用 JS 库不用找 gem 包了。
  3. webpacker 让你写 JS 更规范,可以直接用 ES6。

webpacker 的安装

Rails 6.0 默认已经安装了 webpacker,但同时也安装了 assets pipeline( sprockets ),两者混合使用差异较大,我推荐完全移除 assets pipeline:

新项目

$ rails new my_app --webpack --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

第二步,删除 app/assets 目录,在 app/javascript 目录分别创建 styles/, fonts/, js, images 目录。

第三步,解掉 app/javascript/packs/application.js 中的 images 打包注释:

const images = require.context('../images', true)
const imagePath = (name) => images(name, true)

第四步,将 app/views/layouts/application.html.erb 中的 stylesheet_include_tag 替换为 stylesheet_pack_tag

最后,在开发时不要忘了启动 bin/webpack-dev-server,这个工具可以实时编译资源,并帮你刷新浏览器。

webpacker 下如何写我们的 JS 与 CSS

上述安装配置后,我们彻底移除了 assets pipeline,现在我们的目录布局如下:

app/javascript/packs/: 放在这里面的 js 文件.,最终会打包出来供 javascript_pack_tag 引用。

app/javascript/js/: 在这里写我们自己的 JS 逻辑。

app/javascript/styles/: 在这里写我们自己的 CSS 逻辑。推荐直接写 SCSS。

app/javascript/images/: 放项目用到的图片资源。fonts/ 目录类同。

思维调整

我们从思维上要发生一个根本变化,即:一切皆 JS。所以我们的 CSS 也需要在 application.js 中引入:

import 'styles/application'

模块隔离

webpacker 会将各文件中的对象都隔离,所以无须担心互相影响,也没有所谓的全局变量。所以写一个组件也变得很简单:

// app/javascript/js/a.js
var a = 1
export default a
// app/javascript/js/b.js
import a from './a'
console.log(a)

引入前端库

引入前端库变的简单了:

先用 yarn 安装一下

$ yarn add bootstrap

然后在 app/javascript/packs/application.js 中引用

import 'bootstrap/dist/js/bootstrap'

CSS 中是这样的,app/javascript/styles/application.scss 引用

@import 'bootstrap/scss/bootstrap';

以上路径可以直接去相关前端库的安装说明中找即可。

注意: 引用相对路径时一定要加上 ./,否则不生效并且不一定报错。

JS 调试

webpacker 默认已经将 map 文件装载,所以调试起来仍然相当方便。见下图

同时,也可以用 debugger 指令来强制下断点。

View 中引用资源的方法

stylesheet_link_tagjavascript_include_tag 均已废弃不再使用。

现在常用的几个

1.stylesheet_pack_tag: 加载 CSS 资源

用法:

stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload'

2.javascript_pack_tag: 加载 JS 资源

用法

javascript_pack_tag 'application', 'data-turbolinks-track': 'reload'

3.asset_pack_path: 类似于 asset_path,加载图片、字体等资源

用法( 注意 media/images 这个路径,要加上 media 这个前缀,而且不能使用相对路径 )

asset_pack_path('media/images/favicon.ico')

4.image_pack_tag: 取代image_tag,更明确的加载图片

用法

image_pack_tag 'media/images/calendar.png'

或( 两者等价 )

image_pack_tag 'calendar.png'

webpacker 的原理简单说明

webpacker 是包装自 webpack 并且基本做到零配置开箱即用。配置文件在 config/webpacker.yml,无须做任何调整。

webpack 分为 Entry, Output, Loaders, Plugins 几个关键概念。最新的大版本是 v4。

webpack 会将所有的资源都进行依赖分析,生成依赖树,并最终打成一个或多个包。

示例: 常用库的安装

jQuery

$ yarn add jquery@3.3.1

添加一个 webpack 插件,确保 $, jQuery, 'window.jQuery' 可以在JS库中使用。

// config/webpack/environment.js

const webpack = require('webpack')
environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    'window.jQuery': 'jquery',
    Popper: ['popper.js', 'default']
  })
)

开始使用

// app/javascript/packs/application.js
import 'jquery'

Bootstrap

$ yarn add bootstrap@4.3.1 popper.js

在 app/javascript/styles/ 中创建 bootstrap_custom.scss

// app/javascript/styles/bootstrap_custom.scss
@import 'bootstrap/scss/bootstrap';
// app/javascript/styles/application.scss
@import 'bootstrap_custom'

最后,引用 JS:

// app/javascript/packs/application.js
import 'bootstrap/dist/js/bootstrap'

rails-template

是不是仍然感觉有点复杂,没关系, dao42/rails-template 已经为你的新项目初始化做好了开箱即用。

dao42/rails-template 已经经历过 2 年半的持续升级维护,做好了新项目很多方面的开箱即用。

  1. dao42/rails-template 全面拥抱 webpacker。
  2. dao42/rails-template 集成最新的 bootstrap4, font-awesome5,无须额外任何配置。
  3. dao42/rails-template 集成 mina 发布套件,一键发布项目。

点击这里开始体验 webpacker 的便利之处:dao42/rails-template

参考文稿

发表于 2019.07.11


wotogo • 2021-01-20 11:42

找了好久才找到你这篇文章,照着做后,启动 puma 报错:

Expected to find a manifest file in `app/assets/config/manifest.js` (Sprockets::Railtie::ManifestNeededError)
But did not, please create this file and use it to link any assets that need
to be rendered by your app:

Example:
//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
and restart your server