Module: BunBunBundle::ReloadTag

Includes:
SafeHtml
Defined in:
lib/bun_bun_bundle/reload_tag.rb

Overview

Renders a live reload script tag for development.

Connects to Bun’s WebSocket dev server for:

  • CSS hot-reloading (without full page refresh)

  • Full page reload on JS/image changes

Only outputs content when BunBunBundle.development? is true.

Instance Method Summary collapse

Instance Method Details

#bun_reload_tagObject

Returns the live reload <script> tag, or an empty string in production.

Example (ERB):

<%= bun_reload_tag %>


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/bun_bun_bundle/reload_tag.rb', line 21

def bun_reload_tag # rubocop:disable Metrics/MethodLength
  return '' unless BunBunBundle.development?

  config = BunBunBundle.config
  css_paths = BunBunBundle.manifest.css_entry_points.map do |key|
    "#{config.public_path}/#{key}"
  end

  html = <<~HTML
    <script>
    (() => {
      const cssPaths = #{css_paths.to_json};
      const ws = new WebSocket('#{config.dev_server.ws_url}')
      let connected = false

      ws.onmessage = (event) => {
        const data = JSON.parse(event.data)

        if (data.type === 'css') {
          document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
            const linkPath = new URL(link.href).pathname.split('?')[0]
            if (cssPaths.some(p => linkPath.startsWith(p))) {
              const url = new URL(link.href)
              url.searchParams.set('bust', Date.now())
              link.href = url.toString()
            }
          })
          console.log('\\u25b8 CSS reloaded')
        } else if (data.type === 'error') {
          console.error('\\u2716 Build error:', data.message)
        } else {
          console.log('\\u25b8 Reloading...')
          location.reload()
        }
      }

      ws.onopen = () => {
        connected = true
        console.log('\\u25b8 Live reload connected')
      }
      ws.onclose = () => {
        if (connected) setTimeout(() => location.reload(), 2000)
      }
    })()
    </script>
  HTML
  bun_safe(html)
end