├── .config
└── dotnet-tools.json
├── .editorconfig
├── .gitignore
├── Blazor.PrerenderCache.UnitTest
└── Blazor.PrerenderCache.UnitTest.csproj
├── Blazor.PrerenderCache.sln
├── Blazor.PrerenderCache
├── Blazor.PrerenderCache.csproj
├── PrerenderCache.cs
└── PrerenderCacheStore.razor
├── LICENSE
├── README.md
├── build.cake
├── build.ps1
├── img
└── DoubleLoad.gif
└── pie.png
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "cake.tool": {
6 | "version": "1.0.0-rc0002",
7 | "commands": [
8 | "dotnet-cake"
9 | ]
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | indent_style = tab
3 |
4 | dotnet_diagnostic.CA1034.severity = none # CA1034: Nested types should not be visible
5 | dotnet_diagnostic.CA1054.severity = none # CA1054: Uri parameters should not be strings
6 | dotnet_diagnostic.CA1303.severity = none # CA1303: Do not pass literals as localized parameters
7 | dotnet_diagnostic.CA1305.severity = none # CA1305: Specify IFormatProvider
8 | dotnet_diagnostic.CA1308.severity = none # CA1308: Normalize strings to uppercase
9 | dotnet_diagnostic.CA1819.severity = none # CA1819: Properties should not return arrays
10 | dotnet_diagnostic.CA2007.severity = none # CA2007: Consider calling ConfigureAwait on the awaited task
11 | dotnet_diagnostic.CA2229.severity = none # CA2229: Implement serialization constructors
12 | dotnet_diagnostic.CS1591.severity = none # CS1591: Missing XML comment for publicly visible type or member
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.vspscc
94 | *.vssscc
95 | .builds
96 | *.pidb
97 | *.svclog
98 | *.scc
99 |
100 | # Chutzpah Test files
101 | _Chutzpah*
102 |
103 | # Visual C++ cache files
104 | ipch/
105 | *.aps
106 | *.ncb
107 | *.opendb
108 | *.opensdf
109 | *.sdf
110 | *.cachefile
111 | *.VC.db
112 | *.VC.VC.opendb
113 |
114 | # Visual Studio profiler
115 | *.psess
116 | *.vsp
117 | *.vspx
118 | *.sap
119 |
120 | # Visual Studio Trace Files
121 | *.e2e
122 |
123 | # TFS 2012 Local Workspace
124 | $tf/
125 |
126 | # Guidance Automation Toolkit
127 | *.gpState
128 |
129 | # ReSharper is a .NET coding add-in
130 | _ReSharper*/
131 | *.[Rr]e[Ss]harper
132 | *.DotSettings.user
133 |
134 | # TeamCity is a build add-in
135 | _TeamCity*
136 |
137 | # DotCover is a Code Coverage Tool
138 | *.dotCover
139 |
140 | # AxoCover is a Code Coverage Tool
141 | .axoCover/*
142 | !.axoCover/settings.json
143 |
144 | # Coverlet is a free, cross platform Code Coverage Tool
145 | coverage*.json
146 | coverage*.xml
147 | coverage*.info
148 |
149 | # Visual Studio code coverage results
150 | *.coverage
151 | *.coveragexml
152 |
153 | # NCrunch
154 | _NCrunch_*
155 | .*crunch*.local.xml
156 | nCrunchTemp_*
157 |
158 | # MightyMoose
159 | *.mm.*
160 | AutoTest.Net/
161 |
162 | # Web workbench (sass)
163 | .sass-cache/
164 |
165 | # Installshield output folder
166 | [Ee]xpress/
167 |
168 | # DocProject is a documentation generator add-in
169 | DocProject/buildhelp/
170 | DocProject/Help/*.HxT
171 | DocProject/Help/*.HxC
172 | DocProject/Help/*.hhc
173 | DocProject/Help/*.hhk
174 | DocProject/Help/*.hhp
175 | DocProject/Help/Html2
176 | DocProject/Help/html
177 |
178 | # Click-Once directory
179 | publish/
180 |
181 | # Publish Web Output
182 | *.[Pp]ublish.xml
183 | *.azurePubxml
184 | # Note: Comment the next line if you want to checkin your web deploy settings,
185 | # but database connection strings (with potential passwords) will be unencrypted
186 | *.pubxml
187 | *.publishproj
188 |
189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
190 | # checkin your Azure Web App publish settings, but sensitive information contained
191 | # in these scripts will be unencrypted
192 | PublishScripts/
193 |
194 | # NuGet Packages
195 | *.nupkg
196 | # NuGet Symbol Packages
197 | *.snupkg
198 | # The packages folder can be ignored because of Package Restore
199 | **/[Pp]ackages/*
200 | # except build/, which is used as an MSBuild target.
201 | !**/[Pp]ackages/build/
202 | # Uncomment if necessary however generally it will be regenerated when needed
203 | #!**/[Pp]ackages/repositories.config
204 | # NuGet v3's project.json files produces more ignorable files
205 | *.nuget.props
206 | *.nuget.targets
207 |
208 | # Microsoft Azure Build Output
209 | csx/
210 | *.build.csdef
211 |
212 | # Microsoft Azure Emulator
213 | ecf/
214 | rcf/
215 |
216 | # Windows Store app package directories and files
217 | AppPackages/
218 | BundleArtifacts/
219 | Package.StoreAssociation.xml
220 | _pkginfo.txt
221 | *.appx
222 | *.appxbundle
223 | *.appxupload
224 |
225 | # Visual Studio cache files
226 | # files ending in .cache can be ignored
227 | *.[Cc]ache
228 | # but keep track of directories ending in .cache
229 | !?*.[Cc]ache/
230 |
231 | # Others
232 | ClientBin/
233 | ~$*
234 | *~
235 | *.dbmdl
236 | *.dbproj.schemaview
237 | *.jfm
238 | *.pfx
239 | *.publishsettings
240 | orleans.codegen.cs
241 |
242 | # Including strong name files can present a security risk
243 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
244 | #*.snk
245 |
246 | # Since there are multiple workflows, uncomment next line to ignore bower_components
247 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
248 | #bower_components/
249 |
250 | # RIA/Silverlight projects
251 | Generated_Code/
252 |
253 | # Backup & report files from converting an old project file
254 | # to a newer Visual Studio version. Backup files are not needed,
255 | # because we have git ;-)
256 | _UpgradeReport_Files/
257 | Backup*/
258 | UpgradeLog*.XML
259 | UpgradeLog*.htm
260 | ServiceFabricBackup/
261 | *.rptproj.bak
262 |
263 | # SQL Server files
264 | *.mdf
265 | *.ldf
266 | *.ndf
267 |
268 | # Business Intelligence projects
269 | *.rdl.data
270 | *.bim.layout
271 | *.bim_*.settings
272 | *.rptproj.rsuser
273 | *- [Bb]ackup.rdl
274 | *- [Bb]ackup ([0-9]).rdl
275 | *- [Bb]ackup ([0-9][0-9]).rdl
276 |
277 | # Microsoft Fakes
278 | FakesAssemblies/
279 |
280 | # GhostDoc plugin setting file
281 | *.GhostDoc.xml
282 |
283 | # Node.js Tools for Visual Studio
284 | .ntvs_analysis.dat
285 | node_modules/
286 |
287 | # Visual Studio 6 build log
288 | *.plg
289 |
290 | # Visual Studio 6 workspace options file
291 | *.opt
292 |
293 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
294 | *.vbw
295 |
296 | # Visual Studio LightSwitch build output
297 | **/*.HTMLClient/GeneratedArtifacts
298 | **/*.DesktopClient/GeneratedArtifacts
299 | **/*.DesktopClient/ModelManifest.xml
300 | **/*.Server/GeneratedArtifacts
301 | **/*.Server/ModelManifest.xml
302 | _Pvt_Extensions
303 |
304 | # Paket dependency manager
305 | .paket/paket.exe
306 | paket-files/
307 |
308 | # FAKE - F# Make
309 | .fake/
310 |
311 | # CodeRush personal settings
312 | .cr/personal
313 |
314 | # Python Tools for Visual Studio (PTVS)
315 | __pycache__/
316 | *.pyc
317 |
318 | # Cake - Uncomment if you are using it
319 | tools/**
320 | # !tools/packages.config
321 |
322 | # Tabs Studio
323 | *.tss
324 |
325 | # Telerik's JustMock configuration file
326 | *.jmconfig
327 |
328 | # BizTalk build output
329 | *.btp.cs
330 | *.btm.cs
331 | *.odx.cs
332 | *.xsd.cs
333 |
334 | # OpenCover UI analysis results
335 | OpenCover/
336 |
337 | # Azure Stream Analytics local run output
338 | ASALocalRun/
339 |
340 | # MSBuild Binary and Structured Log
341 | *.binlog
342 |
343 | # NVidia Nsight GPU debugger configuration file
344 | *.nvuser
345 |
346 | # MFractors (Xamarin productivity tool) working folder
347 | .mfractor/
348 |
349 | # Local History for Visual Studio
350 | .localhistory/
351 |
352 | # BeatPulse healthcheck temp database
353 | healthchecksdb
354 |
355 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
356 | MigrationBackup/
357 |
358 | # Ionide (cross platform F# VS Code tools) working folder
359 | .ionide/
360 |
361 | # Fody - auto-generated XML schema
362 | FodyWeavers.xsd
363 |
364 | # Custom additions
365 | lib/
366 | *.css
367 |
--------------------------------------------------------------------------------
/Blazor.PrerenderCache.UnitTest/Blazor.PrerenderCache.UnitTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Blazor.PrerenderCache.UnitTest
4 | Blazor.PrerenderCache.UnitTest
5 | net5.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Blazor.PrerenderCache.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30011.22
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "00 - Build", "00 - Build", "{BF8B0D75-A2E1-4A91-8581-6C218FE73FC0}"
7 | ProjectSection(SolutionItems) = preProject
8 | build.cake = build.cake
9 | EndProjectSection
10 | EndProject
11 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.PrerenderCache", "Blazor.PrerenderCache\Blazor.PrerenderCache.csproj", "{4B4D391E-8F19-4707-B90D-8A24F5069633}"
12 | EndProject
13 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blazor.PrerenderCache.UnitTest", "Blazor.PrerenderCache.UnitTest\Blazor.PrerenderCache.UnitTest.csproj", "{D6E9AE1F-534B-42BF-A4EC-C7ED8B936534}"
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {4B4D391E-8F19-4707-B90D-8A24F5069633}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {4B4D391E-8F19-4707-B90D-8A24F5069633}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {4B4D391E-8F19-4707-B90D-8A24F5069633}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {4B4D391E-8F19-4707-B90D-8A24F5069633}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {D6E9AE1F-534B-42BF-A4EC-C7ED8B936534}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {D6E9AE1F-534B-42BF-A4EC-C7ED8B936534}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {D6E9AE1F-534B-42BF-A4EC-C7ED8B936534}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {D6E9AE1F-534B-42BF-A4EC-C7ED8B936534}.Release|Any CPU.Build.0 = Release|Any CPU
29 | EndGlobalSection
30 | GlobalSection(SolutionProperties) = preSolution
31 | HideSolutionNode = FALSE
32 | EndGlobalSection
33 | GlobalSection(ExtensibilityGlobals) = postSolution
34 | SolutionGuid = {728FD3B3-6BAC-49FE-9D6B-B0AFEBE5C7B9}
35 | EndGlobalSection
36 | EndGlobal
37 |
--------------------------------------------------------------------------------
/Blazor.PrerenderCache/Blazor.PrerenderCache.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1.0.0
4 |
5 | Flyingpie.Blazor.PrerenderCache
6 | Flyingpie.Blazor.PrerenderCache
7 |
8 | enable
9 | true
10 | bin
11 | net5.0
12 |
13 |
14 | true
15 | Marco van den Oever
16 | Flyingpie.Blazor.PrerenderCache
17 | MIT
18 | pie.png
19 | https://github.com/flyingpie/blazor-prerender-cache
20 | blazor webassembly prerender prerendering cache
21 | Cache for use with Blazor WebAssembly and server prerendering, to prevent/ease the double initialize ui flash.
22 |
23 | 1.0.0 Initial release
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Blazor.PrerenderCache/PrerenderCache.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Components;
2 | using Microsoft.JSInterop;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text.Json;
6 | using System.Threading.Tasks;
7 |
8 | namespace Flyingpie.Blazor.PrerenderCache
9 | {
10 | public interface IPrerenderCache
11 | {
12 | Task GetOrAdd(string key, Func> factory);
13 |
14 | string Serialize();
15 | }
16 |
17 | public class PrerenderCache : IPrerenderCache
18 | {
19 | private readonly IJSRuntime _js;
20 |
21 | public PrerenderCache(IJSRuntime js)
22 | {
23 | _js = js ?? throw new ArgumentNullException(nameof(js));
24 | }
25 |
26 | public Dictionary Items { get; set; } = new Dictionary();
27 |
28 | private bool _isLoaded;
29 |
30 | [Inject]
31 | public IJSRuntime JS { get; set; }
32 |
33 | public bool IsRunningOnServer => _js.GetType().Name == "UnsupportedJavaScriptRuntime";
34 |
35 | public async Task GetOrAdd(string key, Func> factory)
36 | {
37 | if (IsRunningOnServer)
38 | {
39 | var res = await factory();
40 |
41 | Items[key] = res;
42 |
43 | return res;
44 | }
45 | else
46 | {
47 | await LoadAsync();
48 |
49 | if (Items.Remove(key, out var item))
50 | {
51 | Console.WriteLine("From cache");
52 |
53 | var json = JsonSerializer.Serialize(item);
54 |
55 | return JsonSerializer.Deserialize(json);
56 | }
57 |
58 | Console.WriteLine("From factory");
59 | return await factory();
60 | }
61 | }
62 |
63 | public async Task LoadAsync()
64 | {
65 | if (!_isLoaded)
66 | {
67 | Items = await _js.InvokeAsync>("prerenderCache.load");
68 | _isLoaded = true;
69 |
70 | Console.WriteLine($"Loaded cache ({Items.Count} items).");
71 | }
72 | }
73 |
74 | public string Serialize() => JsonSerializer.Serialize(Items);
75 | }
76 | }
--------------------------------------------------------------------------------
/Blazor.PrerenderCache/PrerenderCacheStore.razor:
--------------------------------------------------------------------------------
1 | @inject IPrerenderCache cache
2 |
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Blazor Prerender Cache
2 | Cache for use with Blazor WebAssembly and server prerendering. Prevents/eases the double initialize UI flash.
3 |
4 | ## The Problem
5 | This is an attempt to solve/ease the problem, where Blazor WebAssembly + Server Prerendering on pages can cause a "UI Flash".
6 |
7 | 1. Page is rendered on the server (including some async step such as a database call), and the resulting static version of the page is sent to the browser.
8 | 2. The browser renders the static page, leading to a fast, SEO-friendly initial load.
9 | 3. Blazor is being set up in the background, pulling in .Net and the framework binaries.
10 | 4. The app starts and replaces (part of) the initial static page with the dynamic, client-side rendered one.
11 | 5. Some async data gets loaded once again, this time by the client.
12 |
13 | The time it takes to fetch the data for the second time is what causes the UI to flash.
14 |
15 | 
16 |
17 | ## The "Fix"
18 |
19 | This piece of code adds a cache, that handles a lot like the IMemoryCache (which is one of the suggested ways of solving this problem in the first place).
20 |
21 | Though, instead of storing the cache on the server (thereby removing eg. a second trip to the database), the cache is stored in the static prerendered page.
22 |
23 | Then, when the page gets a second initialization, the cache is loaded from the static page and data gets pulled from there.
24 | This prevents the trip to the server entirely, removing the async step and drastically reducing/removing the second loading phase.
25 |
26 | ## Installation
27 |
28 | The library is available as a NuGet package for convienence, but it's so small that it might preferable to just copy the 2 files into your project.
29 |
30 | 1. PrerenderCache.cs
31 | 2. PrerenderCacheStore.razor
32 |
33 | ```
34 | Install-Package Flyingpie.Blazor.PrerenderCache
35 | ```
36 |
37 | ## Usage
38 |
39 | 1. Register IPrerenderCache.
40 |
41 | ```csharp
42 | builder.Services
43 | .AddScoped()
44 | ;
45 | ```
46 |
47 | 2. Include the PrerenderCacheStore component in _Host.cshtml.
48 |
49 | ```cshtml
50 |
51 | ```
52 |
53 | Note that this component must be added to the very bottom of the page, so it gets loaded after all the other components.
54 |
55 | This is to prevent the component from rendering before all to-be-cached-data is available from IPrerenderCache.
56 |
57 | 3. Fetch data subject to double-initialization through IPrerenderCache.
58 |
59 | ```csharp
60 | [Inject]
61 | public IPrerenderCache Cache { get; set; }
62 |
63 | protected override async Task OnInitializedAsync()
64 | {
65 | // Original
66 | // VM = await StashApiClient.GetPostsAsync();
67 |
68 | // Cacheable
69 | VM = await Cache.GetOrAdd(nameof(Articles), () => StashApiClient.GetPostsAsync());
70 | }
71 | ```
72 |
73 | The first argument of the GetOrAdd-method is the cache key, which must be unique within the page.
74 |
75 | ## Under The Hood
76 |
77 | You can see the result of the cache by looking at the page source:
78 |
79 | ```html
80 |
86 | ```
87 |
--------------------------------------------------------------------------------
/build.cake:
--------------------------------------------------------------------------------
1 | #tool "nuget:?package=GitVersion.CommandLine&version=4.0.0"
2 | #tool "nuget:?package=vswhere&version=2.6.7"
3 |
4 | var configuration = Argument("configuration", "Release");
5 | var isPreRelease = Argument("isPreRelease", true);
6 | var output = Argument("output", "artifacts");
7 |
8 | var sln = "Blazor.PrerenderCache.sln";
9 | var nupkgs = "Blazor.PrerenderCache/**/*.nupkg";
10 |
11 | // Determine package version
12 | var gv = GitVersion();
13 | var branch = gv.BranchName;
14 | if (branch.Contains("/")) branch = branch.Substring(branch.LastIndexOf('/') + 1);
15 |
16 | var version = XmlPeek(GetFiles("**/*.csproj").First(), "//Version");
17 | var versionPkg = !isPreRelease ? version : $"{version}-{branch}-{DateTime.Now:MMddHHmm}";
18 |
19 | Task("Clean").Does(() =>
20 | {
21 | CleanDirectory(output);
22 | });
23 |
24 | Task("Build").Does(() =>
25 | {
26 | MSBuild(sln, new MSBuildSettings
27 | {
28 | Configuration = configuration,
29 | Restore = true,
30 | ToolPath = GetFiles(VSWhereLatest() + "/**/MSBuild.exe").FirstOrDefault()
31 | }
32 | .WithProperty("AssemblyVersion", version)
33 | .WithProperty("FileVersion", versionPkg)
34 | .WithProperty("InformationalVersion", versionPkg)
35 | .WithProperty("PackageVersion", versionPkg)
36 | );
37 | });
38 |
39 | Task("Test").Does(() =>
40 | {
41 | VSTest($"./**/bin/{configuration}/net5.0/*.UnitTest.dll", new VSTestSettings
42 | {
43 | ToolPath = GetFiles(VSWhereLatest() + "/**/vstest.console.exe").FirstOrDefault()
44 | });
45 | });
46 |
47 | Task("Artifact.NuGet").Does(() =>
48 | {
49 | MoveFiles(nupkgs, output);
50 | });
51 |
52 | Task("Default")
53 | .IsDependentOn("Clean")
54 | .IsDependentOn("Build")
55 | .IsDependentOn("Test")
56 | .IsDependentOn("Artifact.NuGet")
57 | .Does(() => {})
58 | ;
59 |
60 | RunTarget("Default");
61 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | dotnet tool restore
2 | dotnet dotnet-cake
--------------------------------------------------------------------------------
/img/DoubleLoad.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flyingpie/blazor-prerender-cache/2ac7d6feb03a3a73cc9374fbd25863e3b268b595/img/DoubleLoad.gif
--------------------------------------------------------------------------------
/pie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flyingpie/blazor-prerender-cache/2ac7d6feb03a3a73cc9374fbd25863e3b268b595/pie.png
--------------------------------------------------------------------------------