Build multi-layered project using nix

I have a project that follows the following build structure:

  • some rust parts are compiled down using wasm-pack to wasm
  • the package is then included in a frontend, the frontend is built using npm run buld
  • the resulting dist folder (index.html) is then included in my backend (again written in rust)

My question know is how can I build such a project using nix, my current build strucuture is the one specified below:

FROM rust:alpine AS development
RUN apk update && apk upgrade && apk add npm git alpine-sdk openssh curl
RUN curl -fsS https://dotenvx.sh | sh
RUN cargo install wasm-pack
RUN cargo install --locked bacon
RUN rustup component add rustfmt

FROM development AS build
ARG BUILD_VARIANT=release
WORKDIR /workspace
COPY . .
RUN VARIANT=${BUILD_VARIANT} make all
RUN VARIANT=${BUILD_VARIANT} make test
WORKDIR /artifacts
RUN cp /workspace/target/${BUILD_VARIANT}/backend .
RUN strip backend

FROM scratch AS run
WORKDIR /app
COPY --from=build /artifacts/backend .
CMD ["/app/backend"]

And the makefile is here:

cargo fetch
dotenvx run -- wasm-pack build --${VARIANT} --out-dir ${CURRENT_ROOT}/wasm-pkgs/backend_interfaces sources/rust/backend_interfaces
npm install --workspaces --include=optional
npm run build --workspaces --${VARIANT}
dotenvx run -- cargo build ${CARGO_RELEASE_FLAG}

In the last step (cargo build), the backend embeds the generated index.html in the resulting binary using rust_embed.

The generated wasm package is included in my package.json like this:

  "optionalDependencies": {
    "backend_interfaces": "file:../../../wasm-pkgs/backend_interfaces"
  }

My question here is how can I download the dependencies from npm and cargo before actually running the build scripts? Do you have any pointers on this?
So my main two problems are:

  1. My frontend needs some rust parts (that are included via wasm) to be built, those are referenced via the file: URL in package.json
  2. My backend needs the frontend to be already built, because the resulting html files get included in the binary using rust_embed

I have come up with:

{
  description = "Nix environment";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/8b27c1239e5c421a2bbc2c65d52e4a6fbf2ff296";
    flake-utils.url = "github:numtide/flake-utils/04c1b180862888302ddfb2e3ad9eaa63afc60cf8";
  };

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachSystem [
      flake-utils.lib.system.x86_64-linux
      flake-utils.lib.system.aarch64-linux

      flake-utils.lib.system.x86_64-darwin
      flake-utils.lib.system.aarch64-darwin
    ] ( system:
      let
        pkgs = import nixpkgs {
          inherit system;
          config.allowUnfree = false;
        };

        stdEnv = pkgs.swiftPackages.stdenv;

        globalPackages = with pkgs; [
            # tools
            dotenvx
            zsh
            git
            gnumake
            cmake

            # rust toolchain
            rustc
            cargo
            wasm-pack

            # typescript toolchain
            nodejs_23
        ];

       package = stdEnv.mkDerivation {
            name = "package";
            src = ./.;

            buildInputs = with pkgs; globalPackages;

            phases = [ "unpackPhase" "buildPhase" "installPhase" ];

            buildPhase = ''
              ??
            '';

            installPhase = ''
              mkdir -p $out/bin
              cp my-executable $out/bin/
            '';
          };
      in {
        devShells = {
          default = pkgs.mkShell.override
          {
            stdenv = stdEnv;
          }
          {
            packages = with pkgs; globalPackages ++ [
              (vscode-with-extensions.override {
                  vscode = vscodium;
                  vscodeExtensions = with vscode-extensions; [
                      bbenoist.nix
                      streetsidesoftware.code-spell-checker
                      vscode-extensions.rust-lang.rust-analyzer
                      vscode-extensions.dbaeumer.vscode-eslint
                      vscode-extensions.esbenp.prettier-vscode
                  ] ++ vscode-utils.extensionsFromVscodeMarketplace [ ];
              })
            ];

            DONT_PROMPT_WSL_INSTALL = true; #  to supress warnings issued by vscode on wsl
          };
        };

        packages = {
          default = package;
        };
      }
    );
}