notiziephp.it

Rilasciata Symfony Reprise 1.3.0 (Symfony Blog)

Traduzione da Symfony Blog
28 Settembre 2026 Tempo di lettura: 6 minuti
Rilasciata Symfony Reprise 1.3.0 (Symfony Blog)

È uscita Reprise 1.3.0, con modulepreload sotto una CSP strict, un dev loop di Stimulus senza riavvii e scritture più sicure dei file di metadati. Questo è anche il primo post di release da Reprise 1.0, quindi copre tre modifiche precedenti che avevano ricevuto solo una riga di changelog: metadataPath dalla 1.2.0, le style entry dalla 1.1.3 e l'input di primo livello di Vite in dev dalla 1.1.0.

Con una Content-Security-Policy basata su nonce (script-src 'nonce-...', il tipo che NelmioSecurityBundle configura), i tag <link rel="modulepreload"> renderizzati da Reprise, e i corrispondenti header HTTP Link: di preload, non portavano mai un nonce. Il browser li blocca e, una volta che un modulepreload viene bloccato, il modulo a cui punta non riesce a caricarsi, quindi il JavaScript dell'app non viene mai eseguito.

Un nonce passato a reprise_entry_script_tags() tramite attributes, oppure impostato nella script_attributes globale, ora raggiunge i link modulepreload dell'entry e il loro header Link:, mentre gli altri attributi restano sul tag script:

Ora RenderAssetTagEvent viene dispatchato anche per i link modulepreload, sotto un nuovo tipo modulepreload ($event->isModulepreload()). E l'header Link: ora copia nonce, integrity e crossorigin dal tag finale, dopo che i listener sono stati eseguiti, invece di ricalcolarli da entrypoints.json: un listener che li modificava lasciava l'header fuori sincrono con il tag, e il browser scarta un preload che non corrisponde.

Il modulo virtual:symfony/controllers veniva generato una sola volta, all'avvio del dev server. Aggiungere o rimuovere un controller locale, attivare o disattivare un commento stimulusFetch: 'lazy', oppure un controllers.json aggiornato da Symfony Flex dopo un composer require symfony/ux-* richiedeva in tutti i casi un riavvio del dev server per comparire. Webpack Encore recepiva queste modifiche da solo.

Ora sia Vite sia Rsbuild rigenerano il modulo e ricaricano la pagina quando uno di quei file cambia. Si tratta di un ricaricamento completo della pagina, non di una sostituzione a caldo del controller. I controller locali possono anche usare le estensioni .jsx e .tsx, come potevano fare con Encore:

Con @rsbuild/plugin-tailwindcss (Tailwind CSS v4 osserva le directory del progetto, inclusa quella che contiene outputPath), rsbuild dev e rsbuild build --watch ricompilavano all'infinito: dopo ogni compilazione, Reprise riscrive entrypoints.json, manifest.json e, in dev, i file copiati, il watcher vede il cambiamento della directory e Rspack compila di nuovo. Vite non era interessato, dato che il suo watcher ignora già build.outDir. Ora l'integrazione con Rsbuild aggiunge outputPath e i file di metadati ai watchOptions.ignored di Rspack, mantenendo le ignore predefinite di Rspack quando non ne imposti nessuna e unendole alle tue (RegExp, glob o funzione) quando lo fai.

Quelle riscritture entravano anche in race condition con PHP. writeFileSync() tronca un file prima di scriverlo, quindi una richiesta che arrivava nel frattempo poteva leggere un entrypoints.json vuoto e fallire con una JsonException. Su entrambi i bundler, i due file vengono ora scritti in un file temporaneo accanto a loro e rinominati sopra il file di destinazione, con un fallback a una scrittura diretta quando la rinomina fallisce (Windows può rifiutarla mentre un altro processo tiene il file aperto).

Rilasciato nella 1.2.0. Reprise scriveva entrypoints.json e manifest.json in outputPath, accanto agli asset compilati. Carica quella directory su un object storage pubblico o su una CDN e i due file la seguono, a meno che tu non li escluda manualmente.

La nuova opzione metadataPath (che per default è outputPath) li scrive altrove, mentre gli asset compilati e i file copiati restano in outputPath. AssetMapper riceve la stessa idea in Symfony 8.2 con la sua nuova opzione metadata_dir.

Se ti affidi a manifest.json per le chiamate asset(), punta framework.assets.json_manifest_path anche alla nuova posizione, come mostra la documentazione di metadataPath.

Rilasciato nella 1.1.3. Una style entry è un entry che punta direttamente a un foglio di stile, come faceva addStyleEntry() di Encore. Con Vite veniva compilata in un chunk JavaScript vuoto che Vite eliminava dopo che Reprise lo aveva registrato: lo <script> renderizzato restituiva un 404, manifest.json acquisiva una chiave build/theme.js morta e, con integrity abilitato, la build falliva del tutto. Con Rsbuild, l'entry annunciava un file JavaScript runtime-only, che significava uno <script> inutile e la stessa chiave morta.

Ora una style entry produce solo CSS su entrambi i bundler, senza alcun file JavaScript in entrypoints.json o manifest.json. Su Rsbuild, il file runtime-only viene anche eliminato dalla build, come faceva DeleteUnusedEntriesJSPlugin di Encore:

reprise_entry_link_tags('theme') renderizza il <link>, e reprise_entry_script_tags('theme') non ha nulla da renderizzare. Reprise considera un entry una style entry in base all'estensione del file, come elenca la documentazione delle style entries.

Rilasciato nella 1.1.0. Vite 8.2 ha aggiunto un'opzione input di primo livello, che Vite consiglia rispetto a build.rolldownOptions.input perché anche il dev la usa. Il collector di dev di Reprise leggeva solo build.rolldownOptions.input e build.rollupOptions.input, quindi un progetto basato sulla nuova opzione compilava correttamente, ma il suo entrypoints.json di dev non aveva entry.

Ora il collector di dev ricade sull'input di primo livello dopo quelli annidati, la stessa precedenza che applica vite build, così dev e build nominano le stesse entry:

Su Vite 8.1 e precedenti, le entry restano in build.rollupOptions.input. Rsbuild non è interessato: le sue entry vivono in source.entry.

  • #134 [TagRenderer] Consentire ai nonce CSP di raggiungere i link modulepreload e i loro header Link (@Kocal)
  • #135 [Rsbuild] Trattare build --watch come una build, non come dev (@Kocal)
  • #136 [Options] Garantire uno slash finale su publicPath e manifestKeyPrefix (@Kocal)
  • #137 [Vite] Precaricare i chunk che un entry raggiunge attraverso un altro chunk (@Kocal)
  • #138 [Stimulus] Rilevare le modifiche ai controller in dev senza riavvio (@Kocal)
  • #139 [Rsbuild] Fermare il loop di rebuild quando uno strumento osserva la directory di output (@Kocal)
  • #141 [Cache] Non mettere in cache un entrypoints.json mancante (@Kocal)
  • #144 [Tests] Retrodatare ogni percorso di fixture nel test del watch-loop (@Kocal)
  • #143 [Stimulus] Registrare i controller locali .jsx e .tsx (@Kocal)
  • #142 [Rsbuild] Rispettare devServerOrigin (@Kocal)
  • #140 [Emit] Scrivere entrypoints.json e manifest.json in modo atomico (@Kocal)
  • #145 [DevServer] Annunciare un origin raggiungibile per host wildcard e IPv6 (@Kocal)
  • #147 [Format] Rimuovere joinUrl (@Kocal)
  • #146 [Vite] Rimuovere il tipo ViteOutputChunk (@Kocal)
  • #151 [CI] Testare Symfony 8.1 invece di 8.0 (@Kocal)
  • #148 [Repo] Rimuovere residui e configurazione obsoleta (@Kocal)
  • #150 [Tests] Condividere gli helper dei test di integrazione e ripulire le directory temporanee (@Kocal)
  • #152 [Emit] Scrivere i file Symfony attraverso un'unica pipeline (@Kocal)
  • #149 [TagRenderer] Far seguire all'header di preload il tag finale (@Kocal)
  • #153 [Vite][Rsbuild] Spostare gli hook di ogni bundler nel proprio modulo (@Kocal)
  • #154 [Rsbuild] Chiedere a Rspack solo i campi stats necessari al manifest (@Kocal)

Reprise segue la promessa di retrocompatibilità di Symfony dalla 1.0, e tre delle modifiche sopra sono arrivate da contributor esterni al maintainer. Continuate a mandare feedback: issue e pull request sono benvenute su GitHub.

Condividi su: LinkedIn

Altri articoli recenti