diff --git a/packages/react-router-dev/config/config.ts b/packages/react-router-dev/config/config.ts index b5bd6ea254..075c2b499c 100644 --- a/packages/react-router-dev/config/config.ts +++ b/packages/react-router-dev/config/config.ts @@ -1,5 +1,6 @@ -import fs from "node:fs"; import { execSync } from "node:child_process"; +import fs from "node:fs"; +import { isDeepStrictEqual } from "node:util"; import PackageJson from "@npmcli/package-json"; import * as ViteNode from "../vite/vite-node"; import type * as Vite from "vite"; @@ -9,11 +10,8 @@ import chokidar, { type EmitArgs as ChokidarEmitArgs, } from "chokidar"; import colors from "picocolors"; -import pick from "lodash/pick"; -import omit from "lodash/omit"; -import cloneDeep from "lodash/cloneDeep"; -import isEqual from "lodash/isEqual"; +import { omit, pick } from "../utils"; import { type RouteManifest, type RouteManifestEntry, @@ -389,7 +387,7 @@ async function resolveConfig({ } // Prevent mutations to the user config - reactRouterUserConfig = deepFreeze(cloneDeep(reactRouterUserConfig)); + reactRouterUserConfig = deepFreeze(structuredClone(reactRouterUserConfig)); let presets: ReactRouterConfig[] = ( await Promise.all( @@ -404,12 +402,11 @@ async function resolveConfig({ return null; } - let configPreset: ReactRouterConfig = omit( + return omit( await preset.reactRouterConfig({ reactRouterUserConfig }), + // @ts-expect-error excludedConfigPresetKeys, ); - - return configPreset; }), ) ).filter(function isNotNull(value: T | null): value is T { @@ -775,10 +772,14 @@ export async function createConfigLoader({ let configChanged = result.ok && - !isEqual(omitRoutes(currentConfig), omitRoutes(result.value)); + !isDeepStrictEqual( + omitRoutes(currentConfig), + omitRoutes(result.value), + ); let routeConfigChanged = - result.ok && !isEqual(currentConfig?.routes, result.value.routes); + result.ok && + !isDeepStrictEqual(currentConfig?.routes, result.value.routes); for (let handler of changeHandlers) { handler({ diff --git a/packages/react-router-dev/config/routes.ts b/packages/react-router-dev/config/routes.ts index fa94d482f7..d37312ac63 100644 --- a/packages/react-router-dev/config/routes.ts +++ b/packages/react-router-dev/config/routes.ts @@ -1,8 +1,8 @@ import * as Path from "pathe"; import * as v from "valibot"; -import pick from "lodash/pick"; import invariant from "../invariant"; +import { pick } from "../utils"; declare global { var __reactRouterAppDirectory: string; @@ -240,7 +240,10 @@ type CreateIndexOptions = Pick< * Helper function for creating a route config entry for an index route, for use * within `routes.ts`. */ -function index(file: string, options?: CreateIndexOptions): RouteConfigEntry { +function index( + file: string, + options: CreateIndexOptions = {}, +): RouteConfigEntry { return { file, index: true, diff --git a/packages/react-router-dev/package.json b/packages/react-router-dev/package.json index 3b78681fa5..c642bb4095 100644 --- a/packages/react-router-dev/package.json +++ b/packages/react-router-dev/package.json @@ -86,11 +86,11 @@ "es-module-lexer": "^1.3.1", "exit-hook": "2.2.1", "jsesc": "3.0.2", - "lodash": "^4.17.21", "pathe": "^1.1.2", "picocolors": "^1.1.1", "prettier": "^3.6.2", "react-refresh": "^0.14.0", + "scule": "^1.3.0", "semver": "^7.3.7", "set-cookie-parser": "^2.6.0", "tinyglobby": "^0.2.14", @@ -105,7 +105,6 @@ "@types/dedent": "^0.7.0", "@types/express": "^4.17.9", "@types/jsesc": "^3.0.1", - "@types/lodash": "^4.14.182", "@types/node": "^20.0.0", "@types/npmcli__package-json": "^4.0.0", "@types/set-cookie-parser": "^2.4.1", diff --git a/packages/react-router-dev/utils.ts b/packages/react-router-dev/utils.ts new file mode 100644 index 0000000000..c8d653294c --- /dev/null +++ b/packages/react-router-dev/utils.ts @@ -0,0 +1,15 @@ +export const pick = ( + obj: T, + keys: readonly K[], +): Pick => + Object.fromEntries( + Object.entries(obj).filter(([key]) => keys.includes(key as K)), + ) as Pick; + +export const omit = ( + obj: T, + keys: readonly K[], +): Omit => + Object.fromEntries( + Object.entries(obj).filter(([key]) => !keys.includes(key as K)), + ) as Omit; diff --git a/packages/react-router-dev/vite/plugin.ts b/packages/react-router-dev/vite/plugin.ts index 8a7af33ba7..c6c345bd6f 100644 --- a/packages/react-router-dev/vite/plugin.ts +++ b/packages/react-router-dev/vite/plugin.ts @@ -31,11 +31,10 @@ import { init as initEsModuleLexer, parse as esModuleLexer, } from "es-module-lexer"; +import { kebabCase } from "scule"; import { escapePath as escapePathAsGlob } from "tinyglobby"; -import pick from "lodash/pick"; import jsesc from "jsesc"; import colors from "picocolors"; -import kebabCase from "lodash/kebabCase"; import * as Typegen from "../typegen"; import type { RouteManifestEntry, RouteManifest } from "../config/routes"; @@ -44,6 +43,7 @@ import type { Manifest as ReactRouterManifest, } from "../manifest"; import invariant from "../invariant"; +import { pick } from "../utils"; import type { Cache } from "./cache"; import { generate, parse } from "./babel"; import type { NodeRequestHandler } from "./node-adapter"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d0b8091100..3fcab9170d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1147,9 +1147,6 @@ importers: jsesc: specifier: 3.0.2 version: 3.0.2 - lodash: - specifier: ^4.17.21 - version: 4.17.21 pathe: specifier: ^1.1.2 version: 1.1.2 @@ -1162,6 +1159,9 @@ importers: react-refresh: specifier: ^0.14.0 version: 0.14.2 + scule: + specifier: ^1.3.0 + version: 1.3.0 semver: specifier: ^7.3.7 version: 7.7.2 @@ -1199,9 +1199,6 @@ importers: '@types/jsesc': specifier: ^3.0.1 version: 3.0.3 - '@types/lodash': - specifier: ^4.14.182 - version: 4.17.0 '@types/node': specifier: ^20.0.0 version: 20.11.30 @@ -4934,9 +4931,6 @@ packages: '@types/lambda-tester@3.6.2': resolution: {integrity: sha512-nQRUx0AuvTq5KOz1SaxMOOFJvnybo1oAzvSy/p9bVGthZVvg1Dar/051mhMuzdN1DWg++bs+eGq1MdCbm6wjSQ==} - '@types/lodash@4.17.0': - resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} - '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -8997,6 +8991,9 @@ packages: scheduler@0.26.0: resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + scule@1.3.0: + resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} + semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true @@ -13299,8 +13296,6 @@ snapshots: dependencies: '@types/aws-lambda': 8.10.141 - '@types/lodash@4.17.0': {} - '@types/mdast@3.0.15': dependencies: '@types/unist': 2.0.10 @@ -18689,6 +18684,8 @@ snapshots: scheduler@0.26.0: {} + scule@1.3.0: {} + semver@5.7.1: {} semver@6.3.1: {}