fix: use vite-plugin-symfony Stimulus loader and wrap react_component in div
The @symfony/stimulus-bundle loader generates an empty controllers.js, so Stimulus controllers from controllers.json (including ux-react) were never registered. Switching to vite-plugin-symfony/stimulus/helpers uses the virtual:symfony/controllers module that properly reads controllers.json. Also wrap react_component() output in a <div> since it only renders data-attributes, not a full HTML element. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
4
assets/bootstrap.js
vendored
4
assets/bootstrap.js
vendored
@@ -1,4 +1,4 @@
|
|||||||
import { startStimulusApp } from '@symfony/stimulus-bundle';
|
import { startStimulusApp } from 'vite-plugin-symfony/stimulus/helpers';
|
||||||
|
|
||||||
const app = startStimulusApp();
|
const app = startStimulusApp();
|
||||||
|
|
||||||
@@ -15,5 +15,5 @@ window.resolveReactComponent = (name) => {
|
|||||||
.map(k => k.replace('./react/controllers/', '').replace('.jsx', ''));
|
.map(k => k.replace('./react/controllers/', '').replace('.jsx', ''));
|
||||||
throw new Error(`React controller "${name}" does not exist. Possible values: ${available.join(', ')}`);
|
throw new Error(`React controller "${name}" does not exist. Possible values: ${available.join(', ')}`);
|
||||||
}
|
}
|
||||||
return module.default;
|
return module;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
{
|
{
|
||||||
"controllers": {
|
"controllers": {
|
||||||
|
"@symfony/ux-react": {
|
||||||
|
"react": {
|
||||||
|
"enabled": true,
|
||||||
|
"fetch": "eager"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@symfony/ux-turbo": {
|
"@symfony/ux-turbo": {
|
||||||
"turbo-core": {
|
"turbo-core": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
@@ -9,12 +15,6 @@
|
|||||||
"enabled": false,
|
"enabled": false,
|
||||||
"fetch": "eager"
|
"fetch": "eager"
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"@symfony/ux-react": {
|
|
||||||
"react": {
|
|
||||||
"enabled": true,
|
|
||||||
"fetch": "eager"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entrypoints": []
|
"entrypoints": []
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
when@dev:
|
||||||
|
pentatrion_vite:
|
||||||
|
proxy_origin: http://node:5173
|
||||||
|
|
||||||
pentatrion_vite:
|
pentatrion_vite:
|
||||||
default_build: app
|
default_build: app
|
||||||
builds:
|
builds:
|
||||||
|
|||||||
@@ -30,6 +30,14 @@ ENV APP_ENV=dev \
|
|||||||
POSTGRES_USER=app \
|
POSTGRES_USER=app \
|
||||||
POSTGRES_PASSWORD=pwd
|
POSTGRES_PASSWORD=pwd
|
||||||
|
|
||||||
|
###
|
||||||
|
# Composer install stage (provides vendor assets for node build)
|
||||||
|
###
|
||||||
|
FROM base AS composer-deps
|
||||||
|
|
||||||
|
COPY composer.json composer.lock symfony.lock ./
|
||||||
|
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
|
||||||
|
|
||||||
###
|
###
|
||||||
# Node build stage (for prod assets)
|
# Node build stage (for prod assets)
|
||||||
###
|
###
|
||||||
@@ -37,6 +45,9 @@ FROM node:22-alpine AS node-build
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy vendor UX assets so npm can resolve file: dependencies
|
||||||
|
COPY --from=composer-deps /app/vendor/symfony/ux-react/assets vendor/symfony/ux-react/assets
|
||||||
|
|
||||||
COPY package.json package-lock.json* ./
|
COPY package.json package-lock.json* ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
|
|
||||||
|
|||||||
56
package-lock.json
generated
56
package-lock.json
generated
@@ -15,6 +15,8 @@
|
|||||||
"react-dom": "^19.0"
|
"react-dom": "^19.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@symfony/stimulus-bridge": "^3.2.0 || ^4.0.0",
|
||||||
|
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
|
||||||
"@vitejs/plugin-react-swc": "^4.3.0",
|
"@vitejs/plugin-react-swc": "^4.3.0",
|
||||||
"vite": "^6.0",
|
"vite": "^6.0",
|
||||||
"vite-plugin-symfony": "^8.0"
|
"vite-plugin-symfony": "^8.0"
|
||||||
@@ -961,7 +963,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz",
|
||||||
"integrity": "sha512-wa/zupVG0eWxRYJjC1IiPBdt3Lruv0RqGN+/DTMmUWUyMAEB27KXmVY6a8YpUVTM7QwVuaLNGW4EqDgrS2upXQ==",
|
"integrity": "sha512-wa/zupVG0eWxRYJjC1IiPBdt3Lruv0RqGN+/DTMmUWUyMAEB27KXmVY6a8YpUVTM7QwVuaLNGW4EqDgrS2upXQ==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@hotwired/stimulus": ">= 3.0"
|
"@hotwired/stimulus": ">= 3.0"
|
||||||
}
|
}
|
||||||
@@ -1701,7 +1702,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@symfony/stimulus-bridge/-/stimulus-bridge-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@symfony/stimulus-bridge/-/stimulus-bridge-4.0.1.tgz",
|
||||||
"integrity": "sha512-+/kSQ4qFXMbZS+HjkhzOxwdN+60pMev7kzzDpQV/Tdm/iIWoxx5GDsVcdLaBb2783BVQHyrBP72JerF2SXTbTg==",
|
"integrity": "sha512-+/kSQ4qFXMbZS+HjkhzOxwdN+60pMev7kzzDpQV/Tdm/iIWoxx5GDsVcdLaBb2783BVQHyrBP72JerF2SXTbTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hotwired/stimulus-webpack-helpers": "^1.0.1",
|
"@hotwired/stimulus-webpack-helpers": "^1.0.1",
|
||||||
"@types/webpack-env": "^1.16.4",
|
"@types/webpack-env": "^1.16.4",
|
||||||
@@ -1723,6 +1723,10 @@
|
|||||||
"resolved": "vendor/symfony/ux-react/assets",
|
"resolved": "vendor/symfony/ux-react/assets",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@symfony/ux-turbo": {
|
||||||
|
"resolved": "vendor/symfony/ux-turbo/assets",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@testing-library/dom": {
|
"node_modules/@testing-library/dom": {
|
||||||
"version": "10.4.1",
|
"version": "10.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
|
||||||
@@ -1861,12 +1865,18 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/hotwired__turbo": {
|
||||||
|
"version": "8.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/hotwired__turbo/-/hotwired__turbo-8.0.9.tgz",
|
||||||
|
"integrity": "sha512-q2XWdObf8J+3V8fESKkd452Iy1A9ZFemQVGzKmxmZ02Clo1D/HEiX8bMQRmJ432RQ4sp24R0f7XQjHWNQC26XA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/json-schema": {
|
"node_modules/@types/json-schema": {
|
||||||
"version": "7.0.15",
|
"version": "7.0.15",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||||
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "19.2.14",
|
"version": "19.2.14",
|
||||||
@@ -2069,7 +2079,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"fast-uri": "^3.0.1",
|
"fast-uri": "^3.0.1",
|
||||||
@@ -2086,7 +2095,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
||||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.0.0"
|
"ajv": "^8.0.0"
|
||||||
},
|
},
|
||||||
@@ -2104,7 +2112,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
||||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fast-deep-equal": "^3.1.3"
|
"fast-deep-equal": "^3.1.3"
|
||||||
},
|
},
|
||||||
@@ -2477,8 +2484,7 @@
|
|||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob": {
|
"node_modules/fast-glob": {
|
||||||
"version": "3.3.3",
|
"version": "3.3.3",
|
||||||
@@ -2511,8 +2517,7 @@
|
|||||||
"url": "https://opencollective.com/fastify"
|
"url": "https://opencollective.com/fastify"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.20.1",
|
"version": "1.20.1",
|
||||||
@@ -2774,8 +2779,7 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/json5": {
|
"node_modules/json5": {
|
||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
@@ -2795,7 +2799,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz",
|
||||||
"integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==",
|
"integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 12.13.0"
|
"node": ">= 12.13.0"
|
||||||
}
|
}
|
||||||
@@ -3127,7 +3130,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -3260,7 +3262,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
|
||||||
"integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
|
"integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.9",
|
"@types/json-schema": "^7.0.9",
|
||||||
"ajv": "^8.9.0",
|
"ajv": "^8.9.0",
|
||||||
@@ -4683,6 +4684,29 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"vendor/symfony/ux-turbo/assets": {
|
||||||
|
"name": "@symfony/ux-turbo",
|
||||||
|
"version": "2.31.0",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@hotwired/stimulus": "^3.0.0",
|
||||||
|
"@hotwired/turbo": "^7.1.0 || ^8.0",
|
||||||
|
"@testing-library/dom": "^10.4.0",
|
||||||
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
|
"@testing-library/user-event": "^14.6.1",
|
||||||
|
"@types/hotwired__turbo": "^8.0.4",
|
||||||
|
"jsdom": "^26.1.0",
|
||||||
|
"tslib": "^2.8.1",
|
||||||
|
"tsx": "^4.20.3",
|
||||||
|
"typescript": "^5.8.3",
|
||||||
|
"vitest": "^3.2.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@hotwired/stimulus": "^3.0.0",
|
||||||
|
"@hotwired/turbo": "^7.1.0 || ^8.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
"react-dom": "^19.0"
|
"react-dom": "^19.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@symfony/stimulus-bridge": "^3.2.0 || ^4.0.0",
|
||||||
|
"@symfony/ux-turbo": "file:vendor/symfony/ux-turbo/assets",
|
||||||
"@vitejs/plugin-react-swc": "^4.3.0",
|
"@vitejs/plugin-react-swc": "^4.3.0",
|
||||||
"vite": "^6.0",
|
"vite": "^6.0",
|
||||||
"vite-plugin-symfony": "^8.0"
|
"vite-plugin-symfony": "^8.0"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{{ react_component('GameGrid', {
|
<div {{ react_component('GameGrid', {
|
||||||
grid: grid,
|
grid: grid,
|
||||||
width: width,
|
width: width,
|
||||||
middle: middle,
|
middle: middle,
|
||||||
}) }}
|
}) }}></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export default defineConfig({
|
|||||||
strictPort: true,
|
strictPort: true,
|
||||||
origin: 'http://localhost:5173',
|
origin: 'http://localhost:5173',
|
||||||
cors: true,
|
cors: true,
|
||||||
|
allowedHosts: ['node'],
|
||||||
hmr: {
|
hmr: {
|
||||||
host: 'localhost',
|
host: 'localhost',
|
||||||
port: 5173,
|
port: 5173,
|
||||||
|
|||||||
Reference in New Issue
Block a user