refrakt_cli/dev

refrakt dev — run the app in development with rebuilds and live reload.

Sets APP_ENV=dev, builds the app and starts it with gleam run. Then it watches src/ and priv/:

Files are watched with fswatch when it is installed, else with inotifywait on Linux, else by polling every 500ms. Bursts of events (an editor saving several files) are debounced into one rebuild.

The process work (ports, sockets, polling) lives in refrakt_cli_dev_ffi.erl; the decisions it makes are the functions below, so they can be unit-tested.

Types

What a batch of file changes calls for.

pub type Change {
  Rebuild
  ReloadOnly
  NoChange
}

Constructors

  • Rebuild

    Something under src/ changed: rebuild and restart.

  • ReloadOnly

    Only files under priv/ changed: they are served as they are, so reloading the browser is enough.

  • NoChange

    Only editor scratch files changed.

How refrakt dev notices file changes.

pub type Watcher {
  Fswatch(executable: String)
  Inotifywait(executable: String)
  Polling(interval_ms: Int)
}

Constructors

  • Fswatch(executable: String)

    fswatch (macOS, BSD, Linux), given its path.

  • Inotifywait(executable: String)

    inotifywait from inotify-tools (Linux), given its path.

  • Polling(interval_ms: Int)

    Compare file sizes, times and contents every interval_ms.

Values

pub fn changed_paths(
  before: dict.Dict(String, stamp),
  after: dict.Dict(String, stamp),
) -> List(String)

The paths that were added, removed or changed between two polling snapshots, sorted.

pub fn choose_watcher(
  os os: String,
  fswatch fswatch: Result(String, Nil),
  inotifywait inotifywait: Result(String, Nil),
) -> Watcher

Prefer fswatch, then inotifywait on Linux, then polling.

pub fn classify(changes: List(#(String, String))) -> Change

Decide what a debounced batch of #(watched_dir, path) changes calls for. Editor scratch files (swap files, backups, dotfiles) are ignored.

pub const debounce_ms: Int

How long to wait for more file events before acting on a burst.

pub const default_live_reload_port: Int

The default port of the live reload event stream.

pub fn describe_watcher(watcher: Watcher) -> String
pub fn is_relevant(path: String) -> Bool

False for files editors write while saving: dotfiles (.post.swp, .#post.gleam), backups (post.gleam~), and vim’s 4913 probe.

pub fn live_reload_port(value: Result(String, Nil)) -> Int

The port from REFRAKT_LIVE_RELOAD_PORT, or the default when it is unset or not a port number.

pub const poll_interval_ms: Int

How often the polling watcher compares snapshots.

pub fn run() -> Nil
✨ Search Document