Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Puma plugin #64

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,34 @@ The installer will create your default Sass input file in `app/assets/stylesheet

If you need to configure the build process – beyond configuring the build files – you can run `bundle exec dartsass` to access the platform-specific executable, and give it your own build options.

When you're developing your application, you want to run Dart Sass in watch mode, so changes are automatically reflected in the generated CSS output. You can do this either by running `rails dartsass:watch` as a separate process, or by running `./bin/dev` which uses [foreman](https://github.com/ddollar/foreman) to start both the Dart Sass watch process and the rails server in development mode.
## Live rebuild

While you're developing your application, you want to run Dartsass in "watch"
mode, so changes are automatically reflected in the generated CSS output. You
can do this in a few different ways:

- use this gem's [Puma](https://puma.io/) plugin to integrate "watch" with `rails server`,
- or run `rails dartsass:watch` as a separate process,
- or run `bin/dev` which uses [Foreman](https://github.com/ddollar/foreman)

### Puma plugin

This gem ships with a Puma plugin. To use it, add this line to your `puma.rb` configuration:

```ruby
plugin :dartsass if ENV.fetch("RAILS_ENV", "development") == "development"
```

and then running `rails server` will run the Dartsass watch process in the background

### Run `rails dartsass:watch`

Running `./bin/rails dartsass:watch` starts the Dartsass process in watch mode.

### Foreman

Running `bin/dev` invokes Foreman to start both the Dartsass watch process and
the rails server in development mode based on your `Procfile.dev` file.

## Installation

Expand Down
4 changes: 4 additions & 0 deletions lib/dartsass/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ def dartsass_load_paths
def dartsass_compile_command
[ RbConfig.ruby, EXEC_PATH ].concat(dartsass_build_options).concat(dartsass_load_paths).concat(dartsass_build_mapping)
end

def dartsass_watch_command
dartsass_compile_command << "--watch"
end
end
end
69 changes: 69 additions & 0 deletions lib/puma/plugin/dartsass.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require "dartsass/runner"
require "puma/plugin"

Puma::Plugin.create do
attr_reader :puma_pid, :dartsass_pid, :log_writer

def start(launcher)
@log_writer = launcher.log_writer
@puma_pid = $$
@dartsass_pid = fork do
Thread.new { monitor_puma }
# Using IO.popen(command, 'r+') will avoid watch_command read from $stdin.
# If we use system(*command) instead, IRB and Debug can't read from $stdin
# correctly bacause some keystrokes will be taken by watch_command.
IO.popen(Dartsass::Runner.dartsass_watch_command, 'r+') do |io|
IO.copy_stream(io, $stdout)
end
end

launcher.events.on_stopped { stop_dartsass }

in_background do
monitor_dartsass
end
end

private
def stop_dartsass
Process.waitpid(dartsass_pid, Process::WNOHANG)
log "Stopping dartsass..."
Process.kill(:INT, dartsass_pid) if dartsass_pid
Process.wait(dartsass_pid)
rescue Errno::ECHILD, Errno::ESRCH
end

def monitor_puma
monitor(:puma_dead?, "Detected Puma has gone away, stopping dartsass...")
end

def monitor_dartsass
monitor(:dartsass_dead?, "Detected dartsass 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 dartsass_dead?
Process.waitpid(dartsass_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
2 changes: 1 addition & 1 deletion lib/tasks/build.rake
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace :dartsass do

desc "Watch and build your Dart Sass CSS on file changes"
task watch: :environment do
system(*Dartsass::Runner.dartsass_compile_command, "--watch", exception: true)
system(*Dartsass::Runner.dartsass_watch_command, exception: true)
end
end

Expand Down
Loading