vite_react 0.1.5 → 0.1.8
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.
- checksums.yaml +4 -4
- data/lib/generators/v0/component_generator.rb +33 -0
- data/lib/generators/v0/install_generator.rb +0 -0
- data/lib/generators/vite_react/devise/devise.rb +16 -0
- data/lib/generators/vite_react/migration/migration.rb +3 -6
- data/lib/generators/vite_react/model_validation/model_validation_generator.rb +6 -6
- data/lib/generators/vite_react/scaffold/scaffold_generator.rb +69 -36
- data/lib/generators/vite_react/scaffold/templates/_form.html.erb.tt +43 -0
- data/lib/generators/vite_react/scaffold/templates/edit.html.erb.tt +12 -0
- data/lib/generators/vite_react/scaffold/templates/index.html.erb.tt +31 -0
- data/lib/generators/vite_react/scaffold/templates/new.html.erb.tt +11 -0
- data/lib/generators/vite_react/scaffold/templates/partial.html.erb.tt +16 -0
- data/lib/generators/vite_react/scaffold/templates/show.html.erb.tt +20 -0
- data/lib/generators/vite_react/stripe/stripe.rb +10 -0
- data/lib/install/App.tsx +3 -3
- data/lib/install/AppSSR.tsx +41 -0
- data/lib/install/Procfile.dev +6 -0
- data/lib/install/application.css +89 -60
- data/lib/install/application.jsx +15 -0
- data/lib/install/index.html.erb +1 -1
- data/lib/install/opentelemetry.rb.tt +10 -0
- data/lib/install/postcss.config.mjs +5 -0
- data/lib/install/ssr.ts +70 -0
- data/lib/install/tailwind.config.js +46 -46
- data/lib/install/tsconfig.app.json +1 -1
- data/lib/install/tsconfig.node.json +5 -1
- data/lib/install/{vite.config.js → vite.config.ts} +8 -0
- data/lib/install/vite_react.rb +55 -56
- data/lib/tasks/install.rake +0 -5
- data/lib/vite_react/configuration.rb +15 -0
- data/lib/vite_react/engine.rb +16 -0
- data/lib/vite_react/node_manager.rb +39 -0
- data/lib/vite_react/railtie.rb +112 -10
- data/lib/vite_react/version.rb +1 -1
- data/lib/vite_react.rb +9 -0
- metadata +23 -4
- /data/lib/{install/eslint.config.js → generators/devise/tailwind/tailwind_generator.rb} +0 -0
data/lib/install/application.css
CHANGED
@@ -1,69 +1,98 @@
|
|
1
|
-
@
|
2
|
-
|
3
|
-
@
|
1
|
+
@import "tailwindcss";
|
2
|
+
/*
|
3
|
+
@plugin "@tailwindcss/forms"
|
4
|
+
@plugin "@tailwindcss/typography"
|
5
|
+
@plugin "@tailwindcss/container-queries"
|
6
|
+
@plugin "tailwindcss-animate";
|
7
|
+
*/
|
8
|
+
|
9
|
+
@variant dark (&:where(.dark, .dark *));
|
10
|
+
|
11
|
+
|
12
|
+
@theme {
|
13
|
+
--color-background: var(--background);
|
14
|
+
--color-foreground: var(--foreground);
|
15
|
+
--color-card: var(--card);
|
16
|
+
--color-card-foreground: var(--card-foreground);
|
17
|
+
--color-popover: var(--popover);
|
18
|
+
--color-popover-foreground: var(--popover-foreground);
|
19
|
+
--color-primary: var(--primary);
|
20
|
+
--color-primary-foreground: var(--primary-foreground);
|
21
|
+
--color-secondary: var(--secondary);
|
22
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
23
|
+
--color-muted: var(--muted);
|
24
|
+
--color-muted-foreground: var(--muted-foreground);
|
25
|
+
--color-accent: var(--accent);
|
26
|
+
--color-accent-foreground: var(--accent-foreground);
|
27
|
+
--color-destructive: var(--destructive);
|
28
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
29
|
+
--color-border: var(--border);
|
30
|
+
--color-input: var(--input);
|
31
|
+
--color-ring: var(--ring);
|
32
|
+
--color-chart-1: var(--chart-1);
|
33
|
+
--color-chart-2: var(--chart-2);
|
34
|
+
--color-chart-3: var(--chart-3);
|
35
|
+
--color-chart-4: var(--chart-4);
|
36
|
+
--color-chart-5: var(--chart-5);
|
37
|
+
--radius-lg: var(--radius);
|
38
|
+
--radius-md: calc(var(--radius) - 2px);
|
39
|
+
--radius-sm: calc(var(--radius) - 4px);
|
40
|
+
}
|
4
41
|
|
5
|
-
/* Example theming with CSS variables */
|
6
42
|
@layer base {
|
7
43
|
:root {
|
8
|
-
--background:
|
9
|
-
--foreground:
|
10
|
-
--card: 0 0% 100
|
11
|
-
--card-foreground: 0 0% 3.9
|
12
|
-
--popover: 0 0% 100
|
13
|
-
--popover-foreground: 0 0% 3.9
|
14
|
-
--primary: 0 0% 9
|
15
|
-
--primary-foreground: 0 0% 98
|
16
|
-
--secondary: 0 0% 96.1
|
17
|
-
--secondary-foreground: 0 0% 9
|
18
|
-
--muted: 0 0% 96.1
|
19
|
-
--muted-foreground: 0 0% 45.1
|
20
|
-
--accent: 0 0% 96.1
|
21
|
-
--accent-foreground: 0 0% 9
|
22
|
-
--destructive: 0 84.2% 60.2
|
23
|
-
--destructive-foreground: 0 0% 98
|
24
|
-
--border: 0 0% 89.8
|
25
|
-
--input: 0 0% 89.8
|
26
|
-
--ring: 0 0% 3.9
|
27
|
-
--chart-1: 12 76% 61
|
28
|
-
--chart-2: 173 58% 39
|
29
|
-
--chart-3: 197 37% 24
|
30
|
-
--chart-4: 43 74% 66
|
31
|
-
--chart-5: 27 87% 67
|
44
|
+
--background: var(--color-neutral-50);
|
45
|
+
--foreground: var(--color-neutral-900);
|
46
|
+
--card: hsl(0 0% 100%);
|
47
|
+
--card-foreground: hsl(0 0% 3.9%);
|
48
|
+
--popover: hsl(0 0% 100%);
|
49
|
+
--popover-foreground: hsl(0 0% 3.9%);
|
50
|
+
--primary: hsl(0 0% 9%);
|
51
|
+
--primary-foreground: hsl(0 0% 98%);
|
52
|
+
--secondary: hsl(0 0% 96.1%);
|
53
|
+
--secondary-foreground: hsl(0 0% 9%);
|
54
|
+
--muted: hsl(0 0% 96.1%);
|
55
|
+
--muted-foreground: hsl(0 0% 45.1%);
|
56
|
+
--accent: hsl(0 0% 96.1%);
|
57
|
+
--accent-foreground: hsl(0 0% 9%);
|
58
|
+
--destructive: hsl(0 84.2% 60.2%);
|
59
|
+
--destructive-foreground: hsl(0 0% 98%);
|
60
|
+
--border: hsl(0 0% 89.8%);
|
61
|
+
--input: hsl(0 0% 89.8%);
|
62
|
+
--ring: hsl(0 0% 3.9%);
|
63
|
+
--chart-1: hsl(12 76% 61%);
|
64
|
+
--chart-2: hsl(173 58% 39%);
|
65
|
+
--chart-3: hsl(197 37% 24%);
|
66
|
+
--chart-4: hsl(43 74% 66%);
|
67
|
+
--chart-5: hsl(27 87% 67%);
|
32
68
|
--radius: 0.5rem;
|
33
69
|
}
|
70
|
+
|
34
71
|
.dark {
|
35
|
-
--background:
|
36
|
-
--foreground:
|
37
|
-
--card: 0 0
|
38
|
-
--card-foreground: 0 0% 98
|
39
|
-
--popover: 0 0% 3.9
|
40
|
-
--popover-foreground: 0 0% 98
|
41
|
-
--primary: 0 0% 98
|
42
|
-
--primary-foreground: 0 0% 9
|
43
|
-
--secondary: 0 0% 14.9
|
44
|
-
--secondary-foreground: 0 0% 98
|
45
|
-
--muted: 0 0% 14.9
|
46
|
-
--muted-foreground: 0 0% 63.9
|
47
|
-
--accent: 0 0% 14.9
|
48
|
-
--accent-foreground: 0 0% 98
|
49
|
-
--destructive: 0 62.8% 30.6
|
50
|
-
--destructive-foreground: 0 0% 98
|
51
|
-
--border: 0 0% 14.9
|
52
|
-
--input: 0 0% 14.9
|
53
|
-
--ring: 0 0% 83.1
|
54
|
-
--chart-1: 220 70% 50
|
55
|
-
--chart-2: 160 60% 45
|
56
|
-
--chart-3: 30 80% 55
|
57
|
-
--chart-4: 280 65% 60
|
58
|
-
--chart-5: 340 75% 55
|
72
|
+
--background: var(--color-neutral-950);
|
73
|
+
--foreground: var(--color-neutral-100);
|
74
|
+
--card: hsl(0, 0%, 3.9%);
|
75
|
+
--card-foreground: hsl(0 0% 98%);
|
76
|
+
--popover: hsl(0 0% 3.9%);
|
77
|
+
--popover-foreground: hsl(0 0% 98%);
|
78
|
+
--primary: hsl(0 0% 98%);
|
79
|
+
--primary-foreground: hsl(0 0% 9%);
|
80
|
+
--secondary: hsl(0 0% 14.9%);
|
81
|
+
--secondary-foreground: hsl(0 0% 98%);
|
82
|
+
--muted: hsl(0 0% 14.9%);
|
83
|
+
--muted-foreground: hsl(0 0% 63.9%);
|
84
|
+
--accent: hsl(0 0% 14.9%);
|
85
|
+
--accent-foreground: hsl(0 0% 98%);
|
86
|
+
--destructive: hsl(0 62.8% 30.6%);
|
87
|
+
--destructive-foreground: hsl(0 0% 98%);
|
88
|
+
--border: hsl(0 0% 14.9%);
|
89
|
+
--input: hsl(0 0% 14.9%);
|
90
|
+
--ring: hsl(0 0% 83.1%);
|
91
|
+
--chart-1: hsl(220 70% 50%);
|
92
|
+
--chart-2: hsl(160 60% 45%);
|
93
|
+
--chart-3: hsl(30 80% 55%);
|
94
|
+
--chart-4: hsl(280 65% 60%);
|
95
|
+
--chart-5: hsl(340 75% 55%);
|
59
96
|
}
|
60
97
|
}
|
61
98
|
|
62
|
-
@layer base {
|
63
|
-
* {
|
64
|
-
@apply border-border;
|
65
|
-
}
|
66
|
-
body {
|
67
|
-
@apply bg-background text-foreground;
|
68
|
-
}
|
69
|
-
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import "@hotwired/turbo-rails";
|
2
|
+
import React from "react";
|
3
|
+
import ReactDOM from "react-dom/client";
|
4
|
+
|
5
|
+
function hydrateComponents() {
|
6
|
+
document.querySelectorAll("[data-react-component]").forEach(async (el) => {
|
7
|
+
const componentName = el.getAttribute("data-react-component");
|
8
|
+
const props = JSON.parse(el.getAttribute("data-props") || "{}");
|
9
|
+
const module = await import(`../components/${componentName}.tsx`);
|
10
|
+
const Component = module.default;
|
11
|
+
ReactDOM.hydrateRoot(el, <Component {...props} />);
|
12
|
+
});
|
13
|
+
}
|
14
|
+
|
15
|
+
document.addEventListener("DOMContentLoaded", hydrateComponents);
|
data/lib/install/index.html.erb
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
require "opentelemetry/sdk"
|
2
|
+
require "opentelemetry/instrumentation/rails"
|
3
|
+
require "opentelemetry-exporter-otlp"
|
4
|
+
|
5
|
+
|
6
|
+
OpenTelemetry::SDK.configure do |c|
|
7
|
+
c.service_name = "<%= Rails.application.class.module_parent_name.underscore.dasherize %>"
|
8
|
+
c.use_all()
|
9
|
+
end if Rails.env.production?
|
10
|
+
|
data/lib/install/ssr.ts
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
import express, { Request, Response } from 'express';
|
2
|
+
import { createServer as createViteServer } from 'vite';
|
3
|
+
import React from "react";
|
4
|
+
import { renderToPipeableStream } from "react-dom/server";
|
5
|
+
import parse from 'html-react-parser';
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
const port = process.env.PORT || 4000;
|
10
|
+
|
11
|
+
async function startServer() {
|
12
|
+
const app = express();
|
13
|
+
|
14
|
+
// Create Vite server in middleware mode.
|
15
|
+
const vite = await createViteServer({
|
16
|
+
server: { middlewareMode: true },
|
17
|
+
appType: 'custom'
|
18
|
+
});
|
19
|
+
|
20
|
+
// Use Vite's middleware.
|
21
|
+
app.use(vite.middlewares);
|
22
|
+
|
23
|
+
app.use(express.json());
|
24
|
+
|
25
|
+
// SSR render endpoint
|
26
|
+
app.post("/render", async (req: Request, res: Response) => {
|
27
|
+
try {
|
28
|
+
const { component, props } = req.body;
|
29
|
+
console.log("props", props)
|
30
|
+
render(component, props, res);
|
31
|
+
} catch (error) {
|
32
|
+
vite.ssrFixStacktrace(error as Error);
|
33
|
+
console.error("SSR error:", error);
|
34
|
+
res.status(500).send("Internal Server Error");
|
35
|
+
}
|
36
|
+
});
|
37
|
+
|
38
|
+
app.listen(port, () => console.log(`vite_react_ssr Node server listening on port ${port}`));
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
async function render(componentName: string, props: any, res: Response) {
|
44
|
+
|
45
|
+
const module = await import(`@/ssr-components/${componentName}.tsx`);
|
46
|
+
const Component = module.default;
|
47
|
+
if (props?.children) {
|
48
|
+
props.children = parse(props.children);
|
49
|
+
}
|
50
|
+
|
51
|
+
const element = React.createElement(Component, props);
|
52
|
+
|
53
|
+
const streamObj = renderToPipeableStream(element, {
|
54
|
+
onShellReady() {
|
55
|
+
res.setHeader("Content-Type", "text/html");
|
56
|
+
streamObj.pipe(res);
|
57
|
+
},
|
58
|
+
onShellError(error) {
|
59
|
+
console.error("Shell error:", error);
|
60
|
+
res.status(500).send("Internal Server Error");
|
61
|
+
},
|
62
|
+
onError(error) {
|
63
|
+
console.error("Streaming error:", error);
|
64
|
+
}
|
65
|
+
});
|
66
|
+
}
|
67
|
+
|
68
|
+
startServer();
|
69
|
+
|
70
|
+
|
@@ -1,37 +1,15 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
3
2
|
module.exports = {
|
4
|
-
darkMode: [
|
5
|
-
content: [
|
6
|
-
'./public/*.html',
|
7
|
-
'./app/helpers/**/*.rb',
|
8
|
-
'./app/javascript/**/*.{js,jsx,ts,tsx}',
|
9
|
-
'./app/views/**/*.{erb,haml,html,slim}'
|
10
|
-
],
|
3
|
+
darkMode: ["class"],
|
4
|
+
content: ["app/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
|
11
5
|
theme: {
|
12
6
|
extend: {
|
13
|
-
fontFamily: {
|
14
|
-
sans: [
|
15
|
-
'Inter var',
|
16
|
-
...defaultTheme.fontFamily.sans
|
17
|
-
]
|
18
|
-
},
|
19
|
-
borderRadius: {
|
20
|
-
lg: 'var(--radius)',
|
21
|
-
md: 'calc(var(--radius) - 2px)',
|
22
|
-
sm: 'calc(var(--radius) - 4px)'
|
23
|
-
},
|
24
7
|
colors: {
|
8
|
+
border: 'hsl(var(--border))',
|
9
|
+
input: 'hsl(var(--input))',
|
10
|
+
ring: 'hsl(var(--ring))',
|
25
11
|
background: 'hsl(var(--background))',
|
26
12
|
foreground: 'hsl(var(--foreground))',
|
27
|
-
card: {
|
28
|
-
DEFAULT: 'hsl(var(--card))',
|
29
|
-
foreground: 'hsl(var(--card-foreground))'
|
30
|
-
},
|
31
|
-
popover: {
|
32
|
-
DEFAULT: 'hsl(var(--popover))',
|
33
|
-
foreground: 'hsl(var(--popover-foreground))'
|
34
|
-
},
|
35
13
|
primary: {
|
36
14
|
DEFAULT: 'hsl(var(--primary))',
|
37
15
|
foreground: 'hsl(var(--primary-foreground))'
|
@@ -40,6 +18,10 @@ module.exports = {
|
|
40
18
|
DEFAULT: 'hsl(var(--secondary))',
|
41
19
|
foreground: 'hsl(var(--secondary-foreground))'
|
42
20
|
},
|
21
|
+
destructive: {
|
22
|
+
DEFAULT: 'hsl(var(--destructive))',
|
23
|
+
foreground: 'hsl(var(--destructive-foreground))'
|
24
|
+
},
|
43
25
|
muted: {
|
44
26
|
DEFAULT: 'hsl(var(--muted))',
|
45
27
|
foreground: 'hsl(var(--muted-foreground))'
|
@@ -48,27 +30,45 @@ module.exports = {
|
|
48
30
|
DEFAULT: 'hsl(var(--accent))',
|
49
31
|
foreground: 'hsl(var(--accent-foreground))'
|
50
32
|
},
|
51
|
-
|
52
|
-
DEFAULT: 'hsl(var(--
|
53
|
-
foreground: 'hsl(var(--
|
33
|
+
popover: {
|
34
|
+
DEFAULT: 'hsl(var(--popover))',
|
35
|
+
foreground: 'hsl(var(--popover-foreground))'
|
54
36
|
},
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
37
|
+
card: {
|
38
|
+
DEFAULT: 'hsl(var(--card))',
|
39
|
+
foreground: 'hsl(var(--card-foreground))'
|
40
|
+
}
|
41
|
+
},
|
42
|
+
borderRadius: {
|
43
|
+
lg: '`var(--radius)`',
|
44
|
+
md: '`calc(var(--radius) - 2px)`',
|
45
|
+
sm: 'calc(var(--radius) - 4px)'
|
46
|
+
},
|
47
|
+
keyframes: {
|
48
|
+
'accordion-down': {
|
49
|
+
from: {
|
50
|
+
height: '0'
|
51
|
+
},
|
52
|
+
to: {
|
53
|
+
height: 'var(--radix-accordion-content-height)'
|
54
|
+
}
|
55
|
+
},
|
56
|
+
'accordion-up': {
|
57
|
+
from: {
|
58
|
+
height: 'var(--radix-accordion-content-height)'
|
59
|
+
},
|
60
|
+
to: {
|
61
|
+
height: '0'
|
62
|
+
}
|
64
63
|
}
|
64
|
+
},
|
65
|
+
animation: {
|
66
|
+
'accordion-down': 'accordion-down 0.2s ease-out',
|
67
|
+
'accordion-up': 'accordion-up 0.2s ease-out'
|
65
68
|
}
|
66
69
|
}
|
67
70
|
},
|
68
|
-
plugins: [
|
69
|
-
require('@tailwindcss/forms'),
|
70
|
-
require('@tailwindcss/typography'),
|
71
|
-
require('@tailwindcss/container-queries'),
|
72
|
-
require('tailwindcss-animate')
|
73
|
-
]
|
71
|
+
plugins: [require("tailwindcss-animate")],
|
74
72
|
}
|
73
|
+
|
74
|
+
|
@@ -16,7 +16,11 @@
|
|
16
16
|
"noUnusedLocals": true,
|
17
17
|
"noUnusedParameters": true,
|
18
18
|
"noFallthroughCasesInSwitch": true,
|
19
|
-
"noUncheckedSideEffectImports": true
|
19
|
+
"noUncheckedSideEffectImports": true,
|
20
|
+
"baseUrl": ".",
|
21
|
+
"paths": {
|
22
|
+
"@/*": ["app/javascript/*"]
|
23
|
+
}
|
20
24
|
},
|
21
25
|
"include": ["vite.config.ts"]
|
22
26
|
}
|
@@ -2,12 +2,20 @@ import path from 'path'
|
|
2
2
|
import { defineConfig } from 'vite'
|
3
3
|
import RubyPlugin from 'vite-plugin-ruby'
|
4
4
|
import react from "@vitejs/plugin-react"
|
5
|
+
import tailwindcss from '@tailwindcss/vite'
|
6
|
+
|
5
7
|
|
6
8
|
export default defineConfig({
|
7
9
|
plugins: [
|
8
10
|
react(),
|
9
11
|
RubyPlugin(),
|
12
|
+
tailwindcss()
|
10
13
|
],
|
14
|
+
server: {
|
15
|
+
watch: {
|
16
|
+
usePolling: true
|
17
|
+
}
|
18
|
+
},
|
11
19
|
resolve: {
|
12
20
|
alias: {
|
13
21
|
"@": path.resolve(__dirname, "./app/javascript"),
|
data/lib/install/vite_react.rb
CHANGED
@@ -1,8 +1,26 @@
|
|
1
1
|
say "=== Vite-react setup starting... ===", :green
|
2
2
|
|
3
|
+
unless File.exist? "starting"
|
4
|
+
create_file "starting"
|
5
|
+
else
|
6
|
+
remove_file "starting"
|
7
|
+
exit
|
8
|
+
end
|
9
|
+
|
3
10
|
gem "vite_rails", "~> 3.0"
|
4
|
-
gem "turbo-mount", "~> 0.4.1"
|
11
|
+
# gem "turbo-mount", "~> 0.4.1"
|
12
|
+
gem "tailwindcss-ruby", "~> 4.0.0.beta.9"
|
5
13
|
gem "tailwindcss-rails", "~> 3.0"
|
14
|
+
gem "opentelemetry-sdk"
|
15
|
+
gem "opentelemetry-instrumentation-rails"
|
16
|
+
gem "opentelemetry-exporter-otlp"
|
17
|
+
gem "yabeda"
|
18
|
+
gem "yabeda-gc"
|
19
|
+
gem "yabeda-rails"
|
20
|
+
gem "yabeda-activerecord"
|
21
|
+
gem "yabeda-activejob"
|
22
|
+
gem "yabeda-prometheus"
|
23
|
+
|
6
24
|
|
7
25
|
|
8
26
|
rails_command "tailwindcss:install"
|
@@ -19,32 +37,35 @@ say "=== Installing Vite, React, Tailwind, shadcn, etc. ===", :green
|
|
19
37
|
# --- Vite ---
|
20
38
|
run "bundle exec vite install"
|
21
39
|
|
40
|
+
|
22
41
|
# --- Install NPM dependencies ---
|
23
42
|
run <<~CMD
|
24
43
|
npm install \
|
25
44
|
react react-dom \
|
26
|
-
|
27
|
-
|
45
|
+
express typescript @types/express @types/node ts-node nodemon \
|
46
|
+
stimulus-vite-helpers clsx tailwind-merge \
|
47
|
+
@hotwired/turbo-rails \
|
28
48
|
@rails/actioncable @rails/activestorage \
|
29
|
-
class-variance-authority clsx tailwind-merge lucide-react
|
49
|
+
class-variance-authority clsx tailwind-merge lucide-react html-react-parser
|
30
50
|
CMD
|
31
51
|
|
32
52
|
run <<~CMD
|
33
53
|
npm install -D \
|
34
|
-
@vitejs/plugin-react eslint globals eslint-plugin-react-refresh
|
54
|
+
@vitejs/plugin-react eslint globals eslint-plugin-react-refresh @eslint/js \
|
35
55
|
@types/react @types/react-dom vite-plugin-stimulus-hmr vite-plugin-full-reload \
|
36
|
-
tailwind autoprefixer tailwindcss-animate \
|
56
|
+
tailwind @tailwindcss/postcss @tailwindcss/vite autoprefixer tailwindcss-animate @types/node \
|
37
57
|
@tailwindcss/typography @tailwindcss/container-queries @tailwindcss/forms
|
38
58
|
CMD
|
39
59
|
|
40
60
|
# Initialize Tailwind configs
|
41
|
-
run "npx tailwindcss init -p"
|
61
|
+
# run "npx tailwindcss init -p"
|
62
|
+
copy_file "#{__dir__}/postcss.config.mjs", "postcss.config.mjs"
|
42
63
|
|
43
64
|
# --------------------------------------------------------------------------
|
44
65
|
# 2.3.2: Overwrite vite.config.js with your React + Ruby config
|
45
66
|
# --------------------------------------------------------------------------
|
46
|
-
remove_file "vite.config.
|
47
|
-
copy_file "#{__dir__}/vite.config.
|
67
|
+
remove_file "vite.config.ts"
|
68
|
+
copy_file "#{__dir__}/vite.config.ts", "vite.config.ts"
|
48
69
|
|
49
70
|
# --------------------------------------------------------------------------
|
50
71
|
# 2.3.3: Add TypeScript config files
|
@@ -67,41 +88,18 @@ create_file "app/javascript/controllers/index.js", <<~JS
|
|
67
88
|
registerControllers(application, controllers);
|
68
89
|
JS
|
69
90
|
|
70
|
-
|
71
91
|
copy_file "#{__dir__}/application.css", "app/javascript/entrypoints/application.css"
|
72
|
-
|
92
|
+
remove_file "app/assets/stylesheets/application.tailwind.css"
|
93
|
+
copy_file "#{__dir__}/application.css", "app/assets/stylesheets/application.tailwind.css"
|
73
94
|
# 2.3.5: Create the main JS entrypoint for Vite
|
74
95
|
remove_file "app/javascript/entrypoints/application.js"
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
import "./application.css";
|
80
|
-
|
81
|
-
console.log("Hello from application.js");
|
82
|
-
JS
|
83
|
-
|
84
|
-
# --------------------------------------------------------------------------
|
85
|
-
# 2.4: turbo-mount installation
|
86
|
-
# --------------------------------------------------------------------------
|
87
|
-
say "=== Installing turbo-mount ===", :green
|
88
|
-
generate "turbo_mount:install --framework=react"
|
89
|
-
|
90
|
-
# We’ll create a dedicated turbo-mount entry for React components
|
91
|
-
remove_file "app/javascript/turbo-mount.js"
|
92
|
-
create_file "app/javascript/entrypoints/turbo-mount.js", <<~JS
|
93
|
-
import { TurboMount } from "turbo-mount";
|
94
|
-
import { registerComponent } from "turbo-mount/react";
|
95
|
-
|
96
|
-
// Example React component
|
97
|
-
import { App } from "@/components/App";
|
98
|
-
|
99
|
-
const turboMount = new TurboMount();
|
100
|
-
registerComponent(turboMount, "App", App);
|
101
|
-
JS
|
96
|
+
copy_file "#{__dir__}/application.jsx", "app/javascript/entrypoints/application.jsx"
|
97
|
+
empty_directory "app/javascript/ssr"
|
98
|
+
copy_file "#{__dir__}/ssr.ts", "app/javascript/ssr/ssr.ts"
|
99
|
+
copy_file "#{__dir__}/AppSSR.tsx", "app/javascript/ssr-components/App.tsx"
|
102
100
|
|
103
101
|
# --------------------------------------------------------------------------
|
104
|
-
# 2.
|
102
|
+
# 2.4: Example React component + Home controller
|
105
103
|
# --------------------------------------------------------------------------
|
106
104
|
|
107
105
|
copy_file "#{__dir__}/App.tsx", "app/javascript/components/App.tsx"
|
@@ -119,32 +117,33 @@ route "root to: 'route#index'"
|
|
119
117
|
remove_file "app/views/route/index.html.erb", force: true
|
120
118
|
copy_file "#{__dir__}/index.html.erb", "app/views/route/index.html.erb"
|
121
119
|
|
122
|
-
# --------------------------------------------------------------------------
|
123
|
-
# 2.6: Insert needed tags in application.html.erb
|
124
|
-
# --------------------------------------------------------------------------
|
125
|
-
insert_into_file "app/views/layouts/application.html.erb",
|
126
|
-
after: "<%= csrf_meta_tags %>\n" do
|
127
|
-
<<~ERB
|
128
|
-
<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
129
|
-
<%= javascript_importmap_tags %>
|
130
|
-
<%= vite_client_tag %>
|
131
|
-
<%= vite_javascript_tag 'application' %>
|
132
|
-
ERB
|
133
|
-
end
|
134
|
-
|
135
120
|
# --------------------------------------------------------------------------
|
136
121
|
# 2.7: shadcn initialization
|
137
122
|
# --------------------------------------------------------------------------
|
138
|
-
#run "npx shadcn@latest init"
|
123
|
+
# run "npx shadcn@latest init"
|
139
124
|
copy_file "#{__dir__}/components.json", "components.json"
|
140
125
|
copy_file "#{__dir__}/utils.ts", "app/javascript/lib/utils.ts"
|
141
|
-
remove_file "tailwind.config.
|
126
|
+
remove_file "tailwind.config.js"
|
127
|
+
copy_file "#{__dir__}/postcss.config.mjs", "postcss.config.mjs"
|
142
128
|
copy_file "#{__dir__}/tailwind.config.js", "tailwind.config.js"
|
129
|
+
remove_file "Procfile.dev"
|
130
|
+
copy_file "#{__dir__}/Procfile.dev", "Procfile.dev"
|
131
|
+
|
143
132
|
|
144
133
|
# --------------------------------------------------------------------------
|
145
|
-
# 2.8 setup
|
146
|
-
|
134
|
+
# 2.8 setup telemetry
|
135
|
+
# --------------------------------------------------------------------------
|
136
|
+
template "#{__dir__}/opentelemetry.rb.tt", "config/initializers/opentelemetry.rb"
|
137
|
+
insert_into_file "config/routes.rb",
|
138
|
+
before: " get \"up\" => \"rails/health#show\", as: :rails_health_check\n" do
|
139
|
+
" mount Yabeda::Prometheus::Exporter, at: \"/metrics\"\n"
|
140
|
+
end
|
147
141
|
|
142
|
+
gsub_file "app/views/layouts/application.html.erb",
|
143
|
+
/<%= vite_javascript_tag 'application' %>/,
|
144
|
+
"<%= vite_javascript_tag 'application.jsx' %>"
|
145
|
+
rails_command "assets:precompile"
|
146
|
+
run "bundle exec vite build --ssr"
|
148
147
|
# --------------------------------------------------------------------------
|
149
148
|
# 2.9: Done!
|
150
149
|
# --------------------------------------------------------------------------
|
data/lib/tasks/install.rake
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ViteReact
|
4
|
+
class Configuration
|
5
|
+
# Port for the Node/Vite SSR server.
|
6
|
+
attr_accessor :node_server_port
|
7
|
+
# Path to the Node executable (optional override)
|
8
|
+
attr_accessor :node_path
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@node_server_port = 4000
|
12
|
+
@node_path = nil # uses system's node by default
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rails"
|
2
|
+
|
3
|
+
module ViteReact
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
config.app_generators do |generate|
|
6
|
+
generate.assets true # create assets when generating a scaffold
|
7
|
+
generate.force_plural false # allow pluralized model names
|
8
|
+
generate.helper true # generate helpers
|
9
|
+
generate.integration_tool :test_unit # which tool generates integration tests (might be overwritten automatically if using rspec-rails)
|
10
|
+
generate.system_tests :test_unit # which tool generates system tests (might be overwritten automatically if using rspec-rails)
|
11
|
+
generate.resource_controller :controller # which generator generates a controller when using bin/rails generate resource
|
12
|
+
generate.resource_route true # generate a resource route definition
|
13
|
+
generate.scaffold_controller :vite_react
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|