Skip to content

Commit 1c6c064

Browse files
adrumkapi2289
andauthored
[1.x] Added automatic Vite versioning (#34)
* added automatic vite versioning * Minor changes --------- Co-authored-by: kapi2289 <[email protected]>
1 parent 3ab22e2 commit 1c6c064

File tree

6 files changed

+91
-11
lines changed

6 files changed

+91
-11
lines changed

InertiaCore/Extensions/Configure.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ public static IApplicationBuilder UseInertia(this IApplicationBuilder app)
1818
Inertia.UseFactory(factory);
1919

2020
var viteBuilder = app.ApplicationServices.GetService<IViteBuilder>();
21-
if (viteBuilder != null) Vite.UseBuilder(viteBuilder);
21+
if (viteBuilder != null)
22+
{
23+
Vite.UseBuilder(viteBuilder);
24+
Inertia.Version(Vite.GetManifestHash);
25+
}
2226

2327
app.Use(async (context, next) =>
2428
{

InertiaCore/Extensions/InertiaExtensions.cs

+14
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Microsoft.AspNetCore.Http;
44
using Microsoft.AspNetCore.Http.Extensions;
55
using Microsoft.AspNetCore.Mvc;
6+
using System.Text;
67

78
namespace InertiaCore.Extensions;
89

@@ -49,4 +50,17 @@ internal static bool Override<TKey, TValue>(this IDictionary<TKey, TValue> dicti
4950

5051
return result?.GetValue(task);
5152
}
53+
54+
internal static string MD5(this string s)
55+
{
56+
using var md5 = System.Security.Cryptography.MD5.Create();
57+
var inputBytes = Encoding.UTF8.GetBytes(s);
58+
var hashBytes = md5.ComputeHash(inputBytes);
59+
60+
var sb = new StringBuilder();
61+
foreach (var t in hashBytes)
62+
sb.Append(t.ToString("x2"));
63+
64+
return sb.ToString();
65+
}
5266
}

InertiaCore/Inertia.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ public static class Inertia
1919

2020
public static Task<IHtmlContent> Html(dynamic model) => _factory.Html(model);
2121

22-
public static void Version(object? version) => _factory.Version(version);
22+
public static void Version(string? version) => _factory.Version(version);
23+
24+
public static void Version(Func<string?> version) => _factory.Version(version);
2325

2426
public static string? GetVersion() => _factory.GetVersion();
2527

@@ -29,9 +31,9 @@ public static class Inertia
2931

3032
public static void Share(IDictionary<string, object?> data) => _factory.Share(data);
3133

32-
public static AlwaysProp Always(object? value) => _factory.Always(value);
34+
public static AlwaysProp Always(string value) => _factory.Always(value);
3335

34-
public static AlwaysProp Always(Func<object?> callback) => _factory.Always(callback);
36+
public static AlwaysProp Always(Func<string> callback) => _factory.Always(callback);
3537

3638
public static AlwaysProp Always(Func<Task<object?>> callback) => _factory.Always(callback);
3739

InertiaCore/ResponseFactory.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ internal interface IResponseFactory
1616
public Response Render(string component, object? props = null);
1717
public Task<IHtmlContent> Head(dynamic model);
1818
public Task<IHtmlContent> Html(dynamic model);
19-
public void Version(object? version);
19+
public void Version(string? version);
20+
public void Version(Func<string?> version);
2021
public string? GetVersion();
2122
public LocationResult Location(string url);
2223
public void Share(string key, object? value);
@@ -95,7 +96,9 @@ public async Task<IHtmlContent> Html(dynamic model)
9596
return new HtmlString($"<div id=\"app\" data-page=\"{encoded}\"></div>");
9697
}
9798

98-
public void Version(object? version) => _version = version;
99+
public void Version(string? version) => _version = version;
100+
101+
public void Version(Func<string?> version) => _version = version;
99102

100103
public string? GetVersion() => _version switch
101104
{

InertiaCore/Utils/Vite.cs

+15-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
using System.IO.Abstractions;
77
using InertiaCore.Models;
88
using Microsoft.Extensions.Options;
9+
using InertiaCore.Extensions;
910

1011
namespace InertiaCore.Utils;
1112

1213
public interface IViteBuilder
1314
{
1415
HtmlString ReactRefresh();
1516
HtmlString Input(string path);
17+
string? GetManifest();
1618
}
1719

1820
internal class ViteBuilder : IViteBuilder
@@ -65,12 +67,11 @@ public HtmlString Input(string path)
6567
throw new Exception("Vite Manifest is invalid. Run `npm run build` and try again.");
6668
}
6769

68-
if (!manifestJson.ContainsKey(path))
70+
if (!manifestJson.TryGetValue(path, out var obj))
6971
{
7072
throw new Exception("Asset not found in manifest: " + path);
7173
}
7274

73-
var obj = manifestJson[path];
7475
var filePath = obj.GetProperty("file");
7576

7677
if (IsCssPath(filePath.ToString()))
@@ -205,6 +206,13 @@ private static string GetString(IHtmlContent content)
205206
content.WriteTo(writer, HtmlEncoder.Default);
206207
return writer.ToString();
207208
}
209+
210+
public string? GetManifest()
211+
{
212+
return _fileSystem.File.Exists(GetPublicPathForFile(_options.Value.ManifestFilename))
213+
? _fileSystem.File.ReadAllText(GetPublicPathForFile(_options.Value.ManifestFilename))
214+
: null;
215+
}
208216
}
209217

210218
public static class Vite
@@ -222,4 +230,9 @@ public static class Vite
222230
/// Generate React refresh runtime script.
223231
/// </summary>
224232
public static HtmlString ReactRefresh() => _instance.ReactRefresh();
233+
234+
/// <summary>
235+
/// Generate the Manifest hash.
236+
/// </summary>
237+
public static string? GetManifestHash() => _instance.GetManifest()?.MD5();
225238
}

InertiaCoreTests/UnitTestVite.cs

+47-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
using InertiaCore.Models;
44
using InertiaCore.Utils;
55
using Microsoft.AspNetCore.Builder;
6+
using Microsoft.AspNetCore.Http;
7+
using Microsoft.AspNetCore.Mvc;
68
using Microsoft.Extensions.Options;
79
using Moq;
810

@@ -14,8 +16,6 @@ public partial class Tests
1416
[Description("Test if the Vite configuration registers properly the service.")]
1517
public void TestViteConfiguration()
1618
{
17-
Assert.Throws<NullReferenceException>(() => Vite.ReactRefresh());
18-
1919
var builder = WebApplication.CreateBuilder();
2020
builder.Services.AddInertia();
2121

@@ -72,7 +72,8 @@ public void TestNotHot()
7272
}
7373

7474
[Test]
75-
[Description("Test if the Vite Helper handles generating HTML tags for both JS and CSS from HMR and the manifest properly.")]
75+
[Description(
76+
"Test if the Vite Helper handles generating HTML tags for both JS and CSS from HMR and the manifest properly.")]
7677
public void TestViteInput()
7778
{
7879
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>());
@@ -209,4 +210,47 @@ public void TestViteFacade()
209210
"<script src=\"http://127.0.0.1:5174/@vite/client\" type=\"module\"></script>\n\t" +
210211
"<script src=\"http://127.0.0.1:5174/index.scss\" type=\"module\"></script>\n\t"));
211212
}
213+
214+
[Test]
215+
[Description("Test if the vite version is read properly.")]
216+
public async Task TestViteVersion()
217+
{
218+
var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>());
219+
var options = new Mock<IOptions<ViteOptions>>();
220+
options.SetupGet(x => x.Value).Returns(new ViteOptions());
221+
222+
var mock = new Mock<ViteBuilder>(options.Object);
223+
mock.Object.UseFileSystem(fileSystem);
224+
Vite.UseBuilder(mock.Object);
225+
226+
fileSystem.AddFile(@"/wwwroot/build/manifest.json",
227+
new MockFileData("{\"app.tsx\": {\"file\": \"assets/main-19038c6a.js\"}}"));
228+
229+
_factory.Version(Vite.GetManifestHash);
230+
231+
var response = _factory.Render("Test/Page", new
232+
{
233+
Test = "Test"
234+
});
235+
236+
var headers = new HeaderDictionary
237+
{
238+
{ "X-Inertia", "true" }
239+
};
240+
241+
var context = PrepareContext(headers);
242+
243+
response.SetContext(context);
244+
await response.ProcessResponse();
245+
246+
var result = response.GetResult();
247+
248+
Assert.Multiple(() =>
249+
{
250+
Assert.That(result, Is.InstanceOf<JsonResult>());
251+
252+
var json = (result as JsonResult)?.Value;
253+
Assert.That((json as Page)?.Version, Is.EqualTo("bba1afd1066309f4a69430e0c446ba8d"));
254+
});
255+
}
212256
}

0 commit comments

Comments
 (0)