From cf872d6d1935d127ac067dfd668d656acc8ce336 Mon Sep 17 00:00:00 2001 From: Nick Pezza Date: Wed, 20 Dec 2023 19:43:20 -0500 Subject: [PATCH 1/2] Add puma plugin --- README.md | 7 ++++ lib/puma/plugin/tailwindcss.rb | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 lib/puma/plugin/tailwindcss.rb diff --git a/README.md b/README.md index 4c540e8..91075bb 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,13 @@ The inline version also works:
Has the image as it's background
``` +## Puma plugin +We provide a Puma plugin if you want to run the Tailwind watcher together with Puma and have Puma monitor and manage it. Add +```ruby +plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development" +``` +to your `puma.rb` configuration. + ## License Tailwind for Rails is released under the [MIT License](https://opensource.org/licenses/MIT). diff --git a/lib/puma/plugin/tailwindcss.rb b/lib/puma/plugin/tailwindcss.rb new file mode 100644 index 0000000..d78b068 --- /dev/null +++ b/lib/puma/plugin/tailwindcss.rb @@ -0,0 +1,63 @@ +require "puma/plugin" + +Puma::Plugin.create do + attr_reader :puma_pid, :tailwind_pid, :log_writer + + def start(launcher) + @log_writer = launcher.log_writer + @puma_pid = $$ + @tailwind_pid = fork do + Thread.new { monitor_puma } + system(*Tailwindcss::Commands.watch_command) + end + + launcher.events.on_stopped { stop_tailwind } + + in_background do + monitor_tailwind + end + end + + private + def stop_tailwind + Process.waitpid(tailwind_pid, Process::WNOHANG) + log "Stopping tailwind..." + Process.kill(:INT, tailwind_pid) if tailwind_pid + Process.wait(tailwind_pid) + rescue Errno::ECHILD, Errno::ESRCH + end + + def monitor_puma + monitor(:puma_dead?, "Detected Puma has gone away, stopping tailwind...") + end + + def monitor_tailwind + monitor(:tailwind_dead?, "Detected tailwind has gone away, stopping Puma...") + end + + def monitor(process_dead, message) + loop do + if send(process_dead) + log message + Process.kill(:INT, $$) + break + end + sleep 2 + end + end + + def tailwind_dead? + Process.waitpid(tailwind_pid, Process::WNOHANG) + false + rescue Errno::ECHILD, Errno::ESRCH + true + end + + def puma_dead? + Process.ppid != puma_pid + end + + def log(...) + log_writer.log(...) + end +end From 18a721ec77bd6f95561b1f9544efb44e7b3dded8 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 4 Jan 2024 16:52:17 -0500 Subject: [PATCH 2/2] doc: rework README to feature the Puma plugin and add a CHANGELOG entry --- CHANGELOG.md | 5 +++++ README.md | 34 ++++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1a7f5d..d79f998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## next / unreleased + +* Introduce a Puma plugin to manage the Tailwind "watch" process from `rails server`. (#300) @npezza93 + + ## v2.1.0 / 2023-12-19 * Update to [Tailwind CSS v3.4.0](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.0) from v3.3.6 by @flavorjones diff --git a/README.md b/README.md index 91075bb..a78f6c8 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,26 @@ The `tailwindcss:build` task is automatically attached to the `test:prepare` Rak ### Update assets automatically -While you're developing your application, you want to run Tailwind in "watch" mode, so changes are automatically reflected in the generated CSS output. You can do this by: +While you're developing your application, you want to run Tailwind in "watch" mode, so changes are automatically reflected in the generated CSS output. You can do this in a few different ways: -- running `rails tailwindcss:watch` as a separate process, -- or by running `./bin/dev` which uses [foreman](https://github.com/ddollar/foreman) to start both the Tailwind watch process and the rails server in development mode. +- use the [Puma](https://puma.io/) plugin to integrate "watch" with `rails server`, or +- run `rails tailwindcss:watch` as a separate process, or +- run `bin/dev` which uses [Foreman](https://github.com/ddollar/foreman) + +#### Puma plugin + +The Puma plugin requires you to add this line to your `puma.rb` configuration: + +```ruby +plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development" +``` + +and then running `rails server` will run the Tailwind watch process in the background + + +#### Run `rails tailwindcss:watch` + +This is a flexible command, which can be run with a few different options. If you are running `rails tailwindcss:watch` on a system that doesn't fully support file system events, pass a `poll` argument to the task to instruct tailwindcss to instead use polling: `rails tailwindcss:watch[poll]`. If you use `bin/dev` then you should modify your `Procfile.dev`. @@ -72,6 +88,11 @@ If you are running `rails tailwindcss:watch` as a process in a Docker container, If you are running `rails tailwindcss:watch` in a docker container without a tty, pass the `always` argument to the task to instruct tailwindcss to keep the watcher alive even when `stdin` is closed: `rails tailwindcss:watch[always]`. If you use `bin/dev` then you should modify your `Procfile.dev`. +#### Foreman + +Running `bin/dev` invokes Foreman to start both the Tailwind watch process and the rails server in development mode based on your `Procfile.dev` file. + + ### Debugging with unminified assets If you want unminified assets, you can pass a `debug` argument to the rake task, i.e. `rails tailwindcss:build[debug]` or `rails tailwindcss:watch[debug]`. @@ -171,13 +192,6 @@ The inline version also works:
Has the image as it's background
``` -## Puma plugin -We provide a Puma plugin if you want to run the Tailwind watcher together with Puma and have Puma monitor and manage it. Add -```ruby -plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development" -``` -to your `puma.rb` configuration. - ## License Tailwind for Rails is released under the [MIT License](https://opensource.org/licenses/MIT).