mix popcorn. cook
(Popcorn v1.0.0)
View Source
Compiles the current Mix project and packages it for the browser.
Run the task from the project's directory:
mix popcorn.cook
# Customize output directory
mix popcorn.cook --out-dir priv/static/popcornThe default output directory is public/out. Paths are relative to the
current directory. The task uses the current Mix environment and target.
For a production build, use MIX_ENV=prod mix popcorn.cook.
The task deletes the output directory before packaging. Use a directory reserved for generated files. Do not put source files or other assets there.
Configuration
Set cooking options in your project's config/config.exs. The same settings
apply when cooking through a JavaScript bundler plugin.
import Config
config :popcorn,
extra_apps: [:eex],
treeshake: true| Setting | Behavior |
|---|---|
app | Entrypoint application. Default: the current Mix application. Set nil for no entrypoint. |
extra_apps | Additional applications to include with their required dependencies. Default: []. |
runtime_variant | Selects :core or :crypto instead of automatic runtime selection. |
strip | Removes BEAM debug and documentation chunks. Default: true. |
exclude_priv | Leaves out priv files matching glob patterns, which are relative to priv: {app, pattern} in one application's, like {:phoenix, "templates"}, and a bare pattern in every application's, like "static/*.map". A matched directory is left out with its contents. Default: []. |
treeshake | (Experimental) Removes unreachable modules and functions. Set to true or a keyword list of options to enable. See Tree-shaking below for details. Default: false. |
brotli_effort | Selects :standard (default) or :max. :max compresses more slowly. |
Use application names, such as :my_app, rather than module names.
Runtime variants also accept strings.
Popcorn starts the entrypoint when the browser virtual machine boots.
Extra applications enter the package but do not become entrypoints.
The package includes all compiled applications in the current
environment's build directory, including runtime: false and transitive Mix
dependencies. Mix libraries with no .app file (app: false) are not
packaged. The package always includes the Elixir runtime, Popcorn's
application, which boots the VM, and their required dependencies.
The package includes the applications' config, in the boot script, which the
browser can read. runtime.exs is not evaluated.
Secrets
Don't store secrets in your Popcorn app's config. It will be readable by the browser.
The task selects crypto VM variant if the package includes asn1, crypto,
public_key, or ssl. Otherwise, it selects core.
An explicit core selection fails if an application requires crypto support.
Tree-shaking
Experimental feature
Tree-shaking is experimental. There may be breaking changes to its behaviour and configuration, even in minor releases.
Tree-shaking finds code that nothing calls and removes it from the bundle. It can significantly reduce bundle size, which is important for web apps.
Due to the dynamic nature of Elixir, it's not possible to detect unused code with
full certainty. In particular, if some code is only called through dynamic calls
(like apply/3 on a module known at runtime), it's possible that tree-shaking
removes it.
You can use the keep option to prevent given piece of code from being removed,
along with all the code it depends on. keep accepts a keyword list with the following
entries:
mod: module- keeps all public functions of a module,mfa: {module, fun, arity}- keeps a given function,behaviour_impls: behaviour- keeps all modules implementing a given behaviour,referenced_modules_defining: {fun, arity}- if a module is referenced in the reachable code, keeps it as a whole as long as it defines a given function
For example:
config :popcorn,
treeshake: [keep: [mod: MyApp.Plugin, mfa: {MyApp.Codec, :decode, 1}]]keep can be also used to work-around a bug in the tree-shaker. In such case, please
open an issue in Popcorn.
Tree-shaking doesn't work for use cases involving code compilation and evaluation. The compiler and evaluator code is dropped by default.
Output
The output contains the browser API (index.mjs), workers, and WebAssembly
runtime. The otp/ directory contains manifest.json and three archives:
stdlib.<hash>.tar, app.<hash>.tar, and deps.<hash>.tar. They contain
selected OTP/Elixir built-ins, user applications, and remaining dependencies
respectively. All output artifacts also have .gz and .br variants.
Serve the complete output directory. Keep its generated layout.
Import Popcorn from the generated index.mjs to use the package.
Configure the web server with Cross-Origin-Opener-Policy: same-origin and
Cross-Origin-Embedder-Policy: require-corp.
Packaging failures
- If an application is missing, check its name and the current Mix environment
and target. Fetch project dependencies with
mix deps.getbefore cooking. - For
unsupported_otporunsupported_boot, use an OTP installation that matches the packaged runtime version.