Skip to content

Commit

Permalink
feat: Improved Phlex asset inclusion with Proscenium::Phlex::AssetInc…
Browse files Browse the repository at this point in the history
…lusions
  • Loading branch information
joelmoss committed Oct 18, 2023
1 parent ebf006c commit 26bfa4c
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 11 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,27 @@ class MyView < Proscenium::Phlex
end
```
In your layouts, include `Proscenium::Phlex::AssetInclusions`, and call the `include_assets` helper.
```ruby
class ApplicationLayout < Proscenium::Phlex
include Proscenium::Phlex::AssetInclusions
def template(&)
doctype
html do
head do
title { 'My Awesome App' }
include_assets
end
body(&)
end
end
end
```
You can specifically include CCS and JS assets using the `include_stylesheets` and `include_javascripts` helpers, allowing you to control where they are included in the HTML.
### Side-loading
Any Phlex class that inherits `Proscenium::Phlex` will automatically be [side-loaded](#side-loading).
Expand Down
15 changes: 13 additions & 2 deletions lib/proscenium/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,25 @@ def sideload(filepath, **options)
def each_stylesheet(delete: false)
return if imported.blank?

blk = proc { |key, options| key.end_with?(*CSS_EXTENSIONS) && yield(key, options) }
blk = proc do |key, options|
if key.end_with?(*CSS_EXTENSIONS)
yield(key, options)
true
end
end

delete ? imported.delete_if(&blk) : imported.each(&blk)
end

def each_javascript(delete: false)
return if imported.blank?

blk = proc { |key, options| key.end_with?(*JS_EXTENSIONS) && yield(key, options) }
blk = proc do |key, options|
if key.end_with?(*JS_EXTENSIONS)
yield(key, options)
true
end
end
delete ? imported.delete_if(&blk) : imported.each(&blk)
end

Expand Down
10 changes: 1 addition & 9 deletions lib/proscenium/phlex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,11 @@ class Phlex < ::Phlex::HTML

autoload :CssModules
autoload :ReactComponent
autoload :AssetInclusions

extend ::Phlex::Rails::HelperMacros
include ::Phlex::Rails::Helpers::JavaScriptIncludeTag
include ::Phlex::Rails::Helpers::StyleSheetLinkTag
include Proscenium::SourcePath
include CssModules

define_output_helper :side_load_stylesheets # deprecated
define_output_helper :include_stylesheets
define_output_helper :side_load_javascripts # deprecated
define_output_helper :include_javascripts
define_output_helper :declare_lazy_scripts

module Sideload
def before_template
Proscenium::SideLoad.sideload_inheritance_chain self
Expand Down
96 changes: 96 additions & 0 deletions lib/proscenium/phlex/asset_inclusions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

module Proscenium::Phlex::AssetInclusions
include Phlex::Rails::Helpers::ContentFor
include Phlex::Rails::Helpers::StyleSheetPath
include Phlex::Rails::Helpers::JavaScriptPath

def include_stylesheets
comment { '[PROSCENIUM_STYLESHEETS]' }
end

def include_javascripts(defer_lazy_scripts: false)
comment { '[PROSCENIUM_JAVASCRIPTS]' }
!defer_lazy_scripts && include_lazy_javascripts
end

def include_lazy_javascripts
comment { '[PROSCENIUM_LAZY_SCRIPTS]' }
end

def include_assets(defer_lazy_scripts: false)
include_stylesheets
include_javascripts(defer_lazy_scripts: defer_lazy_scripts)
end

def after_template
super

@_buffer.gsub! '<!-- [PROSCENIUM_STYLESHEETS] -->', capture_stylesheets!
@_buffer.gsub! '<!-- [PROSCENIUM_JAVASCRIPTS] -->', capture_javascripts!

if content_for?(:proscenium_lazy_scripts)
flush
@_buffer.gsub!('<!-- [PROSCENIUM_LAZY_SCRIPTS] -->', capture do
content_for(:proscenium_lazy_scripts)
end)
else
@_buffer.gsub! '<!-- [PROSCENIUM_LAZY_SCRIPTS] -->', ''
end
end

private

def capture_stylesheets!
capture do
Proscenium::Importer.each_stylesheet(delete: true) do |path, _path_options|
link rel: 'stylesheet', href: stylesheet_path(path, extname: false)
end
end
end

def capture_javascripts! # rubocop:disable Metrics/*
unless Rails.application.config.proscenium.code_splitting &&
Proscenium::Importer.multiple_js_imported?
return capture do
Proscenium::Importer.each_javascript(delete: true) do |path, _|
script(src: javascript_path(path, extname: false), type: :module)
end
end
end

imports = Proscenium::Importer.imported.dup
paths_to_build = []
Proscenium::Importer.each_javascript(delete: true) do |x, _|
paths_to_build << x.delete_prefix('/')
end

result = Proscenium::Builder.build(paths_to_build.join(';'), base_url: helpers.request.base_url)

# Remove the react components from the results, so they are not side loaded. Instead they
# are lazy loaded by the component manager.

capture do
scripts = {}
result.split(';').each do |x|
inpath, outpath = x.split('::')
inpath.prepend '/'
outpath.delete_prefix! 'public'

next unless imports.key?(inpath)

if (import = imports[inpath]).delete(:lazy)
scripts[inpath] = import.merge(outpath: outpath)
else
script(src: javascript_path(outpath, extname: false), type: :module)
end
end

content_for :proscenium_lazy_scripts do
script type: 'application/json', id: 'prosceniumLazyScripts' do
unsafe_raw scripts.to_json
end
end
end
end
end

0 comments on commit 26bfa4c

Please sign in to comment.