From e167dc59093742c4baa72038fbc2b682f3c36f70 Mon Sep 17 00:00:00 2001 From: Jeremy Woertink Date: Fri, 9 Sep 2022 14:17:32 -0700 Subject: [PATCH] Experimenting with optional vite integration. (#1729) * Experimenting with optional vite integration. Ref #1724 * move the manifest loading to the top since it happens at compilation time and only needs to run onces --- public/vite-manifest.json | 10 +++++ spec/lucky/asset_helpers_spec.cr | 54 ++++++++++++++++++++++-- spec/spec_helper.cr | 1 + src/lucky/asset_helpers.cr | 7 +++ src/run_macros/generate_asset_helpers.cr | 26 ++++++++++-- 5 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 public/vite-manifest.json diff --git a/public/vite-manifest.json b/public/vite-manifest.json new file mode 100644 index 000000000..f990c3642 --- /dev/null +++ b/public/vite-manifest.json @@ -0,0 +1,10 @@ +{ + "src/images/lucky_logo.png": { + "file": "images/lucky_logo.a54cc67e.png", + "src": "src/images/lucky_logo.png" + }, + "src/assets/js/app.js": { + "file": "assets/js/app.a54cc67e.js", + "src": "src/assets/js/app.js" + } +} diff --git a/spec/lucky/asset_helpers_spec.cr b/spec/lucky/asset_helpers_spec.cr index 4ecef0352..5748e56fb 100644 --- a/spec/lucky/asset_helpers_spec.cr +++ b/spec/lucky/asset_helpers_spec.cr @@ -5,10 +5,13 @@ module Shared::ComponentWithAsset asset("images/logo.png") end - def dynamic_asset_inside_component - interpolated = "logo" + def dynamic_asset_inside_component(interpolated = "logo") dynamic_asset("images/#{interpolated}.png") end + + def vite_asset_inside_component + asset("images/lucky_logo.png") + end end private class TestPage @@ -23,14 +26,17 @@ private class TestPage asset("images/inside-assets-folder.png") end - def dynamic_asset_path - interpolated = "logo" + def dynamic_asset_path(interpolated = "logo") dynamic_asset("images/#{interpolated}.png") end def missing_dynamic_asset_path dynamic_asset("woops!.png") end + + def asset_path_from_vite + asset("images/lucky_logo.png") + end end describe Lucky::AssetHelpers do @@ -79,4 +85,44 @@ describe Lucky::AssetHelpers do end end end + + describe "testing with vite manifest" do + it "returns the fingerprinted path" do + Lucky::AssetHelpers.asset("images/lucky_logo.png").should eq "/images/lucky_logo.a54cc67e.png" + end + + it "works when included in another class" do + TestPage.new.asset_path_from_vite.should eq "/images/lucky_logo.a54cc67e.png" + end + + it "works when used from an included module" do + TestPage.new.vite_asset_inside_component.should eq "/images/lucky_logo.a54cc67e.png" + end + + it "prepends the asset_host configuration option" do + Lucky::Server.temp_config(asset_host: "https://production.com") do + TestPage.new.asset_path_from_vite.should eq "https://production.com/images/lucky_logo.a54cc67e.png" + end + end + + it "returns the fingerprinted path" do + TestPage.new.dynamic_asset_path("lucky_logo").should eq "/images/lucky_logo.a54cc67e.png" + end + + it "works inside included module" do + TestPage.new.dynamic_asset_inside_component("lucky_logo").should eq "/images/lucky_logo.a54cc67e.png" + end + + it "raises a helpful error" do + expect_raises Exception, "Missing asset: woops!.png" do + TestPage.new.missing_dynamic_asset_path + end + end + + it "prepends the asset_host configuration option" do + Lucky::Server.temp_config(asset_host: "https://production.com") do + TestPage.new.dynamic_asset_path("lucky_logo").should eq "https://production.com/images/lucky_logo.a54cc67e.png" + end + end + end end diff --git a/spec/spec_helper.cr b/spec/spec_helper.cr index 6c71e837b..e5955135b 100644 --- a/spec/spec_helper.cr +++ b/spec/spec_helper.cr @@ -8,6 +8,7 @@ include RoutesHelper Pulsar.enable_test_mode! Lucky::AssetHelpers.load_manifest +Lucky::AssetHelpers.load_manifest("./public/vite-manifest.json", use_vite: true) Spec.before_each do ARGV.clear diff --git a/src/lucky/asset_helpers.cr b/src/lucky/asset_helpers.cr index 92f502832..9a07e3630 100644 --- a/src/lucky/asset_helpers.cr +++ b/src/lucky/asset_helpers.cr @@ -13,6 +13,13 @@ module Lucky::AssetHelpers {% CONFIG[:has_loaded_manifest] = true %} end + # EXPERIMENTAL: This feature is experimental. Use this to test + # vite integration with Lucky + macro load_manifest(manifest_file, use_vite) + {{ run "../run_macros/generate_asset_helpers", manifest_file, use_vite }} + {% CONFIG[:has_loaded_manifest] = true %} + end + # Return the string path to an asset # # ``` diff --git a/src/run_macros/generate_asset_helpers.cr b/src/run_macros/generate_asset_helpers.cr index b1c7a95f7..cb6753017 100644 --- a/src/run_macros/generate_asset_helpers.cr +++ b/src/run_macros/generate_asset_helpers.cr @@ -8,16 +8,21 @@ private class AssetManifestBuilder property retries @retries : Int32 = 0 @manifest_path : String = File.expand_path("./public/mix-manifest.json") + @use_vite : Bool = false def initialize end - def initialize(@manifest_path) + def initialize(@manifest_path, @use_vite : Bool = false) end def build_with_retry if manifest_exists? - build + if @use_vite + build_with_vite_manifest + else + build_with_mix_manifest + end else retry_or_raise_error end @@ -33,16 +38,28 @@ private class AssetManifestBuilder end end - private def build + private def build_with_mix_manifest manifest_file = File.read(@manifest_path) manifest = JSON.parse(manifest_file) manifest.as_h.each do |key, value| + # "/js/app.js" => "js/app.js", key = key.gsub(/^\//, "").gsub(/^assets\//, "") puts %({% ::Lucky::AssetHelpers::ASSET_MANIFEST["#{key}"] = "#{value.as_s}" %}) end end + private def build_with_vite_manifest + manifest_file = File.read(@manifest_path) + manifest = JSON.parse(manifest_file) + + manifest.as_h.each do |key, value| + # "src/images/lucky_logo.png" => "images/lucky_logo.png" + key = key[4..] + puts %({% ::Lucky::AssetHelpers::ASSET_MANIFEST["#{key}"] = "/#{value["file"].as_s}" %}) + end + end + private def manifest_exists? File.exists?(@manifest_path) end @@ -55,11 +72,12 @@ end begin manifest_path = ARGV[0] + use_vite = ARGV[1]? == "true" builder = if manifest_path.blank? AssetManifestBuilder.new else - AssetManifestBuilder.new(manifest_path) + AssetManifestBuilder.new(manifest_path, use_vite) end builder.build_with_retry