如何让buildNpmPackage输出目录而非单个bin文件?
问题
我是Nix新手,正在为Eleventy静态站点项目构建Derivation。我的package.json中定义了build脚本为"npx eleventy",运行npm run build时会将源文件编译到名为public/的静态资源目录中。
我定义的Derivation如下:
mysite.nix
{ buildNpmPackage, lib }: let fs = lib.fileset; sourceFiles = fs.gitTracked ./.; in buildNpmPackage rec { npmDepsHash = "sha256-+4lLBQ+UQ2XT0wwE6jADxG1UNZjLkQCLvvN1SdiUwZY="; pname = "mysite"; src = fs.toSource { root = ./.; fileset = sourceFiles; }; version = "0.0.1"; }
default.nix
let # channel 24.11-darwin # 2025-02-20 nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/d27f39bcb57207b9b891f7beaed84bd50e757201.tar.gz"; pkgs = import nixpkgs { config = {}; overlays = []; }; in { mysite = pkgs.callPackage ./mysite.nix { }; }
提示:该nixpkgs哈希会从头构建Node运行时,耗时数小时。建议使用其他提交哈希来复现问题。
执行nix-build --attr mysite能成功构建,也能看到Eleventy提示已写入public目录,但result符号链接目录中找不到public/。尝试给package.json添加bin属性,没有效果。
请问有没有合适的方法让buildNpmPackage生成的Derivation输出目录而非单个bin文件?或者Derivation并不适合这类场景?
解决方案
Derivation完全适合构建静态站点这类场景,问题在于buildNpmPackage默认只处理npm包的标准输出(比如bin目录、lib目录等),不会自动把Eleventy生成的public/目录复制到输出路径$out。你需要手动添加构建步骤来保留产物:
修改mysite.nix,在buildNpmPackage中添加postBuild阶段,将public/目录复制到$out:
{ buildNpmPackage, lib }: let fs = lib.fileset; sourceFiles = fs.gitTracked ./.; in buildNpmPackage rec { npmDepsHash = "sha256-+4lLBQ+UQ2XT0wwE6jADxG1UNZjLkQCLvvN1SdiUwZY="; pname = "mysite"; src = fs.toSource { root = ./.; fileset = sourceFiles; }; version = "0.0.1"; # 添加postBuild步骤,将构建产物复制到输出目录 postBuild = '' cp -r public $out ''; }
如果希望直接把public里的内容放到$out根目录(而非$out/public),可以调整命令:
postBuild = '' cp -r public/* $out/ '';
原理说明
buildNpmPackage的构建流程中,$out是Derivation的输出目录,默认只会包含npm包安装后的标准文件(比如node_modules、bin等),不会保留构建过程中生成的静态文件。- 通过
postBuild钩子,我们可以在npm构建完成后,手动将Eleventy生成的public/目录复制到$out,这样nix-build生成的result链接就会指向包含静态站点文件的目录。
内容的提问来源于stack exchange,提问作者Eleanor Holley
相关产品推荐
相关产品推荐

