Add SPA build caching with folder hash detection#72
Merged
Conversation
Implements intelligent build caching for Angular/React SPA projects to skip unnecessary npm builds when the SPA folder contents haven't changed. Features: - Computes SHA-256 hash of SPA folder using MintPlayer.FolderHasher.Targets - Stores hash in obj/spa-folder.hash for comparison - Skips npm build when hash unchanged and dist/ exists - Supports .hasherignore files for excluding files from hash calculation - New MSBuild properties: EnableSpaBuildCaching, SpaHashFilePath, ForceSpaBuild - Works transitively for all projects referencing the package Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move the npm build conditional logic inside PublishRunWebpack target instead of splitting into two separate targets. This ensures the ResolvedFileToPublish block always runs when EnableSpaBuilder is true. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The double-dash (--) characters inside XML comments confuse parsers since -- is part of the comment delimiter syntax. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify _RunNpmBuild logic: default to true (fail-safe), only set false when explicitly skipping - Add warning when SpaRoot folder doesn't exist - Prevent npm commands from running if SpaRoot doesn't exist - Don't write empty hash to file if hash computation failed Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-create .hasherignore file with sensible defaults if missing - Default patterns exclude: node_modules/, .angular/, dist/, dist-server/, .cache/, coverage/ - Add CreateDefaultHasherIgnore property to control auto-creation - Add SpaHashDefaultIgnorePattern item group for customizing defaults - Add example .hasherignore file in Demo project - Update README documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add additional patterns to SpaHashDefaultIgnorePattern: - Build outputs: build/, out/ - Framework caches: .npm/ - Test outputs: test-results/, .nyc_output/ - IDE files: .idea/, .vscode/ - Editor temp files: *.swp, *.swo, *~ - OS files: .DS_Store, Thumbs.db Update Demo project .hasherignore and README documentation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Empty Include="" is not allowed in MSBuild ItemGroup elements. Removed the blank line item from _HasherIgnoreLines. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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.
Summary
MintPlayer.FolderHasher.Targetsnpm run build/npm run build:ssrwhen hash unchangedFeatures
.hasherignoresupport: Exclude files/folders from hash calculation (similar to.gitignoresyntax).hasherignorewith sensible defaults if missingEnableSpaBuildCaching,SpaHashFilePath,ForceSpaBuild,CreateDefaultHasherIgnoreNew MSBuild Properties
EnableSpaBuildCachingtrueSpaHashFilePath$(IntermediateOutputPath)spa-folder.hashForceSpaBuildfalseCreateDefaultHasherIgnoretrue.hasherignorewith default patterns if missingBuild Command Selection
true(default)npm run build:ssr:productionfalsenpm run build -- --configuration productionDefault Ignore Patterns
The auto-created
.hasherignoreexcludes:node_modules/dist/,dist-server/,build/,out/.angular/,.cache/,.npm/coverage/,test-results/,.nyc_output/.idea/,.vscode/*.swp,*.swo,*~.DS_Store,Thumbs.dbTesting Instructions
1. First publish (should run full build and create hash file):
cd Demo/Prerendering/Demo.Web dotnet publish -c ReleaseLook for messages like:
First SPA build detected (hash: xxx). Will build.npm installandnpm run build:ssr:productionshould execute2. Second publish (should skip build):
Look for:
SPA source unchanged (hash: xxx). Skipping npm build.Using cached SPA build output from ClientApp\dist3. Modify a source file and publish (should rebuild):
# Make a small change to any .ts file in ClientApp/src dotnet publish -c ReleaseLook for:
SPA source changed. Will rebuild. (Previous: xxx, Current: yyy)4. Force rebuild:
5. Check hash file location:
Test plan
ForceSpaBuild=trueforces rebuild even when hash unchanged.hasherignoreis auto-created with default patterns🤖 Generated with Claude Code