# frozen-string-literal: true#classRodamoduleRodaPlugins# The precompile_templates plugin adds support for precompiling template code.# This can result in a large memory savings for applications that have large# templates or a large number of small templates if the application uses a# forking webserver. By default, template compilation is lazy, so all the# child processes in a forking webserver will have their own copy of the# compiled template. By using the precompile_templates plugin, you can# precompile the templates in the parent process before forking, and then# all of the child processes can use the same precompiled templates, which# saves memory.## Another advantage of the precompile_templates plugin is that after# template precompilation, access to the template file in the file system is# no longer needed, so this can be used with security features that do not# allow access to the template files at runtime.## After loading the plugin, you should call precompile_views with an array# of views to compile, using the same argument you are passing to view or# render:## plugin :precompile_templates# precompile_views %w'view1 view2'# # If the view requires local variables, you should call precompile_views with a second# argument for the local variables:## plugin :precompile_templates# precompile_views :view3, [:local_var1, :local_var2]## After all templates are precompiled, you can optionally use freeze_template_caches!,# which will freeze the template caches so that any template compilation at runtime# will result in an error. This also speeds up template cache access, since the# template caches no longer need a mutex.## freeze_template_caches!## Note that you should use Tilt 2.0.1+ if you are using this plugin, so# that locals are handled in the same order.modulePrecompileTemplates# Load the render plugin as precompile_templates depends on it.defself.load_dependencies(app,opts=OPTS)app.plugin:renderendmoduleClassMethods# Freeze the template caches. Should be called after precompiling all templates during# application startup, if you don't want to allow templates to be cached at runtime.# In addition to ensuring that no templates are compiled at runtime, this also speeds# up rendering by freezing the template caches, so that a mutex is not needed to access# them.deffreeze_template_caches!_freeze_layout_methodopts[:render]=render_opts.merge(:cache=>render_opts[:cache].freeze,:template_method_cache=>render_opts[:template_method_cache].freeze,).freezeself::RodaCompiledTemplates.freezenilend# Precompile the templates using the given options. Note that this doesn't# handle optimized template methods supported in newer versions of Roda, but# there are still cases where makes sense to use it.## You can call +precompile_templates+ with the pattern of templates you would# like to precompile:## precompile_templates "views/**/*.erb"## That will precompile all erb template files in the views directory or# any subdirectory.## If the templates use local variables, you need to specify which local# variables to precompile, which should be an array of symbols:## precompile_templates 'views/users/_*.erb', locals: [:user]## You can specify other render options when calling +precompile_templates+,# including +:cache_key+, +:template_class+, and +:template_opts+. If you# are passing any of those options to render/view for the template, you# should pass the same options when precompiling the template.## To compile inline templates, just pass a single hash containing an :inline# to +precompile_templates+:## precompile_templates inline: some_template_stringdefprecompile_templates(pattern,opts=OPTS)ifpattern.is_a?(Hash)opts=pattern.merge(opts)endiflocals=opts[:locals]locals.sort!elselocals=EMPTY_ARRAYendcompile_opts=ifpattern.is_a?(Hash)[opts]elseDir[pattern].map{|file|opts.merge(:path=>File.expand_path(file,nil))}endinstance=allocatecompile_opts.eachdo|compile_opt|template=instance.send(:retrieve_template,compile_opt)beginRender.tilt_template_compiled_method(template,locals,self)rescueNotImplementedError# When freezing template caches, you may want to precompile a template for a# template type that doesn't support template precompilation, just to populate# the cache. Tilt rescues NotImplementedError in this case, which we can ignore.nilendendnilend# Precompile the given views with the given locals, handling optimized template methods.defprecompile_views(views,locals=EMPTY_ARRAY)instance=allocateviews=Array(views)iflocals.empty?opts=OPTSelselocals_hash={}locals.each{|k|locals_hash[k]=nil}opts={:locals=>locals_hash}endviews.eachdo|view|instance.send(:retrieve_template,instance.send(:render_template_opts,view,opts))endiflocals_hashviews.eachdo|view|instance.send(:_optimized_render_method_for_locals,view,locals_hash)endendnilendendendregister_plugin(:precompile_templates,PrecompileTemplates)endend