When you access some page in Hyperstack, every model from app/hyperstack/models directory is included and sent to the browser. For the sake of security and performance, is it possible to load (automatically or by some directive) only the required code for the models and not that are used from the components?
Maybe this can be done in a way similar that policies work for data? So I am asking if there is some kind of policy in Hyperstack that restricts the code that is sent to the browser?
There is no nice automatic way of doing this, but it's not too much work to achieve this. You would have to create a shared JS file of anything that's used on every page (opal, hyperstack, react, etc), and then create a separate JS file for every Page/Single Page App.
Here's a very basic example:
Application.js
# app/assets/javascripts/application.rb
require 'webpack/client_only'
require 'components/shared'
Shared JS file
# app/hyperstack/components/shared.rb
require 'opal'
require 'webpack/client_and_server'
require 'hyperstack-config'
# etc...
User Dashboard SPA:
# app/hyperstack/components/user_dashboard.rb
# Require shared models
require './models/user'
# Require shared components
require_tree './components/user_dashboard'
Todo List SPA:
# app/hyperstack/components/todo_list.rb
# Require shared models
require './models/todo'
require './models/user'
# Require shared components
require_tree './components/todo_list'
User Dashboard HTML Layout
# app/views/layouts/user_dashboard.html.erb
<%= javascript_include_tag('application.js') %>
<%= javascript_include_tag('components/todo_list.js') %>
Todo List HTML Layout
# app/views/layouts/todo_list.html.erb
<%= javascript_include_tag('application.js') %>
<%= javascript_include_tag('components/todo_list.js') %>
What I've also done to make it more dynamic is create a helper method in the controller to define the name of the separate JS file to use based on the controller. This also allows you to use only one layout file if desired:
# app/controllers/application_controller.rb
class ApplicationController
helper_method :spa_asset
def spa_asset
params[:controller]
end
end
# app/views/layouts/application.html.erb
<%= javascript_include_tag('application.js') %>
<%= javascript_include_tag(spa_asset) %>
And then inheriting controller can redefine it if the file name doesn't match the controller name:
# app/controllers/foo_controller.rb
class FooController
def spa_asset
'todo_list'
end
end
Hope this helps!