fix: rebundle when the bundle misses a template source - #25484
Open
totally-not-ai[bot] wants to merge 7 commits into
Open
fix: rebundle when the bundle misses a template source#25484totally-not-ai[bot] wants to merge 7 commits into
totally-not-ai[bot] wants to merge 7 commits into
Conversation
When a matching production bundle is reused, npm install is skipped and node_modules is never created, but TaskCopyTemplateFiles is still scheduled and resolves every @jsmodule of a Template class against node_modules, failing the build-frontend goal on a clean checkout. Development mode already sets copyTemplates only when the dev bundle is actually rebuilt; the added tests state the same expectation for production mode.
The reported failure happens while TaskCopyTemplateFiles resolves the @jsmodule values, so assert there instead of on the NodeTasks command list: on a build that reuses the bundle, a project template is still copied from the frontend folder, while a template that lives in an npm package comes from the bundle and must not be looked up in the missing node_modules.
TaskCopyTemplateFiles copies the JavaScript source of every Template class into config/templates, where the template parser reads it at runtime to map the @id fields of a template. That folder is part of the bundle, so when a matching bundle is reused the sources it holds are unpacked back into place. The copy ran again anyway and resolved every @jsmodule against node_modules, which npm install had not created, failing the build for any template that lives in an npm package. The bundle is now the source of truth for those templates: bundle validation requires the bundle in use, whichever one it is, to contain the template source of every Template class whose @jsmodule points into an npm package, and requires a build when it does not. Templates in the project or in an add-on jar are always available on disk and keep being copied on every build, so they need no check. TaskCopyTemplateFiles then keeps a template it cannot resolve when the bundle has already provided it, and names the template class in the error when the source is nowhere to be found.
A bundle build has npm install behind it, so a template source that cannot be found is an error even when an earlier build left a copy of it in the output folder, which would otherwise hide a template that an npm package upgrade has moved. Whether a template source needs the bundle is now decided by looking it up rather than by the './' prefix of the @jsmodule value, as a template packaged in an add-on jar is available on every build even when it is referenced by a bare path.
The fix rests on the template sources being part of the bundle: cover copying one from node_modules, compressing the folder it is copied into into the bundle, and reusing that bundle on a checkout that has neither node_modules nor the build output.
Contributor
ZipException is an IOException, so the check for a file in a zip lets it through as it is instead of wrapping it.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Problem
TaskCopyTemplateFilescopies the JavaScript source of everyTemplateclass intoconfig/templates, where the template parser reads it at runtime to map the@Idfields of a template. That folder is part of the bundle, so when a matching bundle is reused the sources it holds are unpacked back into place.The copy task ran again anyway and resolved every
@JsModulevalue againstnode_modules— whichnpm installhad not created, because reusing the bundle is exactly what skips it. On a clean checkout with nonode_modulesand no build output, thebuild-frontendgoal failed for any template whose source lives in an npm package, with a bareUnable to locate file ....Fix
The bundle becomes the source of truth for those templates:
BundleValidationUtil) now requires the bundle in use — application-specific, default, or dev — to contain the template source of everyTemplateclass whose@JsModulepoints into an npm package, and requires a rebuild when it does not. Whether a template needs the bundle is decided by looking the source up (frontend folder, then jar resources) rather than by the./prefix of the@JsModulevalue, since a template packaged in an add-on jar is available on every build even when referenced by a bare path. Templates in the project or in an add-on jar are always on disk and keep being copied on every build, so they need no check. A rebuild triggered this way is reported asflow/rebundle-reason-missing-template.TaskCopyTemplateFileskeeps a template it cannot resolve when the bundle has already provided it, and only tolerates that on a non-bundle build — a bundle build hasnpm installbehind it, so an unresolvable source is a genuine error even if an earlier build left a copy in the output folder (which would otherwise hide a template that an npm package upgrade has moved). The error message now names the template class and the places that were searched.@JsModulescan and the template target folder are extracted intogetTemplateJsModules(...)/getTemplateDirectory(...)so bundle validation and the copy task agree on what is expected where.Supporting additions
CompressUtil.hasFileInZip(File, String)— check for an entry without extracting it.ProdBundleUtils.hasBundleFile(File, ClassFinder, String)— the same check against whichever production bundle is in use (application bundle if present, otherwise the default bundle on the class path).Tests
TaskCopyTemplateFilesTest: on a build that reuses the bundle, a project template is still copied from the frontend folder, while a template living in an npm package comes from the bundle and is not looked up in the missingnode_modules; on a bundle build a missing source is still an error.BundleValidationTest: a reused production bundle that is missing a template source forces a rebuild; one that contains it does not. Development mode already setcopyTemplatesonly when the dev bundle is actually rebuilt — the added tests state the same expectation for production mode.node_modulesinto the templates folder, compressed into the bundle, and reused on a checkout that has neithernode_modulesnor the build output.CompressUtilTest: reading a bundle that is not a zip surfaces theZipExceptionas-is rather than wrapped.API Changes
com.vaadin.flow.internal.CompressUtil
com.vaadin.flow.server.frontend.ProdBundleUtils