Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
Assets¶
The Chill assets (js, css, images, …) are managed by Vite in this repository.
Installation¶
Vite needs to run in a Node.js environment. This Node.js environment can be set up using a node docker image. The bash script docker-node.sh sets up a Node.js environment with an adequate configuration. Launch this container by typing:
$ bash docker-node.sh
In this NodeJS environment, install all the assets required by Chill with:
node@b91cab4f7cfc:/app$ npm install
This command will install all the packages that are listed in package.json.
Any further required dependencies can be installed using npm. For example:
node@b91cab4f7cfc:/app$ npm install
Usage¶
Organize your assets¶
Chill assets usually live under the /Resources/public folder of each Chill bundle. Entry points are listed explicitly in ../../../vite/vite.entries.ts at the project root.
To add a new asset entry point:
- Create your entrypoint file (e.g.
src/Bundle/ChillFooBundle/Resources/public/vuejs/MyApp/index.ts) - Add it to
vite/vite.entries.ts:
To gather css files, import them from your js/ts entry file:
// assets/js/main.js
import '../css/app.css';
For finer configuration, refer to the Vite documentation.
Building the assets of an application¶
This repository is only used for development. To deploy Chill, you create a Symfony
application and install chill-project/chill-bundles with composer. The assets of
such an application come from two separate builds, run as two separate processes:
| Build | Sources | Output | Public path |
|---|---|---|---|
| Chill | vendor/chill-project/chill-bundles |
public/build/ |
/build/ |
| Application | the application's own entries, if any | public/build-app/ |
/build-app/ |
Both builds run with Node.js only. Their JavaScript dependencies are installed with npm
into node_modules: the build must never import a JavaScript file from a composer
package other than chill-project/chill-bundles itself.
Chill's build¶
The Vite configuration lives in vite/preset.ts and is exported as
chillVitePreset(); the vite.config.ts at the root of chill-bundles is a three-line
consumer of it. The preset reads its paths from environment variables, resolved against
the directory the build is launched from:
| Variable | Default | Meaning |
|---|---|---|
CHILL_VITE_OUT_DIR |
public/build inside chill-bundles |
where the build lands |
CHILL_VITE_BASE |
/build/ |
public URL of the built files |
CHILL_TRANSLATIONS_DIR |
var/translations inside chill-bundles |
translations dumped by Symfony UX Translator |
The translations are dumped by the application when its cache is warmed up, so warm the cache before building:
# at the root of the application
symfony console cache:warmup
cd vendor/chill-project/chill-bundles
npm ci
CHILL_VITE_OUT_DIR=../../../public/build \
CHILL_TRANSLATIONS_DIR=../../../var/translations \
npm run build
The application's build¶
Most applications have no entry of their own and skip this step. Otherwise, the
application has its own vite.config.ts, which builds only its entries into
public/build-app/. The vite-plugin-symfony plugin writes the entrypoints.json
file that Symfony reads to render the tags:
// vite.config.ts, in your application
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import symfony from "vite-plugin-symfony";
export default defineConfig({
base: "/build-app/",
plugins: [vue(), symfony()],
build: {
outDir: "public/build-app",
manifest: true,
emptyOutDir: true,
rolldownOptions: {
input: {
my_entry_name: "assets/my_entry/index.ts",
},
},
},
});
Symfony configuration¶
The tags are rendered by pentatrion/vite-bundle,
installed as a dependency of chill-bundles. Register it in config/bundles.php:
and declare one configuration per build in config/packages/pentatrion_vite.yaml:
pentatrion_vite:
default_config: chill
configs:
chill:
build_directory: build
app:
build_directory: build-app
when@prod:
pentatrion_vite:
cache: true
With cache: true, the entrypoints.json files are read once, when the cache is warmed
up, instead of on every request.
Chill's layout loads the entry app of the application's build, if the application
defines one. Any other entry of the application's build is loaded by passing the name of
its configuration as third argument:
Loading an entry of each build in the same page loads their shared dependencies twice (two copies of Vue, for instance).
Compile the assets¶
To compile assets for production:
node@b91cab4f7cfc:/app$ npm run build
While developing, you can continuously watch files and recompile on every change (requires a manual browser refresh):
node@b91cab4f7cfc:/app$ npm run watch
Use the assets in the templates¶
Any entry of ../../../vite/vite.entries.ts can be linked from Twig using the helpers of
pentatrion/vite-bundle:
<head>
...
{{ vite_entry_link_tags('my_entry_name') }}
</head>
<body>
...
{{ vite_entry_script_tags('my_entry_name') }}
</body>
vite_entry_link_tags also renders the modulepreload links of the chunks the entry
imports.
Hot Module Replacement (HMR) in development¶
HMR allows the browser to update Vue components, SCSS, and TypeScript files instantly without a full page reload, preserving application state.
The dev server is only used when developing chill-bundles itself, with a single build. Applications only run the production builds described above.
How it works¶
Chill uses a Symfony backend to render HTML pages. Vite normally assumes it controls the full page, so a small adaptation is required:
- When the dev server starts,
vite-plugin-symfonywritespublic/build/.vite/entrypoints.jsonwith the address of the dev server instead of the built files. - pentatrion/vite-bundle reads it and renders
<script>tags pointing tohttp://localhost:5173/build/src/Bundle/..., so Vite serves the source files directly. - The
@vite/clientscript is added to the page to open a WebSocket back to the Vite server for hot updates. vite-plugin-symfonysetsserver.origin, so that fonts and assets referenced in CSS also resolve via Vite (not Symfony).
Setup¶
-
Start both servers in two separate terminals:
-
Open
http://localhost:8000(HTTP only — HTTPS would block cross-origin scripts). -
Edit any
.vue,.ts, or.scssfile. The browser updates instantly.
Note: Stopping the dev server does not restore the built files: run
npm run buildagain, so thatentrypoints.jsonpoints to them.
Linux: inotify limit¶
On Linux, npm run dev-server may fail with:
Error: ENOSPC: System limit for number of file watchers reached
Fix (persistent):
sudo tee /etc/sysctl.d/99-inotify.conf >/dev/null <<'EOF'
fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=1024
fs.inotify.max_queued_events=32768
EOF
sudo sysctl --system
Fallback without sudo: