diff --git a/.changeset/angry-poets-accept.md b/.changeset/angry-poets-accept.md deleted file mode 100644 index 0454cf765d6..00000000000 --- a/.changeset/angry-poets-accept.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@remix-run/serve": patch ---- - -Use node `fileURLToPath` to convert source map URL to path diff --git a/.changeset/big-cooks-confess.md b/.changeset/big-cooks-confess.md deleted file mode 100644 index ab6fd78c460..00000000000 --- a/.changeset/big-cooks-confess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@remix-run/server-runtime": patch ---- - -Add optional `error` to `ServerRuntimeMetaArgs` type to align with `MetaArgs` diff --git a/.changeset/breezy-grapes-roll.md b/.changeset/breezy-grapes-roll.md deleted file mode 100644 index 3f64539b86a..00000000000 --- a/.changeset/breezy-grapes-roll.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Vite: Error messages when `.server` files are referenced by client - -- Previously, referencing a `.server` module from client code resulted in an error message like: - - `The requested module '/app/models/answer.server.ts' does not provide an export named 'isDateType'` -- This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build -- Now, Remix explicitly fails at compile time when a `.server` module is referenced from client code and includes dedicated error messages depending on whether the import occurs in a route or a non-route module -- The error messages also include links to relevant documentation diff --git a/.changeset/breezy-walls-scream.md b/.changeset/breezy-walls-scream.md deleted file mode 100644 index 1b1510d22a1..00000000000 --- a/.changeset/breezy-walls-scream.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Remove `unstable_viteServerBuildModuleId` in favor of manually referencing virtual module name `"virtual:remix/server-build"`. - -**This is a breaking change for projects using the unstable Vite plugin with a custom server.** - -This change was made to avoid issues where `@remix-run/dev` could be inadvertently required in your server's production dependencies. - -Instead, you should manually write the virtual module name `"virtual:remix/server-build"` when calling `ssrLoadModule` in development. - -```diff --import { unstable_viteServerBuildModuleId } from "@remix-run/dev"; - -// ... - -app.all( - "*", - createRequestHandler({ - build: vite -- ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId) -+ ? () => vite.ssrLoadModule("virtual:remix/server-build") - : await import("./build/server/index.js"), - }) -); -``` diff --git a/.changeset/create-remix-fetch.md b/.changeset/create-remix-fetch.md deleted file mode 100644 index f4ac92e94dc..00000000000 --- a/.changeset/create-remix-fetch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"create-remix": patch ---- - -Switch to using `@remix-run/web-fetch` instead of `node-fetch` inside the `create-remix` CLI diff --git a/.changeset/poor-eels-bow.md b/.changeset/poor-eels-bow.md deleted file mode 100644 index 0eec188583f..00000000000 --- a/.changeset/poor-eels-bow.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Add `vite:dev` and `vite:build` commands to the Remix CLI. - -In order to handle upcoming Remix features where your plugin options can impact the number of Vite builds required, you should now run your Vite `dev` and `build` processes via the Remix CLI. - -```diff -{ - "scripts": { -- "dev": "vite dev", -- "build": "vite build && vite build --ssr" -+ "dev": "remix vite:dev", -+ "build": "remix vite:build" - } -} -``` diff --git a/.changeset/rude-keys-heal.md b/.changeset/rude-keys-heal.md deleted file mode 100644 index 325ccf4297e..00000000000 --- a/.changeset/rude-keys-heal.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Vite: Preserve names for exports from `.client` modules - -Unlike `.server` modules, the main idea is not to prevent code from leaking into the server build -since the client build is already public. Rather, the goal is to isolate the SSR render from client-only code. -Routes need to import code from `.client` modules without compilation failing and then rely on runtime checks -or otherwise ensure that execution only happens within a client-only context (e.g. event handlers, `useEffect`). - -Replacing `.client` modules with empty modules would cause the build to fail as ESM named imports are statically analyzed. -So instead, we preserve the named export but replace each exported value with `undefined`. -That way, the import is valid at build time and standard runtime checks can be used to determine if the -code is running on the server or client. diff --git a/.changeset/server-loader-error.md b/.changeset/server-loader-error.md deleted file mode 100644 index c7961752b66..00000000000 --- a/.changeset/server-loader-error.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@remix-run/react": patch ---- - -Propagate server `loader` errors through `serverLoader` in hydrating `clientLoader`'s diff --git a/.changeset/seven-bees-thank.md b/.changeset/seven-bees-thank.md deleted file mode 100644 index 830436dcbfd..00000000000 --- a/.changeset/seven-bees-thank.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Disable watch mode in Vite child compiler during build diff --git a/.changeset/sour-snakes-melt.md b/.changeset/sour-snakes-melt.md deleted file mode 100644 index 8a238697707..00000000000 --- a/.changeset/sour-snakes-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@remix-run/dev": patch ---- - -Vite: Show warning when source maps are enabled in production build diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index 38bdf6cfb41..a1d7f33f627 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: 🥺 Handle Ghosting - uses: actions/stale@v8 + uses: actions/stale@v9 with: days-before-close: 10 close-issue-message: > diff --git a/CHANGELOG.md b/CHANGELOG.md index 40900cfc0b3..4d3ff304dd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,46 +13,50 @@ We manage release notes in this file instead of the paginated Github Releases Pa Table of Contents - [Remix Releases](#remix-releases) + - [v2.4.1](#v241) + - [Patch Changes](#patch-changes) + - [Updated Dependencies](#updated-dependencies) + - [Changes by Package](#changes-by-package) - [v2.4.0](#v240) - [What's Changed](#whats-changed) - [Client Data](#client-data) - [`future.v3_relativeSplatPath`](#futurev3_relativesplatpath) - [Vite Updates (Unstable)](#vite-updates-unstable) - [Minor Changes](#minor-changes) - - [Patch Changes](#patch-changes) - - [Updated Dependencies](#updated-dependencies) - - [Changes by Package](#changes-by-package) - - [v2.3.1](#v231) - [Patch Changes](#patch-changes-1) - [Updated Dependencies](#updated-dependencies-1) - [Changes by Package](#changes-by-package-1) + - [v2.3.1](#v231) + - [Patch Changes](#patch-changes-2) + - [Updated Dependencies](#updated-dependencies-2) + - [Changes by Package](#changes-by-package-2) - [v2.3.0](#v230) - [What's Changed](#whats-changed-1) - [Stabilized `useBlocker`](#stabilized-useblocker) - [`unstable_flushSync` API](#unstable_flushsync-api) - [Minor Changes](#minor-changes-1) - - [Patch Changes](#patch-changes-2) - - [Updated Dependencies](#updated-dependencies-2) - - [Changes by Package](#changes-by-package-2) + - [Patch Changes](#patch-changes-3) + - [Updated Dependencies](#updated-dependencies-3) + - [Changes by Package](#changes-by-package-3) - [v2.2.0](#v220) - [What's Changed](#whats-changed-2) - [Vite!](#vite) - [New Fetcher APIs](#new-fetcher-apis) - [Persistence Future Flag](#persistence-future-flag) - [Minor Changes](#minor-changes-2) - - [Patch Changes](#patch-changes-3) - - [Updated Dependencies](#updated-dependencies-3) - - [Changes by Package](#changes-by-package-3) + - [Patch Changes](#patch-changes-4) + - [Updated Dependencies](#updated-dependencies-4) + - [Changes by Package](#changes-by-package-4) - [v2.1.0](#v210) - [What's Changed](#whats-changed-3) - [View Transitions](#view-transitions) - [Stable `createRemixStub`](#stable-createremixstub) - [Minor Changes](#minor-changes-3) - - [Patch Changes](#patch-changes-4) - - [Updated Dependencies](#updated-dependencies-4) - - [Changes by Package](#changes-by-package-4) - - [v2.0.1](#v201) - [Patch Changes](#patch-changes-5) + - [Updated Dependencies](#updated-dependencies-5) + - [Changes by Package](#changes-by-package-5) + - [v2.0.1](#v201) + - [Patch Changes](#patch-changes-6) - [Changes by Package 🔗](#changes-by-package-) - [v2.0.0](#v200) - [Breaking Changes](#breaking-changes) @@ -64,8 +68,8 @@ We manage release notes in this file instead of the paginated Github Releases Pa - [Breaking Type Changes](#breaking-type-changes) - [New Features](#new-features) - [Other Notable Changes](#other-notable-changes) - - [Updated Dependencies](#updated-dependencies-5) - - [Changes by Package](#changes-by-package-5) + - [Updated Dependencies](#updated-dependencies-6) + - [Changes by Package](#changes-by-package-6) @@ -111,6 +115,93 @@ To add a new release, copy from this template: --> +## v2.4.1 + +### Patch Changes + +- `@remix-run/dev`: Vite - Remove `unstable_viteServerBuildModuleId` in favor of manually referencing virtual module name `"virtual:remix/server-build"` ([#8264](https://github.com/remix-run/remix/pull/8264)) + + - **This is a breaking change for projects using the unstable Vite plugin with a custom server.** + - This change was made to avoid issues where `@remix-run/dev` could be inadvertently required in your server's production dependencies. + - Instead, you should manually write the virtual module name `"virtual:remix/server-build"` when calling `ssrLoadModule` in development. + + ```diff + -import { unstable_viteServerBuildModuleId } from "@remix-run/dev"; + + // ... + + app.all( + "*", + createRequestHandler({ + build: vite + - ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId) + + ? () => vite.ssrLoadModule("virtual:remix/server-build") + : await import("./build/server/index.js"), + }) + ); + ``` + +- `@remix-run/dev`: Vite - Add `vite:dev` and `vite:build` commands to the Remix CLI ([#8211](https://github.com/remix-run/remix/pull/8211)) + + - In order to handle upcoming Remix features where your plugin options can impact the number of Vite builds required, you should now run your Vite `dev` and `build` processes via the Remix CLI. + + ```diff + { + "scripts": { + - "dev": "vite dev", + - "build": "vite build && vite build --ssr" + + "dev": "remix vite:dev", + + "build": "remix vite:build" + } + } + ``` + +- `@remix-run/dev`: Vite - Error messages when `.server` files are referenced by client ([#8267](https://github.com/remix-run/remix/pull/8267)) + - Previously, referencing a `.server` module from client code resulted in an error message like: + - `The requested module '/app/models/answer.server.ts' does not provide an export named 'isDateType'` + - This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build + - Now, Remix explicitly fails at compile time when a `.server` module is referenced from client code and includes dedicated error messages depending on whether the import occurs in a route or a non-route module + - The error messages also include links to relevant documentation +- `@remix-run/dev`: Vite - Preserve names for exports from `.client` modules ([#8200](https://github.com/remix-run/remix/pull/8200)) + - Unlike `.server` modules, the main idea is not to prevent code from leaking into the server build since the client build is already public + - Rather, the goal is to isolate the SSR render from client-only code + - Routes need to import code from `.client` modules without compilation failing and then rely on runtime checks or otherwise ensure that execution only happens within a client-only context (e.g. event handlers, `useEffect`) + - Replacing `.client` modules with empty modules would cause the build to fail as ESM named imports are statically analyzed + - So instead, we preserve the named export but replace each exported value with `undefined` + - That way, the import is valid at build time and standard runtime checks can be used to determine if the code is running on the server or client +- `@remix-run/dev`: Vite - Disable watch mode in Vite child compiler during build ([#8342](https://github.com/remix-run/remix/pull/8342)) +- `@remix-run/dev`: Vite - Show warning when source maps are enabled in production build ([#8222](https://github.com/remix-run/remix/pull/8222)) +- `@remix-run/react`: Propagate server `loader` errors through `serverLoader` in hydrating `clientLoader`'s ([#8304](https://github.com/remix-run/remix/pull/8304)) +- `@remix-run/react` Re-export `Response` helpers (`defer`/`json`/`redirect`/`redirectDocument`) through `@remix-run/react` for use in `clientLoader`/`clientAction` ([#8351](https://github.com/remix-run/remix/pull/8351)) +- `@remix-run/server-runtime`: Add optional `error` to `ServerRuntimeMetaArgs` type to align with `MetaArgs` ([#8238](https://github.com/remix-run/remix/pull/8238)) +- `create-remix`: Switch to using `@remix-run/web-fetch` instead of `node-fetch` inside the `create-remix` CLI ([#7345](https://github.com/remix-run/remix/pull/7345)) +- `remix-serve`: Use node `fileURLToPath` to convert source map URL to path ([#8321](https://github.com/remix-run/remix/pull/8321)) + +### Updated Dependencies + +- [`react-router-dom@6.21.1`](https://github.com/remix-run/react-router/releases/tag/react-router%406.21.1) +- [`@remix-run/router@1.14.1`](https://github.com/remix-run/react-router/blob/main/packages/router/CHANGELOG.md#1141) + +### Changes by Package + +- [`create-remix`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/create-remix/CHANGELOG.md#241) +- [`@remix-run/architect`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-architect/CHANGELOG.md#241) +- [`@remix-run/cloudflare`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare/CHANGELOG.md#241) +- [`@remix-run/cloudflare-pages`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare-pages/CHANGELOG.md#241) +- [`@remix-run/cloudflare-workers`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-cloudflare-workers/CHANGELOG.md#241) +- [`@remix-run/css-bundle`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-css-bundle/CHANGELOG.md#241) +- [`@remix-run/deno`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-deno/CHANGELOG.md#241) +- [`@remix-run/dev`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-dev/CHANGELOG.md#241) +- [`@remix-run/eslint-config`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-eslint-config/CHANGELOG.md#241) +- [`@remix-run/express`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-express/CHANGELOG.md#241) +- [`@remix-run/node`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-node/CHANGELOG.md#241) +- [`@remix-run/react`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-react/CHANGELOG.md#241) +- [`@remix-run/serve`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-serve/CHANGELOG.md#241) +- [`@remix-run/server-runtime`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-server-runtime/CHANGELOG.md#241) +- [`@remix-run/testing`](https://github.com/remix-run/remix/blob/remix%402.4.1/packages/remix-testing/CHANGELOG.md#241) + +**Full Changelog**: [`v2.4.0...v2.4.1`](https://github.com/remix-run/remix/compare/remix@2.4.0...remix@2.4.1) + ## v2.4.0 ### What's Changed @@ -122,7 +213,7 @@ We're excited to land the [Client Data RFC](https://github.com/remix-run/remix/d - [Client Data Guide](https://remix.run/guides/client-data) - [`clientLoader`](https://remix.run/route/client-loader) - [`HydrateFallback`](https://remix.run/route/hydrate-fallback) -- [`clientAction`](https://remix.run/route/client-loader) +- [`clientAction`](https://remix.run/route/client-action) While we still recommend server loaders/actions for the majority of your data needs in a Remix app - these provide some levers you can pull for more advanced use-cases such as: diff --git a/contributors.yml b/contributors.yml index 14b80999999..6b8851535a3 100644 --- a/contributors.yml +++ b/contributors.yml @@ -325,6 +325,7 @@ - leon - leothorp - leovander +- leoweigand - levippaul - LewisArdern - lifeiscontent @@ -434,6 +435,7 @@ - omamazainab - oott123 - orballo +- ovi-ispas - pacexy - pandaiolo - panteliselef @@ -491,6 +493,7 @@ - sandulat - sandstone991 - sarahse +- sathvik-k - sbernheim4 - schpet - scottybrown @@ -624,3 +627,5 @@ - alexanderson1993 - signed - VHall1 +- souredoutlook +- tmcw diff --git a/docs/discussion/server-vs-client.md b/docs/discussion/server-vs-client.md index feb02d5a577..d1700db8464 100644 --- a/docs/discussion/server-vs-client.md +++ b/docs/discussion/server-vs-client.md @@ -62,6 +62,7 @@ export default function Component() { export async function action({ request, }: ActionFunctionArgs) { + const formData = await request.formData(); const user = await getUser(request); await updateUser(user.id, { diff --git a/docs/file-conventions/remix-config.md b/docs/file-conventions/remix-config.md index 72545db61f1..ca47f4f87a0 100644 --- a/docs/file-conventions/remix-config.md +++ b/docs/file-conventions/remix-config.md @@ -272,7 +272,7 @@ There are a few conventions that Remix uses you should be aware of. [esbuild_plugins_node_modules_polyfill]: https://npm.im/esbuild-plugins-node-modules-polyfill [browser-node-builtins-polyfill]: #browsernodebuiltinspolyfill [server-node-builtins-polyfill]: #servernodebuiltinspolyfill -[future-flags]: ../start/future-flags.md +[future-flags]: ../start/future-flags [fetcherpersist-rfc]: https://github.com/remix-run/remix/discussions/7698 [use-fetchers]: ../hooks/use-fetchers [use-fetcher]: ../hooks/use-fetcher diff --git a/docs/future/vite.md b/docs/future/vite.md index ce4bb44fca4..e571bd3cb5a 100644 --- a/docs/future/vite.md +++ b/docs/future/vite.md @@ -304,7 +304,7 @@ If you prefer, you can instead author your custom server in TypeScript. You could then use tools like [`tsx`][tsx] or [`tsm`][tsm] to run your custom server: ```shellscript nonumber -tsx ./server.tsx +tsx ./server.ts node --loader tsm ./server.ts ``` @@ -324,8 +324,8 @@ For example, to update the Dockerfile from the [Blues Stack][blues-stack]: ```diff filename=Dockerfile -COPY --from=build /myapp/build /myapp/build -COPY --from=build /myapp/public /myapp/public -+COPY --from=build /myapp/server/build /myapp/server/build -+COPY --from=build /myapp/client/build /myapp/client/build ++COPY --from=build /myapp/build/server /myapp/build/server ++COPY --from=build /myapp/build/client /myapp/build/client ``` #### Configure path aliases @@ -399,20 +399,24 @@ During development, [Vite injects imported CSS files into the page via JavaScrip This also means that in many cases you won't need the `links` function export anymore. -👉 **Convert CSS imports to side effects** +Since the order of your CSS is determined by its import order, you'll need to ensure that your CSS imports are in the same order as your `links` function. + +👉 **Convert CSS imports into side effects — in the same order they were in your `links` function!** ```diff filename=app/dashboard/route.tsx -// No need to export a links function anymore: - import type { LinksFunction } from "@remix-run/node"; // or cloudflare/deno - import dashboardStyles from "./dashboard.css?url"; +- import sharedStyles from "./shared.css?url"; ++ // ⚠️ NOTE: The import order has been updated ++ // to match the original `links` function! ++ import "./shared.css"; ++ import "./dashboard.css"; - export const links: LinksFunction = () => [ +- { rel: "stylesheet", href: sharedStyles }, - { rel: "stylesheet", href: dashboardStyles }, - ]; - -// Just import the CSS as a side effect: -+ import "./dashboard.css"; ``` While [Vite supports importing static asset URLs via an explicit `?url` query string][vite-url-imports], which in theory would match the behavior of the existing Remix compiler when used for CSS files, there is a [known Vite issue with `?url` for CSS imports][vite-css-url-issue]. This may be fixed in the future, but in the meantime you should exclusively use side effect imports for CSS. @@ -745,6 +749,47 @@ export default function SuperCool() {} export const mySuperCoolThing = () => {}; ``` +##### Full Stack components + +[Full stack components][fullstack-components] are components that are colocated in the same file as a resource route and exported for use in other routes. +They access data from a resource route by fetching that route's URL. + +Conceptually, it's tempting to think of full stack components as a new concept, +but as far as Remix is concerned, they are standard React components. +Looking closer, they only depend on the resource route's URL and the type for the corresponding `loader`. +That means they are shared components with _zero_ runtime dependencies on code from the resource route. +Organize them they way you would organize any shared component. + +For better intuition, consider a full stack component that needs to fetch data from multiple resource routes. +It doesn't belong to any particular resource route. + +👉 **Move full stack components alongside other shared components** + +```ts filename=app/components/hello.tsx +export function Hello() { + /* ... */ +} +``` + +👉 **Export the loader's type from the resource route** + +```diff filename=app/routes/api/hello.ts ++ export type Loader = typeof loader; +``` + +👉 **Replace `typeof loader` with `Loader` type** + +```diff filename=app/components/hello.tsx ++ import type { Loader } from "~/routes/api/hello"; + +export function Hello() { + // ... +- const data = useFetcher() ++ const data = useFetcher() + // ... +} +``` + ## Troubleshooting Check out the [known issues with the Remix Vite plugin on GitHub][issues-vite] before filing a new bug report! @@ -760,7 +805,7 @@ Vite supports both ESM and CJS dependencies, but sometimes you might still run i Usually, this is because a dependency is not properly configured to support ESM. And we don't blame them, its [really tricky to support both ESM and CJS properly][modernizing-packages-to-esm]. -You can check [_Are The Types Wrong_][arethetypeswrong] to see if the dependency giving you trouble might be misconfigured. +To diagnose if your one of dependencies is misconfigured, check [publint][publint] or [_Are The Types Wrong_][arethetypeswrong]. Additionally, you can use the [vite-plugin-cjs-interop plugin][vite-plugin-cjs-interop] smooth over issues with `default` exports for external CJS dependencies. Finally, you can also explicitly configure which dependencies to bundle into your server bundled @@ -888,9 +933,11 @@ We're definitely late to the Vite party, but we're excited to be here now! [sveltekit]: https://kit.svelte.dev/ [modernizing-packages-to-esm]: https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/ [arethetypeswrong]: https://arethetypeswrong.github.io/ +[publint]: https://publint.dev/ [vite-plugin-cjs-interop]: https://github.com/cyco130/vite-plugin-cjs-interop [ssr-no-external]: https://vitejs.dev/config/ssr-options.html#ssr-noexternal [server-dependencies-to-bundle]: https://remix.run/docs/en/main/file-conventions/remix-config#serverdependenciestobundle [blues-stack]: https://github.com/remix-run/blues-stack [global-node-polyfills]: ../other-api/node#polyfills [server-bundles]: ./server-bundles +[fullstack-components]: https://www.epicweb.dev/full-stack-components diff --git a/docs/guides/client-data.md b/docs/guides/client-data.md index ae4a99d3d79..88da8d4c856 100644 --- a/docs/guides/client-data.md +++ b/docs/guides/client-data.md @@ -23,7 +23,7 @@ When using Remix in a [BFF][bff] architecture, it may be advantageous to skip th 1. Load the data from server `loader` on the document load 2. Load the data from the `clientLoader` on all subsequent loads -In this scenario, we will _not_ call the `clientLoader` on hydration - and will only call it on subsequent navigations. +In this scenario, Remix will _not_ call the `clientLoader` on hydration - and will only call it on subsequent navigations. ```tsx lines=[8,15] import type { LoaderFunctionArgs } from "@remix-run/node"; @@ -51,7 +51,7 @@ Sometimes, you may want to leverage "Fullstack State" where some of your data co 1. Load the partial data from server `loader` on the document load 2. Export a [`HydrateFallback`][hydratefallback] component to render during SSR because we don't yet have a full set of data -3. Set `clientLoader.hydrate = true` to load the rest of the data on hydration +3. Set `clientLoader.hydrate = true`, this instructs Remix to call the clientLoader as part of initial document hydration 4. Combine the server data with the client data in `clientLoader` ```tsx lines=[8-10,23-24,27,30] @@ -101,6 +101,8 @@ You may want to mix and match data loading strategies in your application such t 1. Export a `loader` when you want to use server data 2. Export `clientLoader` and a `HydrateFallback` when you want to use client data +A route that only depends on a server loader looks like this: + ```tsx filename="app/routes/server-data-route.tsx import type { LoaderFunctionArgs } from "@remix-run/node"; import { json } from "@remix-run/node"; @@ -118,6 +120,8 @@ export default function Component() { } ``` +A route that only depends on a client loader looks like this. + ```tsx filename="app/routes/client-data-route.tsx import type { ClientLoaderFunctionArgs } from "@remix-run/react"; @@ -149,7 +153,7 @@ export default function Component() { ## Client Cache -Remix normally recommends using `Cache-Control` headers for caching of loader data, however you may want to use a more manual in-browser client-side cache (i.e., in-memory cache, `localStorage`). You can leverage a client-side cache to bypass certain calls to the server as follows: +You can leverage a client-side cache (memory, local storage, etc.) to bypass certain calls to the server as follows: 1. Load the data from server `loader` on the document load 2. Set `clientLoader.hydrate = true` to prime the cache diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md index 949eaec1911..cfd7720efd2 100644 --- a/docs/guides/typescript.md +++ b/docs/guides/typescript.md @@ -9,27 +9,28 @@ Remix seamlessly supports both JavaScript and TypeScript. If you name a file wit The Remix compiler will not do any type checking (it simply removes the types). If you want to do type checking, you'll want to use TypeScript's `tsc` CLI yourself. A common solution is to add a `typecheck` script to your package.json: -```json filename=package.json lines=[9] +```json filename=package.json lines=[10] { "name": "remix-app", "private": true, "sideEffects": false, "scripts": { "build": "remix build", - "dev": "remix dev", - "start": "remix-serve build/index.js", + "dev": "remix dev --manual", + "lint": "eslint --ignore-path .gitignore .", + "start": "remix-serve ./build/index.js", "typecheck": "tsc" }, "dependencies": { "@remix-run/node": "latest", "@remix-run/react": "latest", "@remix-run/serve": "latest", + "isbot": "^3.6.8", "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@remix-run/dev": "latest", - "@remix-run/eslint-config": "latest", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "eslint": "^8.23.1", diff --git a/docs/hooks/use-submit.md b/docs/hooks/use-submit.md index 0a5b7ba9fb4..bdee83e828b 100644 --- a/docs/hooks/use-submit.md +++ b/docs/hooks/use-submit.md @@ -46,13 +46,22 @@ Can be any of the following: ```tsx const formData = new FormData(); formData.append("myKey", "myValue"); -submit(formData); +submit(formData, { method: "post" }); ``` **Plain object that will be serialized as `FormData`** ```tsx -submit({ myKey: "myValue" }); +submit({ myKey: "myValue" }, { method: "post" }); +``` + +**Plain object that will be serialized as JSON** + +```tsx +submit( + { myKey: "myValue" }, + { method: "post", encType: "application/json" } +); ``` ### `options` @@ -61,7 +70,7 @@ Options for the submission, the same as [`
`][form-component] props. All op - **action**: The href to submit to. Default is the current route path. - **method**: The HTTP method to use like POST, default is GET. -- **encType**: The encoding type to use for the form submission: `application/x-www-form-urlencoded` or `multipart/form-data`. Default is `application/x-www-form-urlencoded`. +- **encType**: The encoding type to use for the form submission: `application/x-www-form-urlencoded`, `multipart/form-data`, `application/json`, or `text/plain`. Default is `application/x-www-form-urlencoded`. - **navigate**: Specify `false` to submit using a fetcher instead of performing a navigation - **fetcherKey**: The fetcher key to use when submitting using a fetcher via `navigate: false` - **preventScrollReset**: Prevents the scroll position from being reset to the top of the window when the data is submitted. Default is `false`. diff --git a/docs/other-api/create-remix.md b/docs/other-api/create-remix.md index a28937b30b6..ef7bafb18cd 100644 --- a/docs/other-api/create-remix.md +++ b/docs/other-api/create-remix.md @@ -50,6 +50,7 @@ A valid template can be: - a GitHub repo shorthand — `:username/:repo` or `:username/:repo/:directory` - the URL of a GitHub repo (or directory within it) — `https://github.com/:username/:repo` or `https://github.com/:username/:repo/tree/:branch/:directory` + - The branch name (`:branch`) cannot have a `/` when using this format since `create-remix` cannot unable to differentiate the branch name from the directory path - the URL of a remote tarball — `https://example.com/remix-template.tar.gz` - a local file path to a directory of files — `./path/to/remix-template` - a local file path to a tarball — `./path/to/remix-template.tar.gz` diff --git a/docs/start/tutorial.md b/docs/start/tutorial.md index 2b7f5de7fc5..49a0ada52ab 100644 --- a/docs/start/tutorial.md +++ b/docs/start/tutorial.md @@ -1004,7 +1004,7 @@ When a route has children, and you're at the parent route's path, the `` 👉 **Create an index route for the root route** -``` +```shellscript nonumber touch app/routes/_index.tsx ``` diff --git a/docs/start/v2.md b/docs/start/v2.md index 1eccc091557..ed70ff2060f 100644 --- a/docs/start/v2.md +++ b/docs/start/v2.md @@ -120,7 +120,7 @@ If you are using `v2_dev` config, you'll need to move it to the `dev` config fie You can keep using the old convention with `@remix-run/v1-route-convention` even after upgrading to v2 if you don't want to make the change right now (or ever, it's just a convention, and you can use whatever file organization you prefer). ```shellscript nonumber -npm i @remix-run/v1-route-convention +npm i -D @remix-run/v1-route-convention ``` ```js filename=remix.config.js @@ -708,7 +708,7 @@ been eliminated in v2 or with `v2_dev`. ## `devServerPort` -In your `remix.config.js`, rename `devServerPort` to `dev.port`. +In your `remix.config.js`, rename `devServerPort` to `future.v2_dev.port`. ```js bad filename=remix.config.js lines=[3] /** @type {import('@remix-run/dev').AppConfig} */ @@ -720,6 +720,7 @@ module.exports = { ```js filename=remix.config.js good lines=[3-7] /** @type {import('@remix-run/dev').AppConfig} */ module.exports = { + // While on v1.x, this is via a future flag future: { v2_dev: { port: 8002, @@ -728,6 +729,8 @@ module.exports = { }; ``` +Once you upgrade from v1 to v2, this flattens to a [root-level `dev` config][dev-after-upgrading]. + ## `serverBuildDirectory` In your `remix.config.js`, rename `serverBuildDirectory` to `serverBuildPath` and specify a module path, not a directory. @@ -1126,3 +1129,4 @@ Please see the [`serverModuleFormat`][server-module-format] section. [troubleshooting]: #troubleshooting [server-module-format]: #servermoduleformat [2-min-to-v2]: https://twitter.com/BrooksLybrand/status/1704265835546578989 +[dev-after-upgrading]: #after-upgrading-from-v1-to-v2 diff --git a/docs/utils/parse-multipart-form-data.md b/docs/utils/parse-multipart-form-data.md index 20c234584c0..e0018dcaff4 100644 --- a/docs/utils/parse-multipart-form-data.md +++ b/docs/utils/parse-multipart-form-data.md @@ -49,6 +49,8 @@ export default function AvatarUploadRoute() { } ``` +To read the contents of an uploaded file, use one of the methods it inherits from [the Blob API][the-blob-api]. For example, `.text()` asynchronously returns the text contents of the file, and `.arrayBuffer()` returns the binary contents. + ### `uploadHandler` The `uploadHandler` is the key to the whole thing. It's responsible for what happens to the multipart/form-data parts as they are being streamed from the client. You can save it to disk, store it in memory, or act as a proxy to send it somewhere else (like a file storage provider). @@ -61,3 +63,4 @@ Remix has two utilities to create `uploadHandler`s for you: These are fully featured utilities for handling fairly simple use cases. It's not recommended to load anything but quite small files into memory. Saving files to disk is a reasonable solution for many use cases. But if you want to upload the file to a file hosting provider, then you'll need to write your own. [the-browser-file-api]: https://developer.mozilla.org/en-US/docs/Web/API/File +[the-blob-api]: https://developer.mozilla.org/en-US/docs/Web/API/Blob diff --git a/docs/utils/sessions.md b/docs/utils/sessions.md index fb818ac2938..1bcad1ecf1d 100644 --- a/docs/utils/sessions.md +++ b/docs/utils/sessions.md @@ -293,6 +293,8 @@ const { getSession, commitSession, destroySession } = }); ``` +Note that other session implementations store a unique session ID in a cookie and use that ID to look up the session in the source of truth (in-memory, filesystem, DB, etc.). In a cookie session, the cookie _is_ the source of truth so there is no unique ID out of the box. If you need to track a unique ID in your cookie session you will need to add an ID value yourself via `session.set()`. + ## `createMemorySessionStorage` This storage keeps all the cookie information in your server's memory. diff --git a/packages/create-remix/CHANGELOG.md b/packages/create-remix/CHANGELOG.md index 9679e18c48a..ca735da4837 100644 --- a/packages/create-remix/CHANGELOG.md +++ b/packages/create-remix/CHANGELOG.md @@ -1,5 +1,11 @@ # `create-remix` +## 2.4.1 + +### Patch Changes + +- Switch to using `@remix-run/web-fetch` instead of `node-fetch` inside the `create-remix` CLI ([#7345](https://github.com/remix-run/remix/pull/7345)) + ## 2.4.0 No significant changes to this package were made in this release. [See the repo `CHANGELOG.md`](https://github.com/remix-run/remix/blob/main/CHANGELOG.md) for an overview of all changes in v2.4.0. diff --git a/packages/create-remix/package.json b/packages/create-remix/package.json index 33f191bb3b1..65a50192992 100644 --- a/packages/create-remix/package.json +++ b/packages/create-remix/package.json @@ -1,6 +1,6 @@ { "name": "create-remix", - "version": "2.4.0", + "version": "2.4.1", "description": "Create a new Remix app", "homepage": "https://remix.run", "bugs": { diff --git a/packages/remix-architect/CHANGELOG.md b/packages/remix-architect/CHANGELOG.md index d07bb1760cd..ce00b7d632a 100644 --- a/packages/remix-architect/CHANGELOG.md +++ b/packages/remix-architect/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/architect` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/node@2.4.1` + ## 2.4.0 ### Patch Changes diff --git a/packages/remix-architect/package.json b/packages/remix-architect/package.json index aa521c97692..e41f7d275ef 100644 --- a/packages/remix-architect/package.json +++ b/packages/remix-architect/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/architect", - "version": "2.4.0", + "version": "2.4.1", "description": "Architect server request handler for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -15,7 +15,7 @@ "typings": "dist/index.d.ts", "dependencies": { "@architect/functions": "^5.2.0", - "@remix-run/node": "2.4.0", + "@remix-run/node": "2.4.1", "@types/aws-lambda": "^8.10.82" }, "devDependencies": { diff --git a/packages/remix-cloudflare-pages/CHANGELOG.md b/packages/remix-cloudflare-pages/CHANGELOG.md index f95c0bfbf22..a25360d66d2 100644 --- a/packages/remix-cloudflare-pages/CHANGELOG.md +++ b/packages/remix-cloudflare-pages/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/cloudflare-pages` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/cloudflare@2.4.1` + ## 2.4.0 ### Patch Changes diff --git a/packages/remix-cloudflare-pages/package.json b/packages/remix-cloudflare-pages/package.json index 65dfeee446a..ded2daac50b 100644 --- a/packages/remix-cloudflare-pages/package.json +++ b/packages/remix-cloudflare-pages/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/cloudflare-pages", - "version": "2.4.0", + "version": "2.4.1", "description": "Cloudflare Pages request handler for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -15,7 +15,7 @@ "typings": "dist/index.d.ts", "module": "dist/esm/index.js", "dependencies": { - "@remix-run/cloudflare": "2.4.0" + "@remix-run/cloudflare": "2.4.1" }, "devDependencies": { "@cloudflare/workers-types": "^4.20230518.0", diff --git a/packages/remix-cloudflare-workers/CHANGELOG.md b/packages/remix-cloudflare-workers/CHANGELOG.md index aab71de08e7..308b56c1b31 100644 --- a/packages/remix-cloudflare-workers/CHANGELOG.md +++ b/packages/remix-cloudflare-workers/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/cloudflare-workers` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/cloudflare@2.4.1` + ## 2.4.0 ### Patch Changes diff --git a/packages/remix-cloudflare-workers/package.json b/packages/remix-cloudflare-workers/package.json index 4507f938753..76d7c2bd40f 100644 --- a/packages/remix-cloudflare-workers/package.json +++ b/packages/remix-cloudflare-workers/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/cloudflare-workers", - "version": "2.4.0", + "version": "2.4.1", "description": "Cloudflare worker request handler for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -16,7 +16,7 @@ "module": "dist/esm/index.js", "dependencies": { "@cloudflare/kv-asset-handler": "^0.1.3", - "@remix-run/cloudflare": "2.4.0" + "@remix-run/cloudflare": "2.4.1" }, "devDependencies": { "@cloudflare/workers-types": "^4.20230518.0", diff --git a/packages/remix-cloudflare/CHANGELOG.md b/packages/remix-cloudflare/CHANGELOG.md index 626df1cc6c5..c63edbcaf3b 100644 --- a/packages/remix-cloudflare/CHANGELOG.md +++ b/packages/remix-cloudflare/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/cloudflare` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/server-runtime@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-cloudflare/package.json b/packages/remix-cloudflare/package.json index 1b54580120c..efe975009f3 100644 --- a/packages/remix-cloudflare/package.json +++ b/packages/remix-cloudflare/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/cloudflare", - "version": "2.4.0", + "version": "2.4.1", "description": "Cloudflare platform abstractions for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -15,7 +15,7 @@ "typings": "dist/index.d.ts", "dependencies": { "@cloudflare/kv-asset-handler": "^0.1.3", - "@remix-run/server-runtime": "2.4.0" + "@remix-run/server-runtime": "2.4.1" }, "devDependencies": { "@cloudflare/workers-types": "^4.20230518.0", diff --git a/packages/remix-css-bundle/CHANGELOG.md b/packages/remix-css-bundle/CHANGELOG.md index 5296007aebd..7a8bbd9943b 100644 --- a/packages/remix-css-bundle/CHANGELOG.md +++ b/packages/remix-css-bundle/CHANGELOG.md @@ -1,5 +1,9 @@ # @remix-run/css-bundle +## 2.4.1 + +No significant changes to this package were made in this release. [See the repo `CHANGELOG.md`](https://github.com/remix-run/remix/blob/main/CHANGELOG.md) for an overview of all changes in v2.4.1. + ## 2.4.0 No significant changes to this package were made in this release. [See the repo `CHANGELOG.md`](https://github.com/remix-run/remix/blob/main/CHANGELOG.md) for an overview of all changes in v2.4.0. diff --git a/packages/remix-css-bundle/package.json b/packages/remix-css-bundle/package.json index 42d693f3ca9..76140ad4732 100644 --- a/packages/remix-css-bundle/package.json +++ b/packages/remix-css-bundle/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/css-bundle", - "version": "2.4.0", + "version": "2.4.1", "description": "CSS bundle href when using CSS bundling features in Remix", "homepage": "https://remix.run", "bugs": { diff --git a/packages/remix-deno/CHANGELOG.md b/packages/remix-deno/CHANGELOG.md index dc1bf7b3c92..0ef0edcd3ca 100644 --- a/packages/remix-deno/CHANGELOG.md +++ b/packages/remix-deno/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/deno` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/server-runtime@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-deno/package.json b/packages/remix-deno/package.json index 8e9829d0354..41ee150e9fe 100644 --- a/packages/remix-deno/package.json +++ b/packages/remix-deno/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/deno", - "version": "2.4.0", + "version": "2.4.1", "description": "Deno platform abstractions for Remix", "homepage": "https://remix.run", "main": "./index.ts", @@ -15,7 +15,7 @@ "license": "MIT", "sideEffects": false, "dependencies": { - "@remix-run/server-runtime": "2.4.0", + "@remix-run/server-runtime": "2.4.1", "mime": "^3.0.0" }, "peerDependencies": { diff --git a/packages/remix-dev/CHANGELOG.md b/packages/remix-dev/CHANGELOG.md index c0d1981a41c..8b4a87ab28b 100644 --- a/packages/remix-dev/CHANGELOG.md +++ b/packages/remix-dev/CHANGELOG.md @@ -1,5 +1,78 @@ # `@remix-run/dev` +## 2.4.1 + +### Patch Changes + +- Vite: Error messages when `.server` files are referenced by client ([#8267](https://github.com/remix-run/remix/pull/8267)) + + - Previously, referencing a `.server` module from client code resulted in an error message like: + - `The requested module '/app/models/answer.server.ts' does not provide an export named 'isDateType'` + - This was confusing because `answer.server.ts` _does_ provide the `isDateType` export, but Remix was replacing `.server` modules with empty modules (`export {}`) for the client build + - Now, Remix explicitly fails at compile time when a `.server` module is referenced from client code and includes dedicated error messages depending on whether the import occurs in a route or a non-route module + - The error messages also include links to relevant documentation + +- Remove `unstable_viteServerBuildModuleId` in favor of manually referencing virtual module name `"virtual:remix/server-build"`. ([#8264](https://github.com/remix-run/remix/pull/8264)) + + **This is a breaking change for projects using the unstable Vite plugin with a custom server.** + + This change was made to avoid issues where `@remix-run/dev` could be inadvertently required in your server's production dependencies. + + Instead, you should manually write the virtual module name `"virtual:remix/server-build"` when calling `ssrLoadModule` in development. + + ```diff + -import { unstable_viteServerBuildModuleId } from "@remix-run/dev"; + + // ... + + app.all( + "*", + createRequestHandler({ + build: vite + - ? () => vite.ssrLoadModule(unstable_viteServerBuildModuleId) + + ? () => vite.ssrLoadModule("virtual:remix/server-build") + : await import("./build/server/index.js"), + }) + ); + ``` + +- Vite: Fix errors for non-existent `index.html` importer ([#8353](https://github.com/remix-run/remix/pull/8353)) + +- Add `vite:dev` and `vite:build` commands to the Remix CLI. ([#8211](https://github.com/remix-run/remix/pull/8211)) + + In order to handle upcoming Remix features where your plugin options can impact the number of Vite builds required, you should now run your Vite `dev` and `build` processes via the Remix CLI. + + ```diff + { + "scripts": { + - "dev": "vite dev", + - "build": "vite build && vite build --ssr" + + "dev": "remix vite:dev", + + "build": "remix vite:build" + } + } + ``` + +- Vite: Preserve names for exports from `.client` modules ([#8200](https://github.com/remix-run/remix/pull/8200)) + + Unlike `.server` modules, the main idea is not to prevent code from leaking into the server build + since the client build is already public. Rather, the goal is to isolate the SSR render from client-only code. + Routes need to import code from `.client` modules without compilation failing and then rely on runtime checks + or otherwise ensure that execution only happens within a client-only context (e.g. event handlers, `useEffect`). + + Replacing `.client` modules with empty modules would cause the build to fail as ESM named imports are statically analyzed. + So instead, we preserve the named export but replace each exported value with `undefined`. + That way, the import is valid at build time and standard runtime checks can be used to determine if the + code is running on the server or client. + +- Disable watch mode in Vite child compiler during build ([#8342](https://github.com/remix-run/remix/pull/8342)) + +- Vite: Show warning when source maps are enabled in production build ([#8222](https://github.com/remix-run/remix/pull/8222)) + +- Updated dependencies: + - `@remix-run/server-runtime@2.4.1` + - `@remix-run/node@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-dev/package.json b/packages/remix-dev/package.json index 36a7a19f83d..2883d87f034 100644 --- a/packages/remix-dev/package.json +++ b/packages/remix-dev/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/dev", - "version": "2.4.0", + "version": "2.4.1", "description": "Dev tools and CLI for Remix", "homepage": "https://remix.run", "bugs": { @@ -28,9 +28,9 @@ "@babel/types": "^7.22.5", "@mdx-js/mdx": "^2.3.0", "@npmcli/package-json": "^4.0.1", - "@remix-run/node": "2.4.0", - "@remix-run/router": "1.14.0", - "@remix-run/server-runtime": "2.4.0", + "@remix-run/node": "2.4.1", + "@remix-run/router": "1.14.1", + "@remix-run/server-runtime": "2.4.1", "@types/mdx": "^2.0.5", "@vanilla-extract/integration": "^6.2.0", "arg": "^5.0.1", @@ -73,7 +73,7 @@ "ws": "^7.4.5" }, "devDependencies": { - "@remix-run/serve": "2.4.0", + "@remix-run/serve": "2.4.1", "@types/cacache": "^17.0.0", "@types/cross-spawn": "^6.0.2", "@types/gunzip-maybe": "^1.4.0", @@ -94,7 +94,7 @@ "vite": "^5.0.0" }, "peerDependencies": { - "@remix-run/serve": "^2.4.0", + "@remix-run/serve": "^2.4.1", "typescript": "^5.1.0", "vite": "^5.0.0" }, diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts index 8300b5ce498..60e06d09b70 100644 --- a/packages/remix-dev/vite/plugin.ts +++ b/packages/remix-dev/vite/plugin.ts @@ -1009,7 +1009,13 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => { serverFileRE.test(resolved!.id) || serverDirRE.test(resolved!.id); if (!isDotServer) return; - if (!importer) throw Error(`Importer not found: ${id}`); + if (!importer) return; + if (viteCommand !== "build" && importer.endsWith(".html")) { + // Vite has a special `index.html` importer for `resolveId` within `transformRequest` + // https://github.com/vitejs/vite/blob/5684fcd8d27110d098b3e1c19d851f44251588f1/packages/vite/src/node/server/transformRequest.ts#L158 + // https://github.com/vitejs/vite/blob/5684fcd8d27110d098b3e1c19d851f44251588f1/packages/vite/src/node/server/pluginContainer.ts#L668 + return; + } let vite = importViteEsmSync(); let pluginConfig = await resolvePluginConfig(); diff --git a/packages/remix-eslint-config/CHANGELOG.md b/packages/remix-eslint-config/CHANGELOG.md index 87f48935ef5..2b9ed57f4fd 100644 --- a/packages/remix-eslint-config/CHANGELOG.md +++ b/packages/remix-eslint-config/CHANGELOG.md @@ -1,5 +1,9 @@ # `@remix-run/eslint-config` +## 2.4.1 + +No significant changes to this package were made in this release. [See the repo `CHANGELOG.md`](https://github.com/remix-run/remix/blob/main/CHANGELOG.md) for an overview of all changes in v2.4.1. + ## 2.4.0 No significant changes to this package were made in this release. [See the repo `CHANGELOG.md`](https://github.com/remix-run/remix/blob/main/CHANGELOG.md) for an overview of all changes in v2.4.0. diff --git a/packages/remix-eslint-config/package.json b/packages/remix-eslint-config/package.json index c7d60d8dc6d..cbd2c4db487 100644 --- a/packages/remix-eslint-config/package.json +++ b/packages/remix-eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/eslint-config", - "version": "2.4.0", + "version": "2.4.1", "description": "ESLint configuration for Remix projects", "bugs": { "url": "https://github.com/remix-run/remix/issues" diff --git a/packages/remix-express/CHANGELOG.md b/packages/remix-express/CHANGELOG.md index dbe35462069..547fdbdb544 100644 --- a/packages/remix-express/CHANGELOG.md +++ b/packages/remix-express/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/express` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/node@2.4.1` + ## 2.4.0 ### Patch Changes diff --git a/packages/remix-express/package.json b/packages/remix-express/package.json index 4c34569673d..73bbd0d2cb0 100644 --- a/packages/remix-express/package.json +++ b/packages/remix-express/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/express", - "version": "2.4.0", + "version": "2.4.1", "description": "Express server request handler for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -14,7 +14,7 @@ "main": "dist/index.js", "typings": "dist/index.d.ts", "dependencies": { - "@remix-run/node": "2.4.0" + "@remix-run/node": "2.4.1" }, "devDependencies": { "@types/express": "^4.17.9", diff --git a/packages/remix-node/CHANGELOG.md b/packages/remix-node/CHANGELOG.md index 483e5e34d7c..b289a2b6887 100644 --- a/packages/remix-node/CHANGELOG.md +++ b/packages/remix-node/CHANGELOG.md @@ -1,5 +1,12 @@ # `@remix-run/node` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/server-runtime@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-node/package.json b/packages/remix-node/package.json index 732f57685d2..eff7047a121 100644 --- a/packages/remix-node/package.json +++ b/packages/remix-node/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/node", - "version": "2.4.0", + "version": "2.4.1", "description": "Node.js platform abstractions for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -17,7 +17,7 @@ "./install.js" ], "dependencies": { - "@remix-run/server-runtime": "2.4.0", + "@remix-run/server-runtime": "2.4.1", "@remix-run/web-fetch": "^4.4.2", "@remix-run/web-file": "^3.1.0", "@remix-run/web-stream": "^1.1.0", diff --git a/packages/remix-react/CHANGELOG.md b/packages/remix-react/CHANGELOG.md index 01cef4e18f5..87a1caff5cf 100644 --- a/packages/remix-react/CHANGELOG.md +++ b/packages/remix-react/CHANGELOG.md @@ -1,5 +1,14 @@ # `@remix-run/react` +## 2.4.1 + +### Patch Changes + +- Propagate server `loader` errors through `serverLoader` in hydrating `clientLoader`'s ([#8304](https://github.com/remix-run/remix/pull/8304)) +- Re-export `Response` helpers (`defer`/`json`/`redirect`/`redirectDocument`) through `@remix-run/react` for use in `clientLoader`/`clientAction` ([#8351](https://github.com/remix-run/remix/pull/8351)) +- Updated dependencies: + - `@remix-run/server-runtime@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-react/index.tsx b/packages/remix-react/index.tsx index 50571ac7591..ad42a903d75 100644 --- a/packages/remix-react/index.tsx +++ b/packages/remix-react/index.tsx @@ -1,5 +1,3 @@ -export type { RemixBrowserProps } from "./browser"; -export { RemixBrowser } from "./browser"; export type { ErrorResponse, Fetcher, @@ -52,7 +50,16 @@ export { unstable_usePrompt, unstable_useViewTransitionState, } from "react-router-dom"; +export { + // For use in clientLoader/clientAction + defer, + json, + redirect, + redirectDocument, +} from "@remix-run/server-runtime"; +export type { RemixBrowserProps } from "./browser"; +export { RemixBrowser } from "./browser"; export type { AwaitProps, RemixNavLinkProps as NavLinkProps, diff --git a/packages/remix-react/package.json b/packages/remix-react/package.json index 0e64facefe2..52b29886ed4 100644 --- a/packages/remix-react/package.json +++ b/packages/remix-react/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/react", - "version": "2.4.0", + "version": "2.4.1", "description": "React DOM bindings for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -16,10 +16,10 @@ "typings": "dist/index.d.ts", "module": "dist/esm/index.js", "dependencies": { - "@remix-run/router": "1.14.0", - "@remix-run/server-runtime": "2.4.0", - "react-router": "6.21.0", - "react-router-dom": "6.21.0" + "@remix-run/router": "1.14.1", + "@remix-run/server-runtime": "2.4.1", + "react-router": "6.21.1", + "react-router-dom": "6.21.1" }, "devDependencies": { "@testing-library/jest-dom": "^5.17.0", diff --git a/packages/remix-serve/CHANGELOG.md b/packages/remix-serve/CHANGELOG.md index cd77d1ee01e..1b12ee53325 100644 --- a/packages/remix-serve/CHANGELOG.md +++ b/packages/remix-serve/CHANGELOG.md @@ -1,5 +1,14 @@ # `@remix-run/serve` +## 2.4.1 + +### Patch Changes + +- Use node `fileURLToPath` to convert source map URL to path ([#8321](https://github.com/remix-run/remix/pull/8321)) +- Updated dependencies: + - `@remix-run/node@2.4.1` + - `@remix-run/express@2.4.1` + ## 2.4.0 ### Patch Changes diff --git a/packages/remix-serve/package.json b/packages/remix-serve/package.json index 132af85573a..13233317594 100644 --- a/packages/remix-serve/package.json +++ b/packages/remix-serve/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/serve", - "version": "2.4.0", + "version": "2.4.1", "description": "Production application server for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -15,8 +15,8 @@ "remix-serve": "dist/cli.js" }, "dependencies": { - "@remix-run/express": "2.4.0", - "@remix-run/node": "2.4.0", + "@remix-run/express": "2.4.1", + "@remix-run/node": "2.4.1", "chokidar": "^3.5.3", "compression": "^1.7.4", "express": "^4.17.1", diff --git a/packages/remix-server-runtime/CHANGELOG.md b/packages/remix-server-runtime/CHANGELOG.md index 908c1660bce..61e97efcdd5 100644 --- a/packages/remix-server-runtime/CHANGELOG.md +++ b/packages/remix-server-runtime/CHANGELOG.md @@ -1,5 +1,11 @@ # `@remix-run/server-runtime` +## 2.4.1 + +### Patch Changes + +- Add optional `error` to `ServerRuntimeMetaArgs` type to align with `MetaArgs` ([#8238](https://github.com/remix-run/remix/pull/8238)) + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-server-runtime/package.json b/packages/remix-server-runtime/package.json index 7801ae9809e..9f48561ef5e 100644 --- a/packages/remix-server-runtime/package.json +++ b/packages/remix-server-runtime/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/server-runtime", - "version": "2.4.0", + "version": "2.4.1", "description": "Server runtime for Remix", "bugs": { "url": "https://github.com/remix-run/remix/issues" @@ -16,7 +16,7 @@ "typings": "dist/index.d.ts", "module": "dist/esm/index.js", "dependencies": { - "@remix-run/router": "1.14.0", + "@remix-run/router": "1.14.1", "@types/cookie": "^0.5.3", "@web3-storage/multipart-parser": "^1.0.0", "cookie": "^0.5.0", diff --git a/packages/remix-testing/CHANGELOG.md b/packages/remix-testing/CHANGELOG.md index fa4b7d26097..0e44df460f2 100644 --- a/packages/remix-testing/CHANGELOG.md +++ b/packages/remix-testing/CHANGELOG.md @@ -1,5 +1,13 @@ # `@remix-run/testing` +## 2.4.1 + +### Patch Changes + +- Updated dependencies: + - `@remix-run/react@2.4.1` + - `@remix-run/node@2.4.1` + ## 2.4.0 ### Minor Changes diff --git a/packages/remix-testing/package.json b/packages/remix-testing/package.json index 740eec8fad6..cdb8d7a0a20 100644 --- a/packages/remix-testing/package.json +++ b/packages/remix-testing/package.json @@ -1,6 +1,6 @@ { "name": "@remix-run/testing", - "version": "2.4.0", + "version": "2.4.1", "description": "Testing utilities for Remix apps", "homepage": "https://remix.run", "bugs": { @@ -16,10 +16,10 @@ "typings": "./dist/index.d.ts", "module": "./dist/esm/index.js", "dependencies": { - "@remix-run/node": "2.4.0", - "@remix-run/react": "2.4.0", - "@remix-run/router": "1.14.0", - "react-router-dom": "6.21.0" + "@remix-run/node": "2.4.1", + "@remix-run/react": "2.4.1", + "@remix-run/router": "1.14.1", + "react-router-dom": "6.21.1" }, "devDependencies": { "@types/node": "^18.17.1", diff --git a/packages/remix/package.json b/packages/remix/package.json index df26cc84aa0..8d83b61719a 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -1,6 +1,6 @@ { "name": "remix", - "version": "2.4.0", + "version": "2.4.1", "description": "A framework for building better websites", "homepage": "https://remix.run", "bugs": { diff --git a/scripts/lint-templates.sh b/scripts/lint-templates.sh new file mode 100755 index 00000000000..3417c7e994f --- /dev/null +++ b/scripts/lint-templates.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +# Helper script for us to use to validate template lint setups outside of the +# monorepo. This script will, for each template in your local Remix repo clone: +# +# * Install an app via create-remix for the template (into a temp/ directory) +# * Install deps +# * npm run lint +# +# Usage: +# lint-templates.sh [path-to-remix-repo] +# +# So from a sibling folder to the remix repo: +# ../remix/scripts/lint-templates.sh ../remix + +REPO_DIR="${1}" + +if [ "${REPO_DIR}" == "" ]; then + REPO_DIR="../remix" +fi + +if [ ! -e "${REPO_DIR}" ]; then + echo "Invalid repo directory: ${REPO_DIR}"; + exit 1; +fi + +TEMPLATES=$(find ${REPO_DIR}/templates -type d -mindepth 1 -maxdepth 1 | grep -v deno | grep -v tutorial | sort) + +for D in ${TEMPLATES}; do + echo "Linting template: ${D}"; + echo "-------------------------------------------------------"; + rm -rf temp; + npx create-remix@latest --template "${D}" temp -y; + cd temp; + npm run lint; + echo ""; + echo ""; + cd ..; +done diff --git a/templates/arc/.eslintrc.cjs b/templates/arc/.eslintrc.cjs index 2061cd22684..84c2abea6d7 100644 --- a/templates/arc/.eslintrc.cjs +++ b/templates/arc/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js", "plugin-remix.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/arc/app/entry.server.tsx b/templates/arc/app/entry.server.tsx index 0c7712b0b0e..e2002b0740e 100644 --- a/templates/arc/app/entry.server.tsx +++ b/templates/arc/app/entry.server.tsx @@ -19,6 +19,9 @@ export default function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { return isbot(request.headers.get("user-agent")) diff --git a/templates/arc/package.json b/templates/arc/package.json index 1c202dea0f7..91d8e08eacb 100644 --- a/templates/arc/package.json +++ b/templates/arc/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual -c \"arc sandbox -e testing\"", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "cross-env NODE_ENV=production arc sandbox", "typecheck": "tsc" }, @@ -22,11 +23,16 @@ "devDependencies": { "@architect/architect": "^10.12.1", "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/source-map-support": "^0.5.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6" }, "engines": { diff --git a/templates/cloudflare-pages/.eslintrc.cjs b/templates/cloudflare-pages/.eslintrc.cjs index 2061cd22684..edd3094f704 100644 --- a/templates/cloudflare-pages/.eslintrc.cjs +++ b/templates/cloudflare-pages/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/cloudflare-pages/app/entry.server.tsx b/templates/cloudflare-pages/app/entry.server.tsx index dd06c61bcfa..3f5b9989333 100644 --- a/templates/cloudflare-pages/app/entry.server.tsx +++ b/templates/cloudflare-pages/app/entry.server.tsx @@ -14,6 +14,9 @@ export default async function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { const body = await renderToReadableStream( diff --git a/templates/cloudflare-pages/package.json b/templates/cloudflare-pages/package.json index efe545594c5..ee3120f5819 100644 --- a/templates/cloudflare-pages/package.json +++ b/templates/cloudflare-pages/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual -c \"npm run start\"", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "wrangler pages dev --compatibility-date=2023-06-21 ./public", "typecheck": "tsc" }, @@ -20,10 +21,15 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20230518.0", "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.0", "wrangler": "3.8.0" }, diff --git a/templates/cloudflare-workers/.eslintrc.cjs b/templates/cloudflare-workers/.eslintrc.cjs index 2061cd22684..edd3094f704 100644 --- a/templates/cloudflare-workers/.eslintrc.cjs +++ b/templates/cloudflare-workers/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/cloudflare-workers/app/entry.server.tsx b/templates/cloudflare-workers/app/entry.server.tsx index dd06c61bcfa..3f5b9989333 100644 --- a/templates/cloudflare-workers/app/entry.server.tsx +++ b/templates/cloudflare-workers/app/entry.server.tsx @@ -14,6 +14,9 @@ export default async function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { const body = await renderToReadableStream( diff --git a/templates/cloudflare-workers/package.json b/templates/cloudflare-workers/package.json index 24c570412dc..abab2ac1a74 100644 --- a/templates/cloudflare-workers/package.json +++ b/templates/cloudflare-workers/package.json @@ -6,6 +6,7 @@ "build": "remix build", "deploy": "wrangler deploy", "dev": "remix dev --manual -c \"npm start\"", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "wrangler dev ./build/index.js", "typecheck": "tsc" }, @@ -21,10 +22,16 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20230518.0", "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6", "wrangler": "3.8.0" }, diff --git a/templates/cloudflare-workers/server.ts b/templates/cloudflare-workers/server.ts index 7408ed39813..4b6e39ef295 100644 --- a/templates/cloudflare-workers/server.ts +++ b/templates/cloudflare-workers/server.ts @@ -2,6 +2,7 @@ import { getAssetFromKV } from "@cloudflare/kv-asset-handler"; import type { AppLoadContext } from "@remix-run/cloudflare"; import { createRequestHandler, logDevReady } from "@remix-run/cloudflare"; import * as build from "@remix-run/dev/server-build"; +// eslint-disable-next-line import/no-unresolved import __STATIC_CONTENT_MANIFEST from "__STATIC_CONTENT_MANIFEST"; const MANIFEST = JSON.parse(__STATIC_CONTENT_MANIFEST); @@ -38,7 +39,9 @@ export default { }, } ); - } catch (error) {} + } catch (error) { + // No-op + } try { const loadContext: AppLoadContext = { diff --git a/templates/deno/app/entry.server.tsx b/templates/deno/app/entry.server.tsx index 03789f45e62..83ce4317722 100644 --- a/templates/deno/app/entry.server.tsx +++ b/templates/deno/app/entry.server.tsx @@ -14,6 +14,9 @@ export default async function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext, ) { const body = await renderToReadableStream( diff --git a/templates/express/.eslintrc.cjs b/templates/express/.eslintrc.cjs index 2061cd22684..e40419a11b5 100644 --- a/templates/express/.eslintrc.cjs +++ b/templates/express/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js", "server.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/express/app/entry.server.tsx b/templates/express/app/entry.server.tsx index 0c7712b0b0e..e2002b0740e 100644 --- a/templates/express/app/entry.server.tsx +++ b/templates/express/app/entry.server.tsx @@ -19,6 +19,9 @@ export default function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { return isbot(request.headers.get("user-agent")) diff --git a/templates/express/package.json b/templates/express/package.json index 94cda6955ae..5cb109be617 100644 --- a/templates/express/package.json +++ b/templates/express/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual -c \"node --watch-path server.js --watch server.js\"", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "cross-env NODE_ENV=production node ./server.js", "typecheck": "tsc" }, @@ -24,15 +25,20 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/compression": "^1.7.2", "@types/express": "^4.17.17", "@types/morgan": "^1.9.4", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@types/source-map-support": "^0.5.6", + "@typescript-eslint/eslint-plugin": "^6.7.4", "chokidar": "^3.5.3", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6" }, "engines": { diff --git a/templates/fly/.eslintrc.cjs b/templates/fly/.eslintrc.cjs index 2061cd22684..edd3094f704 100644 --- a/templates/fly/.eslintrc.cjs +++ b/templates/fly/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/fly/app/entry.server.tsx b/templates/fly/app/entry.server.tsx index 0c7712b0b0e..e2002b0740e 100644 --- a/templates/fly/app/entry.server.tsx +++ b/templates/fly/app/entry.server.tsx @@ -19,6 +19,9 @@ export default function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { return isbot(request.headers.get("user-agent")) diff --git a/templates/fly/package.json b/templates/fly/package.json index a536c283941..a4672d381f1 100644 --- a/templates/fly/package.json +++ b/templates/fly/package.json @@ -6,6 +6,7 @@ "build": "remix build", "deploy": "fly deploy --remote-only", "dev": "remix dev", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/index.js", "typecheck": "tsc" }, @@ -20,10 +21,15 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6" }, "engines": { diff --git a/templates/remix-javascript/.eslintrc.cjs b/templates/remix-javascript/.eslintrc.cjs index 2061cd22684..777bae21d87 100644 --- a/templates/remix-javascript/.eslintrc.cjs +++ b/templates/remix-javascript/.eslintrc.cjs @@ -1,4 +1,56 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + { + files: ["**/*.{js,jsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/remix-javascript/package.json b/templates/remix-javascript/package.json index 2c4c9e0b638..e821a97d2b5 100644 --- a/templates/remix-javascript/package.json +++ b/templates/remix-javascript/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/index.js" }, "dependencies": { @@ -18,8 +19,11 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", - "eslint": "^8.38.0" + "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0" }, "engines": { "node": ">=18.0.0" diff --git a/templates/remix-tutorial/.eslintrc.js b/templates/remix-tutorial/.eslintrc.js index d57eeaf437a..edd3094f704 100644 --- a/templates/remix-tutorial/.eslintrc.js +++ b/templates/remix-tutorial/.eslintrc.js @@ -1,3 +1,9 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { root: true, diff --git a/templates/remix-tutorial/package.json b/templates/remix-tutorial/package.json index 2d45011a075..52bfc990bb6 100644 --- a/templates/remix-tutorial/package.json +++ b/templates/remix-tutorial/package.json @@ -4,6 +4,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve build", "typecheck": "tsc" }, diff --git a/templates/remix/.eslintrc.cjs b/templates/remix/.eslintrc.cjs index 2061cd22684..edd3094f704 100644 --- a/templates/remix/.eslintrc.cjs +++ b/templates/remix/.eslintrc.cjs @@ -1,4 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + /** @type {import('eslint').Linter.Config} */ module.exports = { - extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"], + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], }; diff --git a/templates/remix/app/entry.server.tsx b/templates/remix/app/entry.server.tsx index 0c7712b0b0e..e2002b0740e 100644 --- a/templates/remix/app/entry.server.tsx +++ b/templates/remix/app/entry.server.tsx @@ -19,6 +19,9 @@ export default function handleRequest( responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, + // This is ignored so we can keep it in the template for visibility. Feel + // free to delete this parameter in your app if you're not using it! + // eslint-disable-next-line @typescript-eslint/no-unused-vars loadContext: AppLoadContext ) { return isbot(request.headers.get("user-agent")) diff --git a/templates/remix/package.json b/templates/remix/package.json index 57fc5734a21..9a7d370bf82 100644 --- a/templates/remix/package.json +++ b/templates/remix/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "remix build", "dev": "remix dev --manual", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/index.js", "typecheck": "tsc" }, @@ -19,10 +20,15 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6" }, "engines": { diff --git a/templates/unstable-vite-express/.eslintrc.cjs b/templates/unstable-vite-express/.eslintrc.cjs new file mode 100644 index 00000000000..edd3094f704 --- /dev/null +++ b/templates/unstable-vite-express/.eslintrc.cjs @@ -0,0 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], +}; diff --git a/templates/unstable-vite-express/package.json b/templates/unstable-vite-express/package.json index f7b19e8777d..eaf95912f85 100644 --- a/templates/unstable-vite-express/package.json +++ b/templates/unstable-vite-express/package.json @@ -3,8 +3,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "node ./server.mjs", "build": "remix vite:build", + "dev": "node ./server.mjs", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "cross-env NODE_ENV=production node ./server.mjs", "typecheck": "tsc" }, @@ -19,12 +20,18 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/express": "^4.17.20", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "cross-env": "^7.0.3", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6", "vite": "^5.0.0", "vite-tsconfig-paths": "^4.2.1" diff --git a/templates/unstable-vite/.eslintrc.cjs b/templates/unstable-vite/.eslintrc.cjs new file mode 100644 index 00000000000..edd3094f704 --- /dev/null +++ b/templates/unstable-vite/.eslintrc.cjs @@ -0,0 +1,80 @@ +/** + * This is intended to be a basic starting point for linting in your app. + * It relies on recommended configs out of the box for simplicity, but you can + * and should modify this configuration to best suit your team's needs. + */ + +/** @type {import('eslint').Linter.Config} */ +module.exports = { + root: true, + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, + env: { + browser: true, + commonjs: true, + es6: true, + }, + + // Base config + extends: ["eslint:recommended"], + + overrides: [ + // React + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: ["react", "jsx-a11y"], + extends: [ + "plugin:react/recommended", + "plugin:react/jsx-runtime", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + ], + settings: { + react: { + version: "detect", + }, + formComponents: ["Form"], + linkComponents: [ + { name: "Link", linkAttribute: "to" }, + { name: "NavLink", linkAttribute: "to" }, + ], + }, + }, + + // Typescript + { + files: ["**/*.{ts,tsx}"], + plugins: ["@typescript-eslint", "import"], + parser: "@typescript-eslint/parser", + settings: { + "import/internal-regex": "^~/", + "import/resolver": { + node: { + extensions: [".ts", ".tsx"], + }, + typescript: { + alwaysTryTypes: true, + }, + }, + }, + extends: [ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + ], + }, + + // Node + { + files: [".eslintrc.js"], + env: { + node: true, + }, + }, + ], +}; diff --git a/templates/unstable-vite/package.json b/templates/unstable-vite/package.json index ac20019f64e..2e900a79357 100644 --- a/templates/unstable-vite/package.json +++ b/templates/unstable-vite/package.json @@ -3,8 +3,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "remix vite:dev", "build": "remix vite:build", + "dev": "remix vite:dev", + "lint": "eslint --ignore-path .gitignore --cache --cache-location ./node_modules/.cache/eslint .", "start": "remix-serve ./build/server/index.js", "typecheck": "tsc" }, @@ -18,10 +19,16 @@ }, "devDependencies": { "@remix-run/dev": "*", - "@remix-run/eslint-config": "*", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", + "@typescript-eslint/eslint-plugin": "^6.7.4", "eslint": "^8.38.0", + "eslint-config-prettier": "^9.0.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", "typescript": "^5.1.6", "vite": "^5.0.0", "vite-tsconfig-paths": "^4.2.1" diff --git a/templates/unstable-vite/vite.config.ts b/templates/unstable-vite/vite.config.ts index 492e8c2080d..177dd59b27d 100644 --- a/templates/unstable-vite/vite.config.ts +++ b/templates/unstable-vite/vite.config.ts @@ -1,10 +1,7 @@ import { unstable_vitePlugin as remix } from "@remix-run/dev"; -import { installGlobals } from "@remix-run/node"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; -installGlobals(); - export default defineConfig({ plugins: [remix(), tsconfigPaths()], }); diff --git a/yarn.lock b/yarn.lock index 76de9af955c..7d4e530741b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2314,10 +2314,10 @@ "@changesets/types" "^5.0.0" dotenv "^8.1.0" -"@remix-run/router@1.14.0": - version "1.14.0" - resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.14.0.tgz#9bc39a5a3a71b81bdb310eba6def5bc3966695b7" - integrity sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A== +"@remix-run/router@1.14.1": + version "1.14.1" + resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.14.1.tgz#6d2dd03d52e604279c38911afc1079d58c50a755" + integrity sha512-Qg4DMQsfPNAs88rb2xkdk03N3bjK4jgX5fR24eHCTR9q6PrhZQZ4UJBPzCHJkIpTRN1UKxx2DzjZmnC+7Lj0Ow== "@remix-run/web-blob@^3.1.0": version "3.1.0" @@ -10997,20 +10997,20 @@ react-refresh@^0.14.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz" integrity sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ== -react-router-dom@6.21.0: - version "6.21.0" - resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.0.tgz#aa4c6bc046a8e8723095bc09b3c0ab2254532712" - integrity sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ== +react-router-dom@6.21.1: + version "6.21.1" + resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.1.tgz#58b459d2fe1841388c95bb068f85128c45e27349" + integrity sha512-QCNrtjtDPwHDO+AO21MJd7yIcr41UetYt5jzaB9Y1UYaPTCnVuJq6S748g1dE11OQlCFIQg+RtAA1SEZIyiBeA== dependencies: - "@remix-run/router" "1.14.0" - react-router "6.21.0" + "@remix-run/router" "1.14.1" + react-router "6.21.1" -react-router@6.21.0: - version "6.21.0" - resolved "https://registry.npmjs.org/react-router/-/react-router-6.21.0.tgz#6fe3e59877aca3dccceec1801d26991ddf42d12b" - integrity sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg== +react-router@6.21.1: + version "6.21.1" + resolved "https://registry.npmjs.org/react-router/-/react-router-6.21.1.tgz#8db7ee8d7cfc36513c9a66b44e0897208c33be34" + integrity sha512-W0l13YlMTm1YrpVIOpjCADJqEUpz1vm+CMo47RuFX4Ftegwm6KOYsL5G3eiE52jnJpKvzm6uB/vTKTPKM8dmkA== dependencies: - "@remix-run/router" "1.14.0" + "@remix-run/router" "1.14.1" react@^18.2.0: version "18.2.0"