Skip to content

Commit 3041a5b

Browse files
authored
Merge pull request #300 from npezza93/main
Add puma plugin
2 parents 7332768 + 18a721e commit 3041a5b

File tree

3 files changed

+92
-3
lines changed

3 files changed

+92
-3
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## next / unreleased
2+
3+
* Introduce a Puma plugin to manage the Tailwind "watch" process from `rails server`. (#300) @npezza93
4+
5+
16
## v2.1.0 / 2023-12-19
27

38
* Update to [Tailwind CSS v3.4.0](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.4.0) from v3.3.6 by @flavorjones

README.md

+24-3
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,26 @@ The `tailwindcss:build` task is automatically attached to the `test:prepare` Rak
6060

6161
### Update assets automatically
6262

63-
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:
63+
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:
6464

65-
- running `rails tailwindcss:watch` as a separate process,
66-
- 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.
65+
- use the [Puma](https://puma.io/) plugin to integrate "watch" with `rails server`, or
66+
- run `rails tailwindcss:watch` as a separate process, or
67+
- run `bin/dev` which uses [Foreman](https://github.com/ddollar/foreman)
68+
69+
#### Puma plugin
70+
71+
The Puma plugin requires you to add this line to your `puma.rb` configuration:
72+
73+
```ruby
74+
plugin :tailwindcss if ENV.fetch("RAILS_ENV", "development") == "development"
75+
```
76+
77+
and then running `rails server` will run the Tailwind watch process in the background
78+
79+
80+
#### Run `rails tailwindcss:watch`
81+
82+
This is a flexible command, which can be run with a few different options.
6783

6884
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`.
6985

@@ -72,6 +88,11 @@ If you are running `rails tailwindcss:watch` as a process in a Docker container,
7288
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`.
7389

7490

91+
#### Foreman
92+
93+
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.
94+
95+
7596
### Debugging with unminified assets
7697

7798
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]`.

lib/puma/plugin/tailwindcss.rb

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
require "puma/plugin"
2+
3+
Puma::Plugin.create do
4+
attr_reader :puma_pid, :tailwind_pid, :log_writer
5+
6+
def start(launcher)
7+
@log_writer = launcher.log_writer
8+
@puma_pid = $$
9+
@tailwind_pid = fork do
10+
Thread.new { monitor_puma }
11+
system(*Tailwindcss::Commands.watch_command)
12+
end
13+
14+
launcher.events.on_stopped { stop_tailwind }
15+
16+
in_background do
17+
monitor_tailwind
18+
end
19+
end
20+
21+
private
22+
def stop_tailwind
23+
Process.waitpid(tailwind_pid, Process::WNOHANG)
24+
log "Stopping tailwind..."
25+
Process.kill(:INT, tailwind_pid) if tailwind_pid
26+
Process.wait(tailwind_pid)
27+
rescue Errno::ECHILD, Errno::ESRCH
28+
end
29+
30+
def monitor_puma
31+
monitor(:puma_dead?, "Detected Puma has gone away, stopping tailwind...")
32+
end
33+
34+
def monitor_tailwind
35+
monitor(:tailwind_dead?, "Detected tailwind has gone away, stopping Puma...")
36+
end
37+
38+
def monitor(process_dead, message)
39+
loop do
40+
if send(process_dead)
41+
log message
42+
Process.kill(:INT, $$)
43+
break
44+
end
45+
sleep 2
46+
end
47+
end
48+
49+
def tailwind_dead?
50+
Process.waitpid(tailwind_pid, Process::WNOHANG)
51+
false
52+
rescue Errno::ECHILD, Errno::ESRCH
53+
true
54+
end
55+
56+
def puma_dead?
57+
Process.ppid != puma_pid
58+
end
59+
60+
def log(...)
61+
log_writer.log(...)
62+
end
63+
end

0 commit comments

Comments
 (0)