vike-ripple 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +42 -31
  2. package/package.json +1 -1
  3. package/src/setup.js +14 -6
package/README.md CHANGED
@@ -1,11 +1,13 @@
1
- # @vike-ripple/vike-ripple
1
+ # vike-ripple
2
+
3
+ > ⚠️ **HIGHLY EXPERIMENTAL** — This package is in early development. APIs may change without notice, parts may not work, and documentation may be incomplete. Use at your own risk.
2
4
 
3
5
  [Vike](https://vike.dev) integration for [Ripple TS](https://ripple-ts.com) — SSR rendering, client hydration with mount fallback, streaming, `<head>` management, and `.tsrx` page file support.
4
6
 
5
7
  ## Install
6
8
 
7
9
  ```sh
8
- npm install @vike-ripple/vike-ripple
10
+ npm install vike-ripple
9
11
  ```
10
12
 
11
13
  ## Setup
@@ -24,35 +26,28 @@ Or add to your project's `package.json` so it runs automatically after `npm inst
24
26
  }
25
27
  ```
26
28
 
27
- ### 2. Add plugin to `vite.config.ts`
29
+ ### 2. Configure `vite.config.ts`
28
30
 
29
31
  ```ts
30
32
  import { defineConfig } from 'vite'
31
33
  import vike from 'vike/plugin'
32
34
  import { ripple } from '@ripple-ts/vite-plugin'
33
- import vikeRipple from '@vike-ripple/vike-ripple'
35
+ import vikeRipple from 'vike-ripple'
34
36
 
35
37
  export default defineConfig({
36
- optimizeDeps: {
37
- exclude: ['ripple'],
38
- },
39
- plugins: [
40
- vikeRipple(),
41
- ripple({ excludeRippleExternalModules: true }),
42
- vike(),
43
- ],
38
+ optimizeDeps: { exclude: ['ripple'] },
39
+ plugins: [vikeRipple(), ripple({ excludeRippleExternalModules: true }), vike()],
44
40
  })
45
- > **Why `optimizeDeps.exclude: ['ripple']`?** Ripple uses module-scoped variables (`first_child_getter`) shared between `hydrate()` and DOM traversal functions. Vite's dependency optimization splits these into separate bundles, breaking the scope sharing and causing `TypeError: Cannot read properties of undefined (reading 'call')` at `get_first_child` during hydration. Excluding `ripple` from optimization ensures all Ripple internals stay in one module scope.
41
+ ```
46
42
 
47
- ### 3. Add renderer files
43
+ ### 3. Add renderer config
48
44
 
49
- Copy from `node_modules/@vike-ripple/vike-ripple/src/renderer/` to your project's `renderer/`:
45
+ Create `renderer/+config.ts`:
50
46
 
51
- ```
52
- renderer/
53
- +config.ts
54
- +onRenderHtml.tsx
55
- +onRenderClient.tsx
47
+ ```ts
48
+ export default {
49
+ extends: ['import:vike-ripple/config:default'],
50
+ }
56
51
  ```
57
52
 
58
53
  ### 4. Create a page
@@ -71,22 +66,38 @@ export function Page(props: {}) @{
71
66
  }
72
67
  ```
73
68
 
69
+ ## Features
70
+
71
+ | Feature | Status |
72
+ |---|---|
73
+ | `.tsrx` page file support | ✅ |
74
+ | SSR rendering | ✅ |
75
+ | Client hydration with mount fallback | ✅ |
76
+ | Streaming SSR (`rippleStream` config) | ✅ |
77
+ | `<head>` tag extraction | ✅ |
78
+ | `+Layout.tsrx` support | ✅ |
79
+ | `+Head.tsrx` support | ✅ |
80
+ | Config: `title`, `description`, `image`, `viewport`, `favicon`, `lang` | ✅ |
81
+ | Config: `ssr` toggle, `stream` toggle | ✅ |
82
+ | Config: `htmlAttributes`, `bodyAttributes` | ✅ |
83
+ | Config: `headHtmlBegin/End`, `bodyHtmlBegin/End` | ✅ |
84
+ | Hooks: `onBefore/AfterRenderHtml`, `onBefore/AfterRenderClient` | ✅ |
85
+ | `@tailwindcss` integration (via `vike-ripple-tailwindcss`) | ✅ |
86
+ | `@apply` in `<style>` blocks (via `vike-ripple-tailwindcss`) | ✅ |
87
+ | HMR stability during development | 🟡 |
88
+ | TypeScript types for `Vike.Config` / `Vike.PageContext` | 🟡 |
89
+ | Production build testing | 🔴 |
90
+
74
91
  ## What this does
75
92
 
76
93
  | Patch | Why |
77
94
  |---|---|
78
95
  | **`.tsrx` extension** | Vike doesn't know `.tsrx` is a valid page extension — adds it to `isScriptFile.js` |
79
96
  | **`?direct` CSS loading** | Vite's SSR module loader appends `?direct` to module IDs; Ripple's `load` hook checks cache with the wrong key |
80
- | **Hydrate → mount fallback** | Ripple's `hydrate` can mismatch when `<title>` or `<head>` content is extracted during SSR but missing from the client DOM; falls back to `mount` gracefully |
81
-
82
- ## API
83
-
84
- ### `vikeRipple()`
85
-
86
- Vite plugin. Must be placed before `ripple()` in the plugins array, with `enforce: 'pre'` behavior.
97
+ | **`@apply` support** | Prepends `@import "tailwindcss" layer(reference)` to extracted CSS so `@apply` resolves in `<style>` blocks |
87
98
 
88
- ### Renderer files
99
+ ## Known Issues
89
100
 
90
- - **`+onRenderHtml.tsx`** SSR via `ripple/server`'s `render()`, extracts `<head>`, `<body>`, and CSS, injects them into Vike's HTML template. Supports streaming via `rippleStream` config.
91
- - **`+onRenderClient.tsx`** Hydrates with `hydrate()` from `ripple`, falls back to `mount()` on error. Imports `tailwind.css` if present.
92
- - **`+config.ts`** Disables prerender by default, registers `rippleStream` meta config.
101
+ - **Hydration errors**: Ripple's `hydrate()` may throw `TypeError: Illegal invocation` due to Vite dep optimization. Fixed by `optimizeDeps.exclude: ['ripple']` and the mount fallback in the client renderer.
102
+ - **HMR hang**: Editing `.tsrx` files during dev may occasionally cause HMR to hang. Restarting the dev server resolves it.
103
+ - **`</style>` in template literals**: If a `.tsx` file contains `</style>` inside a JavaScript string, the Tailwind Oxide scanner may emit a `CssSyntaxError`. Workaround: break the literal with string concatenation: `"<" + "/style>"`. See [tailwindcss#20000](https://github.com/tailwindlabs/tailwindcss/issues/20000).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-ripple",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Vike extension for Ripple TS — full parity with vike-react/vike-solid/vike-vue",
5
5
  "type": "module",
6
6
  "types": "./src/types/Config.ts",
package/src/setup.js CHANGED
@@ -1,3 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * vike-ripple setup — patches Vike and Ripple for .tsrx support.
4
+ *
5
+ * Run once: npx vike-ripple setup
6
+ * Or add to project's package.json: "postinstall": "vike-ripple setup"
7
+ */
1
8
  import { createRequire } from 'module'
2
9
  import { join } from 'path'
3
10
  import { readFileSync, writeFileSync, existsSync } from 'fs'
@@ -54,7 +61,7 @@ function patchRippleDirect() {
54
61
  log('Patched Ripple plugin for ?direct CSS module loading')
55
62
  }
56
63
 
57
- // ── Patch 3: @apply support via @reference (no HMR loops) ─────
64
+ // ── Patch 3: @apply support ───────────────────────────────────
58
65
  function patchRippleApply() {
59
66
  const target = resolveRipple('src/index.js')
60
67
  if (!target) return
@@ -69,15 +76,16 @@ function patchRippleApply() {
69
76
  '// TW_PATCH: prepend tailwindcss so @apply works',
70
77
  '// TW_PATCH_APPLY: bring tailwindcss into scope for @apply',
71
78
  )
79
+ src = src.replace(
72
80
  "css = '@import \"tailwindcss\";\\n' + css;",
73
81
  "css = '@import \"tailwindcss\" layer(reference);\\n' + css;",
74
82
  )
75
83
  writeFileSync(target, src, 'utf-8')
76
- log('Upgraded @apply patch to @reference (prevents HMR loops)')
84
+ log('Upgraded @apply patch to layer(reference) (HMR-safe)')
77
85
  return
78
86
  }
79
87
 
80
- // Fresh install — prepend @reference comment + tailwind for HMR safety
88
+ // Fresh install — prepend @import with reference layer
81
89
  const orig = (
82
90
  '\t\t\t\t\tif (css) {\n' +
83
91
  '\t\t\t\t\t\tconst cssId = createVirtualImportId(filename, root, \'style\');\n' +
@@ -94,20 +102,20 @@ function patchRippleApply() {
94
102
  const result = src.replace(orig, patched)
95
103
  if (result === src) { warn('Could not patch Ripple plugin for @apply'); return }
96
104
  writeFileSync(target, result, 'utf-8')
97
- log('Patched Ripple plugin for @apply support in <style> blocks (HMR-safe)')
105
+ log('Patched Ripple plugin for @apply support in <style> blocks')
98
106
  }
99
107
 
100
108
  // ── Resolve helpers ────────────────────────────────────────────
101
109
  function resolveVike(rel) {
102
110
  const p = join(projectRoot, 'node_modules', 'vike', rel)
103
111
  if (existsSync(p)) return p
104
- try { return createRequire(join(projectRoot, 'noop.js')).resolve('vike/' + rel) } catch { return null }
112
+ try { const r = createRequire(join(projectRoot, 'package.json')); return r.resolve('vike/' + rel) } catch { return null }
105
113
  }
106
114
 
107
115
  function resolveRipple(rel) {
108
116
  const p = join(projectRoot, 'node_modules', '@ripple-ts', 'vite-plugin', rel)
109
117
  if (existsSync(p)) return p
110
- try { return createRequire(join(projectRoot, 'noop.js')).resolve('@ripple-ts/vite-plugin/' + rel) } catch { return null }
118
+ try { const r = createRequire(join(projectRoot, 'package.json')); return r.resolve('@ripple-ts/vite-plugin/' + rel) } catch { return null }
111
119
  }
112
120
 
113
121
  // ── Main ──────────────────────────────────────────────────────