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

fix(remix-dev): relativize route modules to make builds deterministic #2027

Merged
merged 1 commit into from
Jul 14, 2022

Conversation

jenseng
Copy link
Contributor

@jenseng jenseng commented Feb 18, 2022

Closes #2024

  • Tests

This fixes an issue where the build manifest/hashes/etc will differ based on the parent directory structure. If virtual modules import from absolute paths, their content is technically different when those paths change, so deterministic build output is not guaranteed.

Depending on how you build/deploy (e.g. if you need to build and deploy your server separately from your browser build), this can result in a broken app, since the server and browser manifests may differ (i.e. due to different fingerprints). Sometimes you can't directly control the absolute path where you code is checked out and run (e.g. Jenkins, docker, etc.).

By using relative paths for route modules, we can ensure the same result no matter the absolute path.

Possibly worth pointing out that this fix also affects file path comments in the server build, e.g. you'll now see stuff like:

// app/root.tsx

instead of:

// /absolute/path/on/the/build/machine/to/app/root.tsx

Testing notes:

  1. Added integration test
  2. Verified manually, i.e.
    1. Create two remix projects (via npx create-remix@latest)
    2. npm run build them both
    3. diff -r project1/build project2/build has no differences
    4. diff -r project1/public/build project2/public/build has no differences
    5. dev and start still work as per usual

@jenseng jenseng force-pushed the fix-hashing branch 2 times, most recently from 7eb108f to 0737ce8 Compare February 22, 2022 23:31
@jenseng jenseng changed the title Relativize route modules to make builds deterministic fix(remix-dev): relativize route modules to make builds deterministic Feb 22, 2022
Copy link
Member

@kentcdodds kentcdodds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm surprised that test case fails without your changes (I'm assuming you ran the test first to ensure it does fail without your changes). This is beyond where I'm comfortable merging personally, but I did leave a bit of feedback if you'd like :) Thanks!

integration/deterministic-build-output-test.ts Outdated Show resolved Hide resolved
Copy link
Member

@kentcdodds kentcdodds left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing that!

I'll leave the rest of the review to @mjackson

@jenseng
Copy link
Contributor Author

jenseng commented Apr 22, 2022

Seems like an unrelated CLI test failed, is there a way to retrigger? Or does it not matter?

@jenseng
Copy link
Contributor Author

jenseng commented Jun 3, 2022

@mjackson let me know if you have any questions/suggestions 😄

@ryanflorence
Copy link
Member

Let's fix the conflicts and then merge this bugger.

@machour machour added the needs-response We need a response from the original author about this issue/PR label Jun 21, 2022
@ryanflorence
Copy link
Member

Jon has local changes but Yarn PnP doesn't play nicely with relative paths, so going to wait for a fix there before we do this.

@jenseng
Copy link
Contributor Author

jenseng commented Jun 22, 2022

Alright, I opened a PR to fix the esbuild-plugin-pnp bug, but if we're comfortable shipping this hack we don't technically need to wait for it 😅

@jenseng
Copy link
Contributor Author

jenseng commented Jun 24, 2022

The esbuild-plugin-pnp bugfix has been merged, so once they release a new version I'll unwind my hack and bump the dependency 🥳

@jenseng jenseng force-pushed the fix-hashing branch 4 times, most recently from 3fa2a7d to 99a79d2 Compare June 27, 2022 20:44
@jenseng
Copy link
Contributor Author

jenseng commented Jun 27, 2022

This PR should be good to go, but it looks like something is generally broken around the caching done by bahmutov\npm-install step in GH actions... if a build can't use the cache (i.e. yarn.lock has changed), the windows builds will fails. Here's a simple repro I set up that fails the same way: #3584

jenseng added a commit to jenseng/remix that referenced this pull request Jun 27, 2022
getting a weird GH actions failure around the yarn cache on this PR:
remix-run#2027

seeing if i can repro with another commit
jenseng added a commit to jenseng/remix that referenced this pull request Jun 28, 2022
v1.8.16 breaks cache miss installs on windows, which blocks any PRs/commits
that change dependencies. Opened bahmutov/npm-install#146
to address the underlying issue, but in the meantime we can pin to the prior
version to get things working again.

Additional context:
- Discord: https://discord.com/channels/770287896669978684/940264701785423992/991085961972707338
- Initial PR affected: remix-run#2027
- Repro/Debug PR: remix-run#3584
jenseng added a commit to jenseng/remix that referenced this pull request Jun 28, 2022
v1.8.16 breaks cache miss installs on windows, which blocks any PRs/commits
that change dependencies. Opened bahmutov/npm-install#146
to address the underlying issue, but in the meantime we can pin to the prior
version to get things working again.

Additional context:
- Discord: https://discord.com/channels/770287896669978684/940264701785423992/991085961972707338
- Initial PR affected: remix-run#2027
- Repro/Debug PR: remix-run#3584
jenseng added a commit to jenseng/remix that referenced this pull request Jun 28, 2022
v1.8.16 breaks cache miss installs on windows, which blocks any PRs/commits
that change dependencies. Opened bahmutov/npm-install#146
to address the underlying issue, but in the meantime we can pin to the prior
version to get things working again.

Additional context:
- Discord: https://discord.com/channels/770287896669978684/940264701785423992/991085961972707338
- Initial PR affected: remix-run#2027
- Repro/Debug PR: remix-run#3584
jenseng added a commit to jenseng/remix that referenced this pull request Jun 28, 2022
v1.8.16 breaks cache miss installs on windows, which blocks any PRs/commits
that change dependencies. Opened bahmutov/npm-install#146
to address the underlying issue, but in the meantime we can pin to the prior
version to get things working again.

Additional context:
- Discord: https://discord.com/channels/770287896669978684/940264701785423992/991085961972707338
- Initial PR affected: remix-run#2027
- Repro/Debug PR: remix-run#3584
@jenseng
Copy link
Contributor Author

jenseng commented Jun 28, 2022

Alright, the PR now uses @yarnpkg/esbuild-plugin-pnp/3.0.0-rc.10 which lets us remove the plugin hack/wrapper... in addition to the tests still all passing, examples/yarn-pnp also still builds correctly with this change.

@yarnpkg/esbuild-plugin-pnp/3.x does require node >=14.15.0 (the first 14.x LTS version), but that's not new for remix since @npmcli/package-json (another dependency) does too.

That said, this all may be moot as I just noticed this PR which swaps out this plugin entirely 😆😭 ... in any event, here's the diff from 2.0.2 (what people would have been installing prior to this PR). Although the version we're using is an RC, IMO it's safe to use since the only change it brings is my bugfix:

diff --git a/packages/esbuild-plugin-pnp/package.json b/packages/esbuild-plugin-pnp/package.json
index dbb346c74..8f22e8fb6 100644
--- a/packages/esbuild-plugin-pnp/package.json
+++ b/packages/esbuild-plugin-pnp/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@yarnpkg/esbuild-plugin-pnp",
-  "version": "2.0.2",
+  "version": "3.0.0-rc.10",
   "license": "BSD-2-Clause",
   "main": "./sources/index.ts",
   "dependencies": {
@@ -31,6 +31,7 @@
     "directory": "packages/esbuild-plugin-pnp"
   },
   "engines": {
-    "node": ">=12 <14 || 14.2 - 14.9 || >14.10.0"
-  }
+    "node": ">=14.15.0"
+  },
+  "stableVersion": "2.0.1"
 }
diff --git a/packages/esbuild-plugin-pnp/sources/index.ts b/packages/esbuild-plugin-pnp/sources/index.ts
index 379b64959..64fff1588 100644
--- a/packages/esbuild-plugin-pnp/sources/index.ts
+++ b/packages/esbuild-plugin-pnp/sources/index.ts
@@ -139,9 +139,11 @@ export function pnpPlugin({
           conditions = conditionsRequire;

         // The entry point resolution uses an empty string
-        const effectiveImporter = args.importer
-          ? args.importer
-          : `${baseDir}/`;
+        const effectiveImporter = args.resolveDir
+          ? `${args.resolveDir}/`
+          : args.importer
+            ? args.importer
+            : `${baseDir}/`;

         const pnpApi = findPnpApi(effectiveImporter) as PnpApi | null;
         if (!pnpApi)

@MichaelDeBoey
Copy link
Member

As mentioned in #3594 (comment), I personally would be in favor of solving the problems from #3594 in @yarnpkg/esbuild-plugin-pnp (like we did for this one) & update the dependency instead of removing the plugin & having extra maintenance on our side tbh.

@jenseng Maybe you could point @lensbart into the right direction for a fix in @yarnpkg/esbuild-plugin-pnp?
I think you creating a fix yourself could also work though.

@MichaelDeBoey
Copy link
Member

@jenseng Due to merging #3633, we have some conflicts here. Could you please resolve them?

@changeset-bot
Copy link

changeset-bot bot commented Jul 8, 2022

🦋 Changeset detected

Latest commit: 1c6f49e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
Name Type
@remix-run/dev Patch
create-remix Patch
remix Patch
@remix-run/eslint-config Patch
@remix-run/react Patch
@remix-run/serve Patch
@remix-run/server-runtime Patch
@remix-run/cloudflare Patch
@remix-run/node Patch
@remix-run/deno Patch
@remix-run/cloudflare-pages Patch
@remix-run/cloudflare-workers Patch
@remix-run/express Patch
@remix-run/netlify Patch
@remix-run/vercel Patch
@remix-run/architect Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Fixes remix-run#2024

If virtual modules have non-deterministic paths or content (e.g. due to
importing from other absolute paths), the input is technically different,
and deterministic build output is not guaranteed.

Depending on how you build/deploy (e.g. if you need to build and deploy
your server separately from your browser build), this can result in a broken
app, since the server and browser manifests may differ (i.e. due to different
fingerprints). By using relative paths for route modules, we can ensure the
same result no matter the absolute path.

Possibly worth pointing out that this fix also affects file path comments in
the server build, e.g. you'll now see stuff like:
 // app/root.tsx
instead of:
 // /absolute/path/on/the/build/machine/to/app/root.tsx

Testing notes:
 1. Added integration test
 2. Verified manually, i.e.
    1. Create two remix projects (via npx create-remix@latest)
    2. `npm run build` them both
    3. `diff -r project1/build project2/build` has no differences
    4. `diff -r project1/public/build project2/public/build` has no differences
    5. `dev` and `start` still work as per usual
@chaance chaance merged commit 20e2d62 into remix-run:dev Jul 14, 2022
jenseng added a commit to jenseng/remix that referenced this pull request Aug 8, 2022
This is a fix along the lines of remix-run#2027; because the MDX virtual modules
resolve to absolute paths, the manifest/hashes/etc. differ based on the
parent directory structure.

Testing notes:
1. Expanded existing integration test to cover this scenario (fails without
   the fix). Also add other virtual module scenarios that weren't already
   covered
2. Validated in a real MDX Remix app that has split client / server builds
   (applied fix via patch-package)
jenseng added a commit to jenseng/remix that referenced this pull request Aug 8, 2022
This is a fix along the lines of remix-run#2027; because the MDX virtual modules
resolve to absolute paths, the manifest/hashes/etc. differ based on the
parent directory structure.

Testing notes:
1. Expanded existing integration test to cover this scenario (fails without
   the fix). Also add other virtual module scenarios that weren't already
   covered
2. Validated in a real MDX Remix app that has split client / server builds
   (applied fix via patch-package)
@MichaelDeBoey MichaelDeBoey removed the needs-response We need a response from the original author about this issue/PR label Aug 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants