From da444821aded4bc7a81f67b6939916ec06c26d6a Mon Sep 17 00:00:00 2001 From: Pedro Cattori Date: Wed, 5 Jul 2023 21:24:29 -0400 Subject: [PATCH 1/8] fix(dev): ensure build dir exists when writing metafiles (#6776) --- packages/remix-dev/compiler/analysis.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/remix-dev/compiler/analysis.ts b/packages/remix-dev/compiler/analysis.ts index 73381afbb71..9b575bdf2e2 100644 --- a/packages/remix-dev/compiler/analysis.ts +++ b/packages/remix-dev/compiler/analysis.ts @@ -1,4 +1,4 @@ -import fs from "node:fs"; +import fs from "fs-extra"; import path from "node:path"; import type { Metafile } from "esbuild"; @@ -10,8 +10,5 @@ export let writeMetafile = ( metafile: Metafile ) => { let buildDir = path.dirname(ctx.config.serverBuildPath); - if (!fs.existsSync(buildDir)) { - fs.mkdirSync(buildDir, { recursive: true }); - } - fs.writeFileSync(path.join(buildDir, filename), JSON.stringify(metafile)); + fs.outputFileSync(path.join(buildDir, filename), JSON.stringify(metafile)); }; From efcea9e0044da3169ce467147a1a35ac486d0623 Mon Sep 17 00:00:00 2001 From: Pedro Cattori Date: Thu, 6 Jul 2023 10:28:22 -0400 Subject: [PATCH 2/8] fix(dev): log instead of throw when process cannot be killed (#6779) --- packages/remix-dev/devServer_unstable/proc.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/remix-dev/devServer_unstable/proc.ts b/packages/remix-dev/devServer_unstable/proc.ts index 6f9f6ea9c67..6076f6f8447 100644 --- a/packages/remix-dev/devServer_unstable/proc.ts +++ b/packages/remix-dev/devServer_unstable/proc.ts @@ -4,16 +4,21 @@ import pidtree from "pidtree"; let isWindows = process.platform === "win32"; export let kill = async (pid: number) => { + if (!isAlive(pid)) return; if (isWindows) { await execa("taskkill", ["/F", "/PID", pid.toString()]).catch((error) => { // taskkill 128 -> the process is already dead - if (error.exitCode !== 128) throw error; + if (error.exitCode === 128) return; + if (/There is no running instance of the task./.test(error.message)) + return; + console.warn(error.message); }); return; } await execa("kill", ["-9", pid.toString()]).catch((error) => { // process is already dead - if (!/No such process/.test(error.message)) throw error; + if (/No such process/.test(error.message)) return; + console.warn(error.message); }); }; @@ -34,8 +39,8 @@ export let killtree = async (pid: number) => { return new Promise((resolve, reject) => { let check = setInterval(() => { - let alive = pids.filter(isAlive); - if (alive.length === 0) { + pids = pids.filter(isAlive); + if (pids.length === 0) { clearInterval(check); resolve(); } From eccc18016347fd363275bb43b9414df54d29e21f Mon Sep 17 00:00:00 2001 From: Matt Brophy Date: Thu, 6 Jul 2023 11:28:12 -0400 Subject: [PATCH 3/8] Avoid re-prefetching stylesheets for active routes during a revalidation (#6679) --- .changeset/stylesheet-re-prefetch.md | 5 ++ integration/prefetch-test.ts | 92 ++++++++++++++++++++++++++++ packages/remix-react/links.ts | 7 ++- 3 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 .changeset/stylesheet-re-prefetch.md diff --git a/.changeset/stylesheet-re-prefetch.md b/.changeset/stylesheet-re-prefetch.md new file mode 100644 index 00000000000..3310ddc8f28 --- /dev/null +++ b/.changeset/stylesheet-re-prefetch.md @@ -0,0 +1,5 @@ +--- +"@remix-run/react": patch +--- + +Avoid re-prefetching stylesheets for active routes during a revalidation diff --git a/integration/prefetch-test.ts b/integration/prefetch-test.ts index c07b00abc6e..a70c714e10c 100644 --- a/integration/prefetch-test.ts +++ b/integration/prefetch-test.ts @@ -342,3 +342,95 @@ test.describe("prefetch=viewport", () => { await expect(page.locator("div link")).toHaveCount(0); }); }); + +test.describe("other scenarios", () => { + let fixture: Fixture; + let appFixture: AppFixture; + + test.afterAll(() => { + appFixture?.close(); + }); + + test("does not add prefetch links for stylesheets already in the DOM (active routes)", async ({ + page, + }) => { + fixture = await createFixture({ + config: { + future: { v2_routeConvention: true }, + }, + files: { + "app/root.jsx": js` + import { Links, Meta, Scripts, useFetcher } from "@remix-run/react"; + import globalCss from "./global.css"; + + export function links() { + return [{ rel: "stylesheet", href: globalCss }]; + } + + export async function action() { + return null; + } + + export async function loader() { + return null; + } + + export default function Root() { + let fetcher = useFetcher(); + + return ( + + + + + + + +

{fetcher.state}

+ + + + ); + } + `, + + "app/global.css": ` + body { + background-color: black; + color: white; + } + `, + + "app/routes/_index.jsx": js` + export default function() { + return

Index

; + } + `, + }, + }); + appFixture = await createAppFixture(fixture); + let requests: { type: string; url: string }[] = []; + + page.on("request", (req) => { + requests.push({ + type: req.resourceType(), + url: req.url(), + }); + }); + + let app = new PlaywrightFixture(appFixture, page); + await app.goto("/"); + await page.click("#submit-fetcher"); + await page.waitForSelector("#fetcher-state--idle"); + // We should not send a second request for this root stylesheet that's + // already been rendered in the DOM + let stylesheets = requests.filter( + (r) => r.type === "stylesheet" && /\/global-[a-z0-9]+\.css/i.test(r.url) + ); + expect(stylesheets.length).toBe(1); + }); +}); diff --git a/packages/remix-react/links.ts b/packages/remix-react/links.ts index 6c070d5746d..1edcd6c5841 100644 --- a/packages/remix-react/links.ts +++ b/packages/remix-react/links.ts @@ -254,9 +254,12 @@ export async function prefetchStyleLinks( } } - // don't block for non-matching media queries + // don't block for non-matching media queries, or for stylesheets that are + // already in the DOM (active route revalidations) let matchingLinks = styleLinks.filter( - (link) => !link.media || window.matchMedia(link.media).matches + (link) => + (!link.media || window.matchMedia(link.media).matches) && + !document.querySelector(`link[rel="stylesheet"][href="${link.href}"]`) ); await Promise.all(matchingLinks.map(prefetchStyleLink)); From 497103f8b9b55f9ed9d0e434a25f178627089882 Mon Sep 17 00:00:00 2001 From: Logan McAnsh Date: Mon, 10 Jul 2023 14:24:32 -0400 Subject: [PATCH 4/8] test: we switched to playwright but didnt update all references (#6245) Co-authored-by: Matt Brophy --- integration/abort-signal-test.ts | 2 +- integration/bug-report-test.ts | 2 +- integration/defer-test.ts | 4 ++-- integration/scroll-test.ts | 2 +- integration/set-cookie-revalidation-test.ts | 2 +- packages/remix-architect/__tests__/server-test.ts | 2 +- packages/remix-express/__tests__/server-test.ts | 2 +- packages/remix-netlify/__tests__/server-test.ts | 2 +- packages/remix-vercel/__tests__/server-test.ts | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration/abort-signal-test.ts b/integration/abort-signal-test.ts index db047de7ab0..df4b5c38b1b 100644 --- a/integration/abort-signal-test.ts +++ b/integration/abort-signal-test.ts @@ -44,7 +44,7 @@ test.beforeAll(async () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); diff --git a/integration/bug-report-test.ts b/integration/bug-report-test.ts index ec2fa93a31c..0d6fe2c890a 100644 --- a/integration/bug-report-test.ts +++ b/integration/bug-report-test.ts @@ -84,7 +84,7 @@ test.beforeAll(async () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); diff --git a/integration/defer-test.ts b/integration/defer-test.ts index 267ffba5b49..8fa01a49e43 100644 --- a/integration/defer-test.ts +++ b/integration/defer-test.ts @@ -561,7 +561,7 @@ test.describe("non-aborted", () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); @@ -1244,7 +1244,7 @@ test.describe("aborted", () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); diff --git a/integration/scroll-test.ts b/integration/scroll-test.ts index 70d1a4eec0c..f4c77b25ab5 100644 --- a/integration/scroll-test.ts +++ b/integration/scroll-test.ts @@ -46,7 +46,7 @@ test.beforeAll(async () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); diff --git a/integration/set-cookie-revalidation-test.ts b/integration/set-cookie-revalidation-test.ts index 017bcb6a3a1..8a87d0edee7 100644 --- a/integration/set-cookie-revalidation-test.ts +++ b/integration/set-cookie-revalidation-test.ts @@ -114,7 +114,7 @@ test.beforeAll(async () => { }, }); - // This creates an interactive app using puppeteer. + // This creates an interactive app using playwright. appFixture = await createAppFixture(fixture); }); diff --git a/packages/remix-architect/__tests__/server-test.ts b/packages/remix-architect/__tests__/server-test.ts index e0e8643b3df..38348e559db 100644 --- a/packages/remix-architect/__tests__/server-test.ts +++ b/packages/remix-architect/__tests__/server-test.ts @@ -15,7 +15,7 @@ import { } from "../server"; // We don't want to test that the remix server works here (that's what the -// puppetteer tests do), we just want to test the architect adapter +// playwright tests do), we just want to test the architect adapter jest.mock("@remix-run/node", () => { let original = jest.requireActual("@remix-run/node"); return { diff --git a/packages/remix-express/__tests__/server-test.ts b/packages/remix-express/__tests__/server-test.ts index 964c89a251b..2f50cd5e3b6 100644 --- a/packages/remix-express/__tests__/server-test.ts +++ b/packages/remix-express/__tests__/server-test.ts @@ -14,7 +14,7 @@ import { } from "../server"; // We don't want to test that the remix server works here (that's what the -// puppetteer tests do), we just want to test the express adapter +// playwright tests do), we just want to test the express adapter jest.mock("@remix-run/node", () => { let original = jest.requireActual("@remix-run/node"); return { diff --git a/packages/remix-netlify/__tests__/server-test.ts b/packages/remix-netlify/__tests__/server-test.ts index 0b643a81410..1236e1181dc 100644 --- a/packages/remix-netlify/__tests__/server-test.ts +++ b/packages/remix-netlify/__tests__/server-test.ts @@ -15,7 +15,7 @@ import { } from "../server"; // We don't want to test that the remix server works here (that's what the -// puppetteer tests do), we just want to test the netlify adapter +// playwright tests do), we just want to test the netlify adapter jest.mock("@remix-run/node", () => { let original = jest.requireActual("@remix-run/node"); return { diff --git a/packages/remix-vercel/__tests__/server-test.ts b/packages/remix-vercel/__tests__/server-test.ts index c9191d2684a..852428d397e 100644 --- a/packages/remix-vercel/__tests__/server-test.ts +++ b/packages/remix-vercel/__tests__/server-test.ts @@ -15,7 +15,7 @@ import { } from "../server"; // We don't want to test that the remix server works here (that's what the -// Puppeteer tests do), we just want to test the Vercel adapter +// playwright tests do), we just want to test the Vercel adapter jest.mock("@remix-run/node", () => { let original = jest.requireActual("@remix-run/node"); return { From 8ac053ab0b2286dce1ebaa1ea85aa23b386eaf2e Mon Sep 17 00:00:00 2001 From: nopekun <51075690+toufiqnuur@users.noreply.github.com> Date: Tue, 11 Jul 2023 02:01:10 +0700 Subject: [PATCH 5/8] Update docs cloudflare-pages accessing env variable (#6730) Co-authored-by: Matt Brophy --- contributors.yml | 1 + docs/guides/envvars.md | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/contributors.yml b/contributors.yml index ecb1d1a4cca..86aebae0e6b 100644 --- a/contributors.yml +++ b/contributors.yml @@ -554,4 +554,5 @@ - amir-ziaei - mrkhosravian - tanerijun +- toufiqnuur - ally1002 diff --git a/docs/guides/envvars.md b/docs/guides/envvars.md index 52bd7344aa1..0e80c598292 100644 --- a/docs/guides/envvars.md +++ b/docs/guides/envvars.md @@ -48,11 +48,24 @@ export async function loader() { If you're using the `@remix-run/cloudflare-pages` adapter, env variables work a little differently. Since Cloudflare Pages are powered by Functions, you'll need to define your local environment variables in the [`.dev.vars`][dev-vars] file. It has the same syntax as `.env` example file mentioned above. -Then, in your `loader` functions, you can access environment variables directly on `context`: +Then, you can pass those through via `getLoadContext` in your server file: + +```ts +export const onRequest = createPagesFunctionHandler({ + build, + getLoadContext(context) { + // Hand-off Cloudflare ENV vars to the Remix `context` object + return { env: context.env }; + }, + mode: process.env.NODE_ENV, +}); +``` + +And they'll be available via Remix's `context` in your `loader`/`action` functions: ```tsx export const loader = async ({ context }: LoaderArgs) => { - console.log(context.SOME_SECRET); + console.log(context.env.SOME_SECRET); }; ``` From b6d26effa7bff564afdf66c369b88d9f771ea0bd Mon Sep 17 00:00:00 2001 From: Logan McAnsh Date: Tue, 11 Jul 2023 10:09:40 -0400 Subject: [PATCH 6/8] chore: update how `REMIX_LOCAL_BUILD_DIRECTORY` is resolved (#6150) Signed-off-by: Logan McAnsh Co-authored-by: Pedro Cattori Co-authored-by: Matt Brophy --- DEVELOPMENT.md | 4 ++-- packages/remix/rollup.config.js | 2 +- rollup.utils.js | 11 ++++------- scripts/copy-build-to-dist.mjs | 6 +++--- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 3f5bcef3c4d..013e074eaef 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -107,7 +107,7 @@ By default, the Remix `rollup` build will strip any `console.debug` calls to avo REMIX_DEBUG=true yarn watch ``` -**`REMIX_LOCAL_BUILD_DIRECTORY`** +**`LOCAL_BUILD_DIRECTORY`** When developing Remix locally, you often need to go beyond unit/integration tests and test your changes in a local Remix application. The easiest way to do this is to run your local Remix build and use this environment variable to direct `rollup` to write the output files directly into the local Remix application's `node_modules` folder. Then you just need to restart your local Remix application server to pick up the changes. @@ -118,7 +118,7 @@ cd my-remix-app npm run dev # Tab 2 - remix repository -REMIX_LOCAL_BUILD_DIRECTORY=../my-remix-app yarn watch +LOCAL_BUILD_DIRECTORY=../my-remix-app yarn watch ``` Now - any time you make changes in the Remix repository, they will be written out to the appropriate locations in `../my-remix-app/node_modules` and you can restart the `npm run dev` command to pick them up 🎉. diff --git a/packages/remix/rollup.config.js b/packages/remix/rollup.config.js index 1948486d0c3..42c878681eb 100644 --- a/packages/remix/rollup.config.js +++ b/packages/remix/rollup.config.js @@ -13,7 +13,7 @@ let { name: packageName, version } = require("./package.json"); module.exports = function rollup() { // Don't blow away remix magic exports on local builds, since they've // already been configured by postinstall - if (process.env.REMIX_LOCAL_BUILD_DIRECTORY) { + if (process.env.LOCAL_BUILD_DIRECTORY) { return []; } diff --git a/rollup.utils.js b/rollup.utils.js index 3da8600e857..6f36b967720 100644 --- a/rollup.utils.js +++ b/rollup.utils.js @@ -9,16 +9,13 @@ const path = require("path"); const REPO_ROOT_DIR = __dirname; let activeOutputDir = "build"; -if (process.env.REMIX_LOCAL_BUILD_DIRECTORY) { - let appDir = path.join( - process.cwd(), - process.env.REMIX_LOCAL_BUILD_DIRECTORY - ); +if (process.env.LOCAL_BUILD_DIRECTORY) { + let appDir = path.resolve(process.env.LOCAL_BUILD_DIRECTORY); try { fse.readdirSync(path.join(appDir, "node_modules")); } catch { console.error( - "Oops! You pointed REMIX_LOCAL_BUILD_DIRECTORY to a directory that " + + "Oops! You pointed LOCAL_BUILD_DIRECTORY to a directory that " + "does not have a node_modules/ folder. Please `npm install` in that " + "directory and try again." ); @@ -124,7 +121,7 @@ function copyToPlaygrounds() { await triggerLiveReload(playgroundDir); } } else { - // Otherwise, trigger live reload on our REMIX_LOCAL_BUILD_DIRECTORY folder + // Otherwise, trigger live reload on our LOCAL_BUILD_DIRECTORY folder await triggerLiveReload(activeOutputDir); } }, diff --git a/scripts/copy-build-to-dist.mjs b/scripts/copy-build-to-dist.mjs index 4b9e4cb274d..c9602b6f39e 100644 --- a/scripts/copy-build-to-dist.mjs +++ b/scripts/copy-build-to-dist.mjs @@ -7,13 +7,13 @@ const PACKAGES_PATH = path.join(ROOT_DIR, "packages"); const DEFAULT_BUILD_PATH = path.join(ROOT_DIR, "build"); let activeOutputDir = DEFAULT_BUILD_PATH; -if (process.env.REMIX_LOCAL_BUILD_DIRECTORY) { - let appDir = path.join(ROOT_DIR, process.env.REMIX_LOCAL_BUILD_DIRECTORY); +if (process.env.LOCAL_BUILD_DIRECTORY) { + let appDir = path.resolve(process.env.LOCAL_BUILD_DIRECTORY); try { fse.readdirSync(path.join(appDir, "node_modules")); } catch { console.error( - "Oops! You pointed `REMIX_LOCAL_BUILD_DIRECTORY` to a directory that " + + "Oops! You pointed `LOCAL_BUILD_DIRECTORY` to a directory that " + "does not have a `node_modules` folder. Please `npm install` in that " + "directory and try again." ); From 27deda59f2fa3ebb00dfb46391286ce80e06b104 Mon Sep 17 00:00:00 2001 From: Alem Tuzlak Date: Tue, 11 Jul 2023 16:46:59 +0200 Subject: [PATCH 7/8] fix(remix-react): fix `fetcher.formEncType` (#6810) Co-authored-by: Matt Brophy --- .changeset/chatty-pears-float.md | 5 +++++ contributors.yml | 1 + packages/remix-react/transition.ts | 10 +++++----- 3 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 .changeset/chatty-pears-float.md diff --git a/.changeset/chatty-pears-float.md b/.changeset/chatty-pears-float.md new file mode 100644 index 00000000000..a51f222e43a --- /dev/null +++ b/.changeset/chatty-pears-float.md @@ -0,0 +1,5 @@ +--- +"@remix-run/react": patch +--- + +Narrowed the type of `fetcher.formEncType` to use `FormEncType` from `react-router-dom` instead of `string` diff --git a/contributors.yml b/contributors.yml index 86aebae0e6b..854f09503ad 100644 --- a/contributors.yml +++ b/contributors.yml @@ -556,3 +556,4 @@ - tanerijun - toufiqnuur - ally1002 +- AlemTuzlak \ No newline at end of file diff --git a/packages/remix-react/transition.ts b/packages/remix-react/transition.ts index ff937257562..ae12b614c9d 100644 --- a/packages/remix-react/transition.ts +++ b/packages/remix-react/transition.ts @@ -1,4 +1,4 @@ -import type { Location } from "react-router-dom"; +import type { Location, FormEncType } from "react-router-dom"; export interface Submission { action: string; @@ -137,7 +137,7 @@ export type FetcherStates = { type: "actionSubmission"; formMethod: FetcherActionSubmission["method"]; formAction: string; - formEncType: string; + formEncType: FormEncType; submission: FetcherActionSubmission; data: TData | undefined; } & FetcherSubmissionDataTypes; @@ -146,7 +146,7 @@ export type FetcherStates = { type: "loaderSubmission"; formMethod: FetcherLoaderSubmission["method"]; formAction: string; - formEncType: string; + formEncType: FormEncType; submission: FetcherLoaderSubmission; data: TData | undefined; } & FetcherSubmissionDataTypes; @@ -155,7 +155,7 @@ export type FetcherStates = { type: "actionReload"; formMethod: FetcherActionSubmission["method"]; formAction: string; - formEncType: string; + formEncType: FormEncType; submission: FetcherActionSubmission; data: TData; } & FetcherSubmissionDataTypes; @@ -164,7 +164,7 @@ export type FetcherStates = { type: "actionRedirect"; formMethod: FetcherActionSubmission["method"]; formAction: string; - formEncType: string; + formEncType: FormEncType; submission: FetcherActionSubmission; data: undefined; } & FetcherSubmissionDataTypes; From 79f9ff3254b0c35ee02d03fa0f301c8e2538e882 Mon Sep 17 00:00:00 2001 From: Remix Run Bot Date: Tue, 11 Jul 2023 14:48:54 +0000 Subject: [PATCH 8/8] chore: format --- contributors.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributors.yml b/contributors.yml index 854f09503ad..0b76eb9c311 100644 --- a/contributors.yml +++ b/contributors.yml @@ -556,4 +556,4 @@ - tanerijun - toufiqnuur - ally1002 -- AlemTuzlak \ No newline at end of file +- AlemTuzlak