MishkaCmsCore.Runtime.Compilers.Shared (Mishka CMS Core v0.0.1)

Copy Markdown View Source

The pieces the four kind compilers (component, layout, page, error page) genuinely share.

What is here, and what deliberately is not

web_module/0 and define_import/2 were byte-identical in all four and depend on nothing about the module they live in, so they live here once. component_prefetch/2 is what the page and the layout compiler both write into their modules.

make_env/0,1 looks like a fifth copy and is not one. Two things stop it moving:

  • It closes over __ENV__, which is the defining module's environment. Moving it would silently change which aliases and imports are in scope when a template is evaluated — the subtlest possible way to break rendering.
  • The four are not the same function. LiveViewCompiler.make_env/1 raises when an import fails, because a page whose helpers are missing must not render half-broken; ComponentCompiler and ErrorCompiler take no arguments and hardcode their import list, and LayoutCompiler warns. Those differences are policy, not drift.

Collapsing them would be the kind of tidying that reads well in a diff and changes behaviour, so each stays with its compiler.

Summary

Functions

What a page or layout module needs to build its components before it draws them (MishkaCmsCore.Runtime.ComponentPrefetch), from the template it is compiled from and the name of the site it belongs to, nil for a global one.

Adds module to a macro environment's imports.

The content-addressed URL of a site's compiled stylesheet, or nil before its first compile.

The content-addressed URL of a site's compiled JavaScript, or nil before its first compile.

The host application's web module — what a compiled runtime module does use on.

Functions

component_prefetch(template, site)

@spec component_prefetch(String.t() | nil, String.t() | nil) :: {Macro.t(), Macro.t()}

What a page or layout module needs to build its components before it draws them (MishkaCmsCore.Runtime.ComponentPrefetch), from the template it is compiled from and the name of the site it belongs to, nil for a global one.

The first element defines __component_references__/0, what the template names, kept for the walk a cold render takes. The second is the call its render/1 makes first, carrying the components the template names in a tag that says which copy it draws, as module names.

define_import(env, module)

@spec define_import(Macro.Env.t(), module()) ::
  {:ok, Macro.Env.t()} | {:error, term()}

Adds module to a macro environment's imports.

Takes the environment as an argument rather than capturing one, which is exactly why this half is safe to share while make_env is not.

site_css_href(site_name)

@spec site_css_href(String.t()) :: String.t() | nil

The content-addressed URL of a site's compiled stylesheet, or nil before its first compile.

Error pages used to inline the whole bundle in a <style> tag, which meant every 404 sent the site's entire CSS over the wire uncached — 1.5 MB per missing image, per crawler, per broken link, on the one response you least want to be expensive. The same bytes are already served at this URL with a far-future cache header, and a visitor who reached a 404 by clicking a bad link on the site has it in cache already.

nil means the site has never compiled; the caller should fall back to inlining, because an error page with no styling at all is worse than a large one.

site_js_href(site_name)

@spec site_js_href(String.t()) :: String.t() | nil

The content-addressed URL of a site's compiled JavaScript, or nil before its first compile.

See site_css_href/1 — same reasoning, same fallback.

web_module()

@spec web_module() :: module()

The host application's web module — what a compiled runtime module does use on.

Read through Application.compile_env/3, so changing the key recompiles this module and, through it, every compiler that reads it.