如何在 Rails 7 引擎中使用 Tailwind CSS gem?

2024-01-21

如何在轨道发动机中使用顺风?根据文档,向 Rails 生成器提供 css 参数应该可以工作

使用 Rails 7.0.2.2 引擎生成

rails plugin new tailtest --mountable --full -d postgresql --css tailwind

这会使用 Postgresql 生成引擎,但对 tailwind 根本不起作用,并且遵循手动安装说明也会失败。

运行,按照文档 https://tailwindcss.com/docs/guides/ruby-on-rails, bundle add tailwindcss-rails将 tailwind 添加到 gemfile 而不是引擎 tailtest.gemspec 因此,将依赖项添加到 gemspec 后

spec.add_dependency "tailwindcss-rails", "~> 2.0"

和跑步bundle install确实安装了引擎,但是其余的手动安装失败

然后将 require 添加到 lib/engine.rb

require "tailwindcss-rails"
module Tailtest
  class Engine < ::Rails::Engine
    isolate_namespace Tailtest
  end
end

然后运行安装过程失败

rails tailwindcss:install
Resolving dependencies...
rails aborted!
Don't know how to build task 'tailwindcss:install' (See the list of available tasks with `rails --tasks`)
Did you mean?  app:tailwindcss:install

显然app:tailwindcss:install命令也失败。

所以我可能在 engine.rb 文件中缺少某种初始化程序,但不知道它应该是什么。


这是相同的想法如何在 Rails 7 引擎中设置 importmap-rails? https://stackoverflow.com/questions/69635552/how-to-set-up-importmap-rails-in-rails-7-engine/72095996#72095996。我们不需要使用安装任务。即使您能够运行它,它对引擎也没有帮助(请参阅答案末尾的解释)。

Also rails plugin new没有--css选项。要查看可用选项:rails plugin new -h.

更新引擎的 gemspec 文件:

# my_engine/my_engine.gemspec

spec.add_dependency "tailwindcss-rails"

Update 引擎.rb:

# my_engine/lib/my_engine/engine.rb

module MyEngine
  class Engine < ::Rails::Engine
    isolate_namespace MyEngine

    # NOTE: add engine manifest to precompile assets in production, if you don't have this yet.
    initializer "my-engine.assets" do |app|
      app.config.assets.precompile += %w[my_engine_manifest]
    end
  end
end

更新资产清单:

# my_engine/app/assets/config/my_engine_manifest.js

//= link_tree ../builds/ .css

更新引擎的布局:

# my_engine/app/views/layouts/my_engine/application.html.erb

<!DOCTYPE html>
<html>
  <head>
   <%# 
       NOTE: make sure this name doesn't clash with anything in the main app.
             think of it as `require` and `$LOAD_PATH`,
             but instead it is `stylesheet_link_tag` and `manifest.js`.
    %>
    <%= stylesheet_link_tag "my_engine", "data-turbo-track": "reload" %>
  </head>
  <body> <%= yield %> </body>
</html>

bundle show命令将为我们提供 gem 安装的路径,因此我们可以复制一些文件:

$ bundle show tailwindcss-rails
/home/alex/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/tailwindcss-rails-2.0.8-x86_64-linux

Copy tailwind.config.js文件来自tailwindcss-rails:

$ cp $(bundle show tailwindcss-rails)/lib/install/tailwind.config.js config/tailwind.config.js

Copy 应用程序.tailwind.css将文件放入任何目录以适合您的设置:

$ cp $(bundle show tailwindcss-rails)/lib/install/application.tailwind.css app/assets/stylesheets/application.tailwind.css

Because tailwindcss-rails使用独立的可执行文件,我们不需要节点或rails来编译样式表。我们只需要获取可执行文件本身。

可执行文件位于此处https://github.com/rails/tailwindcss-rails/tree/v2.0.8/exe/ https://github.com/rails/tailwindcss-rails/tree/v2.0.8/exe/。而不是运行构建任务https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/build.rake https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/build.rake我们可以直接调用可执行文件。

$ $(bundle show tailwindcss-rails)/exe/tailwindcss -i app/assets/stylesheets/application.tailwind.css -o app/assets/builds/my_engine.css -c config/tailwind.config.js --minify

Use -w启动观看模式的选项。

$ $(bundle show tailwindcss-rails)/exe/tailwindcss -i app/assets/stylesheets/application.tailwind.css -o app/assets/builds/my_engine.css -c config/tailwind.config.js --minify -w

输出文件应与中的名称匹配stylesheet_link_tag "my_engine".

现在你已经有了一个简单的my_engine.css文件,用它做你想做的事。在布局中使用它,从主应用程序中需要它应用程序.css。通常的铁路资产管道规则适用。

如果您想将所有这些放入任务中,请使用Engine.root获取路径。

# my_engine/lib/tasks/my_engine.rake

task :tailwind_engine_watch do
  require "tailwindcss-rails"
  # NOTE: tailwindcss-rails is an engine
  system "#{Tailwindcss::Engine.root.join("exe/tailwindcss")} \
         -i #{MyEngine::Engine.root.join("app/assets/stylesheets/application.tailwind.css")} \
         -o #{MyEngine::Engine.root.join("app/assets/builds/my_engine.css")} \
         -c #{MyEngine::Engine.root.join("config/tailwind.config.js")} \
         --minify -w"
end

从引擎目录:

$ bin/rails app:tailwind_engine_watch
+ /home/alex/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/tailwindcss-rails-2.0.8-x86_64-linux/exe/x86_64-linux/tailwindcss -i /home/alex/code/stackoverflow/my_engine/app/assets/stylesheets/application.tailwind.css -o /home/alex/code/stackoverflow/my_engine/app/assets/builds/my_engine.css -c /home/alex/code/stackoverflow/my_engine/config/tailwind.config.js --minify -w

Rebuilding...
Done in 549ms.

如果您有很多引擎需要设置,请创建自己的安装任务:

desc "Install tailwindcss into our engine"
task :tailwind_engine_install do
  require "tailwindcss-rails"

  # NOTE: use default app template, which will fail to modify layout, manifest,
  #       and the last command that compiles the initial `tailwind.css`.
  #       It will also add `bin/dev` and `Procfile.dev` which we don't need.
  #       Basically, it's useless in the engine as it is.
  template = Tailwindcss::Engine.root.join("lib/install/tailwindcss.rb")

  # TODO: better to copy the template from 
  #       https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/install/tailwindcss.rb
  #       and customize it
  # template = MyEngine::Engine.root("lib/install/tailwindcss.rb")

  require "rails/generators"
  require "rails/generators/rails/app/app_generator"
  
  # NOTE: because the app template uses `Rails.root` it will run the install
  #       on our engine's dummy app. Just override `Rails.root` with our engine
  #       root to run install in the engine directory.
  Rails.configuration.root = MyEngine::Engine.root

  generator = Rails::Generators::AppGenerator.new [Rails.root], {}, { destination_root: Rails.root }
  generator.apply template
end

安装任务参考:
https://github.com/rails/rails/blob/v7.0.2.4/railties/lib/rails/tasks/framework.rake#L8 https://github.com/rails/rails/blob/v7.0.2.4/railties/lib/rails/tasks/framework.rake#L8
https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/install.rake https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/install.rake

观看任务参考:
https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/build.rake#L10 https://github.com/rails/tailwindcss-rails/blob/v2.0.8/lib/tasks/build.rake#L10


Update如何合并两个顺风。

上面的设置假设引擎是它自己独立的东西,就像管理后端一样,它有自己的路由、模板和样式。如果引擎功能旨在与主应用程序混合,例如视图组件集合,那么顺风风格将相互覆盖。在这种情况下,使用前缀隔离引擎样式可能会起作用:
https://tailwindcss.com/docs/configuration#prefix https://tailwindcss.com/docs/configuration#prefix

顺风风格不混合的原因是大多数选择器具有相同的特异性 https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity并且顺序非常重要。

这是一个例子。带有引擎的主应用程序,都使用 tailwind,都单独编译样式,tailwind 配置仅监视引擎中的一个文件和主应用程序中的一个文件,仅使用@tailwind实用程序;指示:

我们想要在主应用程序中使用的引擎模板应该可以正常工作:

<!-- blep/app/views/blep/_partial.html.erb -->

<div class="bg-red-500 sm:bg-blue-500"> red never-blue </div>

但当在主应用程序中渲染时,它永远不会变成蓝色。这是演示设置:

<!-- app/views/home/index.html.erb -->

<%= stylesheet_link_tag "blep",     "data-turbo-track": "reload" %>
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>

<!-- output generated css in the same order as above link tags -->
<% require "open-uri" %>
<b>Engine css</b>
<pre><%= URI.open(asset_url("blep")).read %></pre>
<b>Main app css</b>
<pre><%= URI.open(asset_url("tailwind")).read %></pre>

<div class="bg-red-500"> red </div> <!-- this generates another bg-red-500 -->
<br>
<%= render "blep/partial" %>

它看起来像这样:

/* Engine css */
.bg-red-500 {
  --tw-bg-opacity: 1;
  background-color: rgb(239 68 68 / var(--tw-bg-opacity))
}

@media (min-width: 640px) {
  .sm\:bg-blue-500 {
    --tw-bg-opacity: 1;
    background-color: rgb(59 130 246 / var(--tw-bg-opacity))
  }
}

/* Main app css */
.bg-red-500 {
  --tw-bg-opacity: 1;
  background-color: rgb(239 68 68 / var(--tw-bg-opacity))
}
<div class="bg-red-500"> red </div>
<br>
<div class="bg-red-500 sm:bg-blue-500"> red never-blue </div>

^ 您可以点击“运行”并单击“整页”。主应用程序bg-red-500选择器是最后一个,因此它会覆盖引擎sm:bg-blue-500选择器、媒体查询不会增加特异性得分。这和你不能覆盖的原因是一样的,mt-1 with m-2,边距顶部出现在样式表的后面。这就是为什么@layer指令很重要。

解决这个问题的唯一方法是在主应用程序中运行 tailwind 时观察引擎目录,以便样式以正确的顺序一起编译。这意味着您实际上并不需要发动机顺风:

module.exports = {
  content: [
    "./app/**/*",
    "/just/type/the/path/to/engine/views",
    "/or/see/updated/task/below",
  ],
}

我尝试过的其他方法,例如为主应用程序和引擎的每一层运行 6 个 tailwind 命令,这样我就可以将它们按顺序排列,效果更好,但仍然有点乱序并且重复。或者做一个@import并以某种方式让postcss-导入知道在哪里寻找引擎样式(我不知道,我只是将其符号链接到节点模块来测试),但这仍然需要顺风来观察引擎文件。


我又做了一些挖掘,tailwindcli 有一个--content选项,这将覆盖content from tailwind.config.js。我们可以用它来设置一个新任务:

namespace :tailwindcss do
  desc "Build your Tailwind CSS + Engine"
  task :watch do |_, args|
    # NOTE: there have been some updates, there is a whole Commands class now
    #       lets copy paste and modify.          (debug = no --minify)
    command = Tailwindcss::Commands.watch_command(debug: true, poll: false)

    # --content /path/to/app/**/*,/path/to/engine/**/*
    command << "--content"
    command << [
      Rails.root.join("app/views/home/*"),
      Blep::Engine.root.join("app/views/**/*.erb")
    ].join(",")

    p command
    system(*command)
  end

  # same for build, just call `compile_command`
  # task :build do |_, args|
  #   command = Tailwindcss::Commands.compile_command(debug: false)
  #   ...
end

https://github.com/rails/tailwindcss-rails/blob/v2.0.21/lib/tasks/build.rake#L11 https://github.com/rails/tailwindcss-rails/blob/v2.0.21/lib/tasks/build.rake#L11

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Rails 7 引擎中使用 Tailwind CSS gem? 的相关文章

随机推荐

  • MVC 捆绑不起作用

    我正在开发一个小型 mvc 项目 我已经在 BundleConfig cs 中声明了一个包 如下所示 JavaScript 包 bundles Add new ScriptBundle bundles Layout1JS Include C
  • 如何让 chrome 自动填充异步帖子

    我有一个表单 因为它是异步提交的
  • 节点 - fs.statbirthtimeMs 和 mtimeMs

    我在 Windows 的文件系统 NTFS 上创建了一个空文件 我打了电话fs stat并意识到birthtimeMs和mtimeMs是相等的 这对我的情况很有好处 因为我需要检测是否有人在此期间没有以某种方式更改文件 所以在 Window
  • 找到可执行文件的路径

    我使用 Go 为各种平台编译一个程序 并通过调用相对路径或仅通过其名称 如果它位于 PATH 变量中 来运行它 是否可以找出可执行文件在哪里 比如说 我的程序叫做 foo exe 我可以跑 foo foo 如果它在路径中 subdir su
  • 强制转换 (int?)null 与 new int?() - 哪个更好?

    I use Nullable
  • 没有默认构造函数的值初始化

    我想知道在什么情况下一个类可能没有默认构造函数但仍然会被值初始化 无默认构造函数 的典型情况是存在参数化构造函数但不存在默认构造函数违约 default 引用 2020 年标准第 9 4 1 章 初始化器 常规 最新草案包含等效措辞 对 T
  • Android:正弦波生成

    我正在尝试使用 AudioTrack 生成正弦波 方波和锯齿波 然而 它创建的音频听起来不像纯正弦波 而是像叠加了某种其他波 在使用第一个示例中的方法的同时 如何获得像第二个代码示例中那样的纯正弦波 由于上面的例子只涉及第二个例子中使用的一
  • Git hooks - 如何仅处理属于存储库内特定文件夹的文件?

    我对 git 有点陌生 对 bash 不太擅长 我有一个存储库 如果重要的话 在 Bitbucket 中 它只包含两个文件夹 我已经有一个钩子 用 bash 编写 可以触发 Jenkins 作业 现在我想更改它 因此它将仅针对提交到其中一个
  • 从另一个包加载 spritekit 场景?

    我正在使用 swift 4 2 制作 SpriteKit 框架 并希望包含一些用于场景和动作的 sks 文件 我尝试使用以下代码从包中加载场景 class func newGameScene gt GameScene guard let g
  • 设置文本时停止调整 UITextField 大小

    我有一个视图设置 其中布局了 4 个 UITextFields 并设置了约束 以便它在所有设备上看起来都很棒并且按预期工作 我有一个问题 如果我使用 TextField text some long text 设置文本或 TextField
  • 如何从 sqlite (3.6.21) 表中删除约束?

    我有下表 CREATE TABLE child id INTEGER PRIMARY KEY parent id INTEGER CONSTRAINT parent id REFERENCES parent id description T
  • 跨隐藏跨度搜索文本 (Ctrl+F)

    Is it possible to search for text using your browser s Ctrl F function across three span tags if the middle tag is set t
  • 突出显示特定日期(来自 bean 的值)

    使用素面
  • C++11 中的纯函数

    C 11 中的一个可以以某种方式gcc将函数 不是类方法 标记为const告诉它是pure并且不使用全局内存而仅使用其参数 我试过了gcc s attribute const 它是恰恰我想要的是 但当函数中触及全局内存时 它不会产生任何编译
  • PHP $_POST 不带重音符号

    这个问题已经解决了 看我的回答看看解决方案 我试图通过使用 POST 提交到 PHP 页面的 html 表单向我的数据库添加带有重音字母的文本 问题是重音字母被转换为不可读的字符 我有这个表格
  • 在目录树中查找具有给定扩展名的文件

    我有一个文件夹 其中有一些文件和子文件夹 例如 我需要返回具有给定扩展名的文件名或相对地址 如果文件位于子文件夹中 html 例如 这是给定文件夹的结构 文本 某事 ncx 文本 123 html 内容 opf toc ncx Flow 0
  • Ctrl+。 (点) 使“e”出现,而不是在 Gnome 上的 VSCode 中显示建议

    我在 Gnome 上使用 VSCode 在 Arch 上的 XOrg 上 最近以来 捷径Ctrl 停止工作 尽管仍然列在键盘快捷键中并且所有扩展都被禁用 相反 带有下划线的e出现 当按两次 Enter 或按一次 ESC 时 该字符消失 当写
  • MySQL Join on LIKE 语句

    我需要计算数据库中每个组中有多少用户 不幸的是 数据库设计不是很好 用户 uid 是针对组表中的组存储在 LONGTEXT 字段列名称 owncloudusers 中 owncloudusers 数据示例 i 0 s 36 25C967BD
  • 使用不同的 dockerfiles 从源目录构建 docker 镜像

    我的目标是从相同的源代码构建几个不同的 docker 镜像 我有我的 src 文件夹 node js 项目 在 src 内我有第一个 dockerfile 和第二个 dockerfile 为了构建项目 我使用这个标准命令行 sudo doc
  • 如何在 Rails 7 引擎中使用 Tailwind CSS gem?

    如何在轨道发动机中使用顺风 根据文档 向 Rails 生成器提供 css 参数应该可以工作 使用 Rails 7 0 2 2 引擎生成 rails plugin new tailtest mountable full d postgresq