Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client builds are not deterministic in some cases #9913

Open
hasanayan opened this issue Aug 26, 2024 · 1 comment
Open

Client builds are not deterministic in some cases #9913

hasanayan opened this issue Aug 26, 2024 · 1 comment

Comments

@hasanayan
Copy link

hasanayan commented Aug 26, 2024

Reproduction

TL;DR; Path of the input files are not considered when computing the content hashes and, this sometimes causes non-deterministic builds. Make sure relative path of the file is also part of content hash computation to prevent this.

I could not manage to create a reproduction repo, size of the project might be in play here. But we spent quite some time debugging this and I'd like to share the findings.

System Info

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 2.42 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.16.0 - /usr/local/bin/node
    Yarn: 1.22.19 - ~/.yarn/bin/yarn
    npm: 10.8.1 - /usr/local/bin/npm
    pnpm: 9.7.1 - /usr/local/bin/pnpm
    bun: 1.1.24 - ~/source/cerbos/spitfire/frontend/node_modules/.bin/bun
    Watchman: 2024.04.15.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 127.0.6533.122
    Safari: 17.4.1

Used Package Manager

pnpm

Expected Behavior

I would expect build outputs to be consistent across different builds unless there is a change in the inputs

Actual Behavior

We have many route modules named as route.tsx files under route folders. Some of those routes (let's assume the count is x) have different loaders/actions but they import the exact same component from a shared folder and export is as default.

When we analyzed our build outputs, we saw that the manifest file was changing its content hash on each build. All route files were named as route-[hash].tsx, which looks normal at first but when we look into contents of the manifest file, too, we realized that the x routes that import and export the same component were swapping file names with each other on each build. Which was causing the contents of manifest file to change on each build.

We've made some deductions/observations on what was happening;

  • When you take only the client code from the route files, you end up with exactly the same content for those x routes. They just import and re-export as default the same component.
  • content hash computation does not take the path of the file into account

Because of these two, those x routes are supposed to get the same output file name (exact same content hash). It seems vite is adding incremental numbers to the clashing file names to prevent collisions so they are getting non-clashing names.

BUT those x routes are randomly sharing those x file names on each build. It seems they are not being processed in the same order across builds and, this is causing the change in manifest file contents and thus, we get non-deterministic builds.

To remedy this, I created a vite plugin that adds the path of the file as a comment in the route files and makes sure it is placed in a way that the comment ends up in the client code and that way we get deterministic builds.

@gnohj
Copy link

gnohj commented Sep 4, 2024

OS: Mac Sonoma 14.16.1
Node: 20.15.1
PNPM: 9.7.1
Remix: 2.11.2


I’m experiencing a similar issue, and it aligns with the findings mentioned here. The manifest’s content hash keeps changing between builds, even though the input files and environment has not been modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants
@brophdawg11 @hasanayan @gnohj and others