From db07a9d5ba6faa4e17870d7839f7e4f2142f2fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Tue, 13 Feb 2024 13:45:09 +0200 Subject: [PATCH] compress-all --- flake.nix | 3 +- hosts/vno1-oh2/configuration.nix | 2 +- modules/services/gitea/default.nix | 2 +- pkgs/compress-all.nix | 128 +++++++++++++++++++++++++++++ pkgs/gamja.nix | 74 ++++++----------- 5 files changed, 155 insertions(+), 54 deletions(-) create mode 100644 pkgs/compress-all.nix diff --git a/flake.nix b/flake.nix index bdeb82a..326f828 100644 --- a/flake.nix +++ b/flake.nix @@ -107,6 +107,7 @@ tmuxbash = super.callPackage ./pkgs/tmuxbash.nix {}; nicer = super.callPackage ./pkgs/nicer.nix {}; gamja = super.callPackage ./pkgs/gamja.nix {}; + compressAll = super.callPackage ./pkgs/compress-all.nix {}; }) ]; in @@ -322,7 +323,7 @@ }; }; - packages.gamja = pkgs.gamja; + packages.gamja = pkgs.compressAll pkgs.gamja; devShells.default = pkgs.mkShellNoCC { packages = [ diff --git a/hosts/vno1-oh2/configuration.nix b/hosts/vno1-oh2/configuration.nix index bab87c4..a590852 100644 --- a/hosts/vno1-oh2/configuration.nix +++ b/hosts/vno1-oh2/configuration.nix @@ -312,7 +312,7 @@ abort @denied tls {$CREDENTIALS_DIRECTORY}/irc.jakstys.lt-cert.pem {$CREDENTIALS_DIRECTORY}/irc.jakstys.lt-key.pem - root * ${gamja.passthru.data-compressed} + root * ${pkgs.compressAll gamja} file_server browse { precompressed br gzip } diff --git a/modules/services/gitea/default.nix b/modules/services/gitea/default.nix index de031be..aa01811 100644 --- a/modules/services/gitea/default.nix +++ b/modules/services/gitea/default.nix @@ -78,7 +78,7 @@ route /static/assets/* { uri strip_prefix /static/assets file_server * { - root ${pkgs.gitea.passthru.data-compressed}/public + root ${pkgs.compressAll pkgs.gitea.data}/public precompressed br gzip } } diff --git a/pkgs/compress-all.nix b/pkgs/compress-all.nix new file mode 100644 index 0000000..f12eb78 --- /dev/null +++ b/pkgs/compress-all.nix @@ -0,0 +1,128 @@ +/* +compress-all compresses files in a given derivation. + +Useful when one wants to pre-compress certain static assets and pass them to +the web server. For example, `pkgs.gamja` creates this derivation: + + /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/ + ├── index.2fd01148.js + ├── index.2fd01148.js.map + ├── index.37aa9a8a.css + ├── index.37aa9a8a.css.map + ├── index.html + └── manifest.webmanifest + +`pkgs.compressAll pkgs.gamja`: + + /nix/store/f5ryid7zrw2hid7h9kil5g5j29q5r2f7-gamja-1.0.0-beta.9-compressed + ├── index.2fd01148.js -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js + ├── index.2fd01148.js.br + ├── index.2fd01148.js.gz + ├── index.2fd01148.js.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.2fd01148.js.map + ├── index.2fd01148.js.map.br + ├── index.2fd01148.js.map.gz + ├── index.37aa9a8a.css -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css + ├── index.37aa9a8a.css.br + ├── index.37aa9a8a.css.gz + ├── index.37aa9a8a.css.map -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.37aa9a8a.css.map + ├── index.37aa9a8a.css.map.br + ├── index.37aa9a8a.css.map.gz + ├── index.html -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/index.html + ├── index.html.br + ├── index.html.gz + ├── manifest.webmanifest -> /nix/store/2wn1qbk8gp4y2m8xvafxv1b2dcdqj8fz-gamja-1.0.0-beta.9/manifest.webmanifest + ├── manifest.webmanifest.br + └── manifest.webmanifest.gz + + +When this `-compressed` directory is passed to a properly configured web +server, it will serve those pre-compressed files: + + $ curl -I -H 'Accept-Encoding: br' https://irc.example.org/ + <...> + content-encoding: br + <...> + +For example, a caddy configuration snippet for gamja to serve +the static assets (JS, CSS files) pre-compressed: + + virtualHosts."irc.example.org".extraConfig = '' + root * ${pkgs.compressAll pkgs.gamja} + file_server browse { + precompressed br gzip + } + ''; + +This feature is also available in nginx via `ngx_brotli` and +`ngx_http_gzip_static_module`. + + +Inputs: +- extensions :: [String] + + The default list of file extensions to compress. + + Default: common formats that compress well. The list may be appended (but + not reduced) without warning. + +- extraExtensions :: [String] + + Extra extensions to compress in addition to `extensions`. + +- compressors :: [String] + + A list of compressor names to use. + + Default: ["gz" "br"] + +- compressor- :: String + + Maps a desired extension (e.g. `gz`) to a compress program (e.g. `zopfli + --keep {}`). + + The compressor program that will be executed to get the `COMPRESSOR` + extension. The program is passed to xargs like this: + + xargs -I{} -n1 ${prog} + + Example: + + compressor-xz = "${xz}/bin/xz --keep {}"; + compressor-zst = "${zstd}/bin/zstd --keep {}"; +*/ +{ + lib, + runCommand, + xorg, + zopfli, + brotli, + xz, + zstd, + extensions ? ["css" "js" "svg" "ttf" "eot" "txt" "xml" "map" "html" "json" "webmanifest"], + extraExtensions ? [], + compressors ? ["gz" "br"], +} @ args: drv: let + compressorMap = + { + compressor-gz = "${zopfli}/bin/zopfli --keep {}"; + compressor-br = "${brotli}/bin/brotli --keep --no-copy-stat {}"; + compressor-xz = "${xz}/bin/xz --keep {}"; + compressor-zst = "${zstd}/bin/zstd --keep {}"; + } + // lib.filterAttrs (k: _: (lib.hasPrefix "compressor-" k)) args; + compressCommands = + map + (ext: let + prog = builtins.getAttr "compressor-${ext}" compressorMap; + in "tee >(xargs -I{} -n1 -P$NIX_BUILD_CORES ${prog})") + compressors; + extensionsVbar = builtins.concatStringsSep "|" (extensions ++ extraExtensions); +in + runCommand "${drv.name}-compressed" {} '' + mkdir $out + ${xorg.lndir}/bin/lndir ${drv}/ $out/ + + find -L $out -type f -regextype posix-extended \ + -iregex '.*\.(${extensionsVbar})' | \ + ${builtins.concatStringsSep " | \\\n " compressCommands} + '' diff --git a/pkgs/gamja.nix b/pkgs/gamja.nix index f5ffd74..2ccce4c 100644 --- a/pkgs/gamja.nix +++ b/pkgs/gamja.nix @@ -1,65 +1,37 @@ { lib, - stdenvNoCC, fetchFromSourcehut, buildNpmPackage, - runCommand, writeText, - brotli, - zopfli, - xorg, # https://git.sr.ht/~emersion/gamja/tree/master/doc/config-file.md gamjaConfig ? null, -}: let +}: +buildNpmPackage rec { + pname = "gamja"; version = "1.0.0-beta.9"; - pkg = buildNpmPackage { - pname = "gamja"; - inherit version; - src = fetchFromSourcehut { - owner = "~emersion"; - repo = "gamja"; - rev = "v${version}"; - hash = "sha256-09rCj9oMzldRrxMGH4rUnQ6wugfhfmJP3rHET5b+NC8="; - }; - - npmDepsHash = "sha256-LxShwZacCctKAfMNCUMyrSaI1hIVN80Wseq/d8WITkc="; - - installPhase = '' - mv dist $out - ${lib.optionalString (gamjaConfig != null) "cp ${writeText "gamja-config" (builtins.toJSON gamjaConfig)} $out/config.json"} - ''; + src = fetchFromSourcehut { + owner = "~emersion"; + repo = "gamja"; + rev = "v${version}"; + hash = "sha256-09rCj9oMzldRrxMGH4rUnQ6wugfhfmJP3rHET5b+NC8="; }; -in - stdenvNoCC.mkDerivation { - name = pkg.pname; - inherit (pkg) version; - src = pkg; - sourceRoot = "."; - installPhase = '' - runHook preInstall - mv gamja-${version} $out - runHook postInstall - ''; + npmDepsHash = "sha256-LxShwZacCctKAfMNCUMyrSaI1hIVN80Wseq/d8WITkc="; - passthru = { - data-compressed = runCommand "gamja-compressed" {} '' - mkdir $out - ${xorg.lndir}/bin/lndir ${pkg}/ $out/ + installPhase = '' + runHook preInstall - find $out \ - -regextype posix-extended \ - -iregex '.*\.(css|js|json|map|webmanifest|html)' | \ - tee >(xargs -n1 -P''$(nproc) ${zopfli}/bin/zopfli) | \ - xargs -n1 -P''$(nproc) ${brotli}/bin/brotli --no-copy-stat - ''; - }; + cp -r dist $out + ${lib.optionalString (gamjaConfig != null) "cp ${writeText "gamja-config" (builtins.toJSON gamjaConfig)} $out/config.json"} - meta = with lib; { - description = "A simple IRC web client"; - homepage = "https://git.sr.ht/~emersion/gamja"; - license = licenses.agpl3Only; - maintainers = with maintainers; [motiejus]; - }; - } + runHook postInstall + ''; + + meta = with lib; { + description = "A simple IRC web client"; + homepage = "https://git.sr.ht/~emersion/gamja"; + license = licenses.agpl3Only; + maintainers = with maintainers; [motiejus]; + }; +}