{"id":16592463,"url":"https://github.com/hauleth/phoenix_bakery","last_synced_at":"2025-03-16T21:30:38.855Z","repository":{"id":45128952,"uuid":"414173013","full_name":"hauleth/phoenix_bakery","owner":"hauleth","description":"Better compression for your Phoenix assets","archived":false,"fork":false,"pushed_at":"2023-03-14T08:14:37.000Z","size":3883,"stargazers_count":56,"open_issues_count":1,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-27T14:30:26.290Z","etag":null,"topics":["assets","compression","hacktoberfest","phoenix","phoenix-framework"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hauleth.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["hauleth"]}},"created_at":"2021-10-06T10:50:32.000Z","updated_at":"2024-11-13T20:42:32.000Z","dependencies_parsed_at":"2023-02-18T15:31:22.621Z","dependency_job_id":null,"html_url":"https://github.com/hauleth/phoenix_bakery","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fphoenix_bakery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fphoenix_bakery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fphoenix_bakery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hauleth%2Fphoenix_bakery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hauleth","download_url":"https://codeload.github.com/hauleth/phoenix_bakery/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243830915,"owners_count":20354850,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assets","compression","hacktoberfest","phoenix","phoenix-framework"],"created_at":"2024-10-11T23:20:58.893Z","updated_at":"2025-03-16T21:30:38.022Z","avatar_url":"https://github.com/hauleth.png","language":"Elixir","funding_links":["https://github.com/sponsors/hauleth"],"categories":[],"sub_categories":[],"readme":"# PhoenixBakery\n\n\u003c!-- start:PhoenixBakery --\u003e\nBetter compression for your Phoenix assets.\n\nThis is set of modules that implement [`Phoenix.Digester.Compressor`][]\nbehaviour which can be used together with Phoenix 1.6 or later for better\ncompression of the static assets served by `Plug.Static`.\n\n[`Phoenix.Digester.Compressor`]: https://hexdocs.pm/phoenix/1.6.0/Phoenix.Digester.Compressor.html\n\n## Installation\n\nFirst thing to do is to add `PhoenixBakery` as a dependency.\n\n```elixir\ndef deps do\n  [\n    {:phoenix_bakery, \"~\u003e 0.1.0\", runtime: false}\n  ]\nend\n```\n\nAnd configure your `Plug.Static`:\n\n```elixir\nplug Plug.Static,\n  encodings: [{\"zstd\", \".zstd\"}],\n  gzip: true,\n  brotli: true,\n  # Rest of the options…\n```\n\n\u003e #### WARNING {: .warning }\n\u003e\n\u003e Plug 1.12 do not support `:encodings` option and this option is ignored.\n\u003e So Zstandard-compressed files will not be served to the clients, even\n\u003e if client will have support for such format.\n\nThen you need to configure your compressors via Phoenix configuration:\n\n```elixir\nconfig :phoenix,\n  static_compressors: [\n    # Pick all that you want to use\n    PhoenixBakery.Gzip,\n    PhoenixBakery.Brotli,\n    PhoenixBakery.Zstd\n  ]\n```\n\n[pr-1050]: https://github.com/elixir-plug/plug/pull/1050\n\u003c!-- end:PhoenixBakery --\u003e\n\n## Supported compressors\n\n### `PhoenixBakery.Gzip`\n\n\u003c!-- start:PhoenixBakery.Gzip --\u003e\nReplacement of default [`Phoenix.Digester.Gzip`][] that provides better default\ncompression ratio (defaults to maximum possible) instead of default option that\ncompromises between compression speed and compression ratio.\n\nIt uses built-in `zlib` library, which mean, that there is no external\ndependencies and it will work OotB on any installation.\n\n#### Configuration\n\n`PhoenixBakery.Gzip` provides 3 different knobs that you can alter via\napplication configuration:\n\n```elixir\nconfig :phoenix_bakery, :gzip_opts, %{\n    level: :best_speed, # defaults to: `:best_compression`\n    window_bits: 8, # defaults to: `15` (max)\n    mem_level: 8 # defaults to: `9` (max)\n  }\n```\n\nThe shown above are defaults. For description of each option check [`zlib`\ndocumentaion][erl-zlib]\n\n[`Phoenix.Digester.Gzip`]: https://hexdocs.pm/phoenix/1.6.0/Phoenix.Digester.Gzip.html\n[erl-zlib]: https://erlang.org/doc/man/zlib.html\n\u003c!-- end:PhoenixBakery.Gzip --\u003e\n\n### `PhoenixBakery.Brotli`\n\n\u003c!-- start:PhoenixBakery.Brotli --\u003e\n[Brotli][br] is algorithm that offers better compression ratio when compared\nwith Gzip, but at the cost of greater memory consumption during compression. It\nprovides quite good decompression speed. [It is supported by all major modern browsers][caniuse-br]\n\n[br]: https://tools.ietf.org/html/rfc7932\n[caniuse-br]: https://caniuse.com/brotli\n\n#### Requirements\n\nTo use `PhoenixBakery.Brotli` you need at least one of:\n\n- Add `{:brotli, \"\u003e= 0.0.0\", runtime: false}` to use NIF version of the Brotli\n  compressor. It requires C code compilation and it can slow down compilation a\n  little as the compilation isn't the fastest.\n- Have `brotli` utility available in `$PATH` or configured via\n  `config :phoenix_bakery, :brotli, \"/path/to/brotli\"`\n\nIf none of the above is true then compressor will raise.\n\n#### Configuration\n\n```elixir\nconfig :phoenix_bakery,\n  brotli_opts: %{\n    quality: 5 # defaults to: `11` (max)\n  }\n```\n\u003c!-- end:PhoenixBakery.Brotli --\u003e\n\n### `PhoenixBakery.Zstd`\n\n\u003c!-- start:PhoenixBakery.Zstd --\u003e\n[Zstandard][zstd] is algorithm that offers quite good compression ratio when\ncompared with Gzip, but slightly worse than Brotli, but with much better\ndecompression speed. It is currently not supported by browsers, but is already\nIANA standard, so the rollout of the support should be pretty fast.\n\n[zstd]: https://datatracker.ietf.org/doc/html/rfc8878\n\n#### Requirements\n\nTo use `PhoenixBakery.Zstd` you need at least one of:\n\n- Add `{:ezstd, \"~\u003e 1.0\", runtime: false}` to use NIF version of Zstd\n  compressor. It requires C code compilation and `git` tool to be available to\n  fetch the code of `zstandard` code.\n- Have `zstd` utility available in `$PATH` or configured via\n  `config :phoenix_bakery, :zstd, \"\u003cpath-to-zstd-executable\u003e/zstd\"`\n\nIf none of the above is true then compressor will raise.\n\n#### Configuration\n\n```elixir\nconfig :phoenix_bakery,\n  zstd_opts: %{\n    level: 10 # defaults to: `22` (ultra-max)\n  }\n```\n\u003c!-- end:PhoenixBakery.Zstd --\u003e\n\n## Compression gains\n\nTest files are composed out of Phoenix JS 1.6.2 library and Phoenix LiveView JS\n0.16.4 bundled with ESBuild 0.12.17 installed from NPM repository using command\n\n```sh\nesbuild ./js/app.js --minify --target=es2020 --bundle --outdir=../priv/static/js --color=true\n```\n\nFirst we will declare our baseline. These are \"regular\" bundle and minified\nbundle and the same files compressed with default `Phoenix.Digest.Gzip`\ncompressor shipped with Phoenix:\n\n```\n155311\tphoenix_app.js\n77351\tphoenix_app.min.js\n34341\tphoenix_app.js.gz\n24393\tphoenix_app.min.js.gz\n```\n\nThese are results produced by the compressors available in this package:\n\n```\n34033\tphoenix_app.js.gz\n30323\tphoenix_app.js.zst\n29017\tphoenix_app.js.br\n24339\tphoenix_app.min.js.gz\n23202\tphoenix_app.min.js.zst\n21843\tphoenix_app.min.js.br\n```\n\nThis show us that with this input file we gain only a little bit better results\nfor GZIP compression (\u003c1% for non-minified and \u003c0.5% for minified), but quite\nsubstantial for different compression methods, namely:\n\n- ~12% for ZSTD on non-minified file and ~5% on minified JS file\n- ~15.5% for Brotli on non-minified file and ~10.5% on minified JS file\n\nWhen compared with default compression from Phoenix.\n\nZSTD while it provides slightly worse compression ratio it provides better\ndecompression times, which may be preferred on slower or low powered devices.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhauleth%2Fphoenix_bakery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhauleth%2Fphoenix_bakery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhauleth%2Fphoenix_bakery/lists"}