feat: configure export conditions properly (#12136)

feat: nuke rollup into oblivion in favor of tsup
feat: add ESM build for architect, express and node packages
chore: update HMR test to ignore warning log
feat: add module-sync export condition
fix: react-router should not reference itself, that's weird (use tsconfig paths)
chore: update e2e test warning assertion
chore: add vite ignore comment for dynamic import
fix: update optimizeDeps
chore: add wireit for caching
chore: add cache to workflows

---------

Co-authored-by: Matt Brophy <matt@brophy.org>
pull/12186/head
Jacob Ebey 3 months ago committed by GitHub
parent 5c7cc020be
commit 2d5924f567
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -22,6 +22,8 @@ jobs:
node-version-file: ".nvmrc"
cache: "pnpm"
- uses: google/wireit@setup-github-actions-caching/v2
- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"

@ -45,6 +45,8 @@ jobs:
node-version: ${{ matrix.node }}
cache: "pnpm"
- uses: google/wireit@setup-github-actions-caching/v2
- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"

@ -45,6 +45,8 @@ jobs:
cache: pnpm
check-latest: true
- uses: google/wireit@setup-github-actions-caching/v2
- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"

1
.gitignore vendored

@ -22,6 +22,7 @@ node_modules/
/packages/*/dist/
/packages/*/LICENSE.md
.wireit
.eslintcache
.tmp
/.env

@ -0,0 +1,12 @@
export function createBanner(packageName: string, version: string) {
return `/**
* ${packageName} v${version}
*
* Copyright (c) Remix Software Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/`;
}

@ -1,9 +1,11 @@
import cp from "node:child_process";
import type { Page, Response, Request } from "@playwright/test";
import { test } from "@playwright/test";
import cheerio from "cheerio";
import { load } from "cheerio";
import prettier from "prettier";
let cheerio = load("");
import type { AppFixture } from "./create-fixture.js";
export class PlaywrightFixture {
@ -239,7 +241,7 @@ export function selectHtml(source: string, selector: string) {
return prettyHtml(cheerio.html(el)).trim();
}
export function prettyHtml(source: string): string {
export function prettyHtml(source: string) {
return prettier.format(source, { parser: "html" });
}

@ -567,8 +567,15 @@ test.describe("SPA Mode", () => {
expect(await page.locator("[data-root]").textContent()).toBe("Root");
expect(await page.locator("[data-index]").textContent()).toBe("Index");
// Hydrates without issues
expect(logs).toEqual([]);
// Hydrates without issues - this message is expected due to the nested <Routes>
expect(logs).toEqual([
'You rendered descendant <Routes> (or called `useRoutes()`) at "/" ' +
'(under <Route path="">) but the parent route path has no trailing "*". ' +
"This means if you navigate deeper, the parent won't match anymore and " +
"therefore the child routes will never render." +
"\n\n" +
'Please change the parent <Route path=""> to <Route path="/*">.',
]);
});
test("wraps default root HydrateFallback in user-provided Layout", async ({

@ -2,7 +2,7 @@
"name": "@remix-run/react-router",
"private": true,
"scripts": {
"build": "rollup -c",
"build": "pnpm run --filter=\"./packages/**/*\" build",
"clean": "git clean -fdX .",
"clean:build": "git clean -fdx -e node_modules .",
"clean:integration": "node ./integration/helpers/cleanup.mjs",
@ -57,10 +57,6 @@
"@octokit/rest": "^18.12.0",
"@playwright/test": "^1.33.0",
"@remix-run/changelog-github": "^0.0.5",
"@rollup/plugin-babel": "^5.3.1",
"@rollup/plugin-node-resolve": "^11.0.1",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-typescript": "^8.5.0",
"@testing-library/jest-dom": "5.17.0",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^14.5.2",
@ -104,10 +100,6 @@
"remark-gfm": "3.0.1",
"remark-parse": "^10.0.1",
"remark-stringify": "^10.0.2",
"rollup": "^2.79.1",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-prettier": "^2.3.0",
"rollup-plugin-terser": "^7.0.2",
"semver": "^7.5.4",
"tslib": "^2.6.2",
"type-fest": "^2.19.0",

@ -15,13 +15,38 @@
"typings": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"node": {
"types": "./dist/index.d.ts",
"module-sync": "./dist/index.mjs",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"sessions/**",
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@architect/functions": "^5.2.0",
@ -35,7 +60,9 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router": "workspace:*",
"typescript": "^5.1.0"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"@react-router/node": "workspace:^",

@ -1,56 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const typescript = require("@rollup/plugin-typescript");
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
getBuildDirectories,
createBanner,
WATCH,
remixBabelConfig,
} = require("../../rollup.utils");
const { name: packageName, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
packageName,
// We don't live in a folder matching our package name
"react-router-architect"
);
return [
{
external: (id) => isBareModuleId(id),
input: `${SOURCE_DIR}/index.ts`,
output: {
banner: createBanner(packageName, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "auto",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -15,23 +15,45 @@
"typings": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"scripts": {
"build": "rollup -c",
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"sessions/**",
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20230518.0",
"react-router": "workspace:*",
"typescript": "^5.1.0"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"@cloudflare/workers-types": "^4.0.0",
"react-router": "workspace:^",
"tsup": "^8.3.0",
"typescript": "^5.1.0"
},
"peerDependenciesMeta": {

@ -1,55 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const typescript = require("@rollup/plugin-typescript");
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
getBuildDirectories,
createBanner,
remixBabelConfig,
WATCH,
} = require("../../rollup.utils");
const { name: packageName, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
packageName,
// We don't live in a folder matching our package name
"react-router-cloudflare"
);
return [
{
external: (id) => isBareModuleId(id),
input: `${SOURCE_DIR}/index.ts`,
output: {
banner: createBanner(packageName, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "named",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -3,10 +3,12 @@ import * as v from "valibot";
import pick from "lodash/pick";
import invariant from "../invariant";
let appDirectory: string;
declare global {
var __reactRouterAppDirectory: string;
}
export function setAppDirectory(directory: string) {
appDirectory = directory;
globalThis.__reactRouterAppDirectory = directory;
}
/**
@ -14,8 +16,8 @@ export function setAppDirectory(directory: string) {
* This is designed to support resolving file system routes.
*/
export function getAppDirectory() {
invariant(appDirectory);
return appDirectory;
invariant(globalThis.__reactRouterAppDirectory);
return globalThis.__reactRouterAppDirectory;
}
export interface RouteManifestEntry {

@ -32,7 +32,25 @@
"react-router": "bin.js"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"cli/**",
"config/**",
"typescript/**",
"vite/**",
"*.ts",
"bin.js",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@babel/core": "^7.21.8",
@ -90,7 +108,10 @@
"react-router": "workspace:^",
"strip-ansi": "^6.0.1",
"tiny-invariant": "^1.2.0",
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"vite": "^5.1.0",
"wireit": "0.14.9",
"wrangler": "^3.28.2"
},
"peerDependencies": {

@ -1,78 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
createBanner,
isBareModuleId,
getBuildDirectories,
remixBabelConfig,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-dev"
);
return [
{
external: isBareModuleId,
input: [
`${SOURCE_DIR}/cli/index.ts`,
`${SOURCE_DIR}/routes.ts`,
`${SOURCE_DIR}/vite.ts`,
`${SOURCE_DIR}/vite/cloudflare.ts`,
`${SOURCE_DIR}/typescript/plugin.ts`,
],
output: {
banner: createBanner("@react-router/dev", version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "auto",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [
{ src: "LICENSE.md", dest: SOURCE_DIR },
{ src: `${SOURCE_DIR}/vite/static`, dest: `${OUTPUT_DIR}/vite` },
{
src: `${SOURCE_DIR}/config/defaults`,
dest: `${OUTPUT_DIR}/config`,
},
],
}),
// Allow dynamic imports in CJS code to allow us to utilize
// ESM modules as part of the compiler.
{
name: "dynamic-import-polyfill",
renderDynamicImport() {
return {
left: "import(",
right: ")",
};
},
},
],
},
];
};

@ -0,0 +1,53 @@
import * as fsp from "fs/promises";
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = [
"cli/index.ts",
"routes.ts",
"vite.ts",
"vite/cloudflare.ts",
"typescript/plugin.ts",
];
const external = ["./static/refresh-utils.cjs"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs"],
outDir: "dist",
dts: true,
external,
banner: {
js: createBanner(pkg.name, pkg.version),
},
plugins: [
{
name: "copy",
async buildEnd() {
await fsp.mkdir("dist/static", { recursive: true });
await fsp.copyFile(
"vite/static/refresh-utils.cjs",
"dist/static/refresh-utils.cjs"
);
await fsp.mkdir("dist/config/defaults", { recursive: true });
const files = await fsp.readdir("config/defaults");
for (const file of files) {
await fsp.copyFile(
`config/defaults/${file}`,
`dist/config/defaults/${file}`
);
}
},
},
],
},
]);

@ -5,7 +5,7 @@ import { type BinaryLike, createHash } from "node:crypto";
import * as path from "node:path";
import * as url from "node:url";
import * as fse from "fs-extra";
import babel from "@babel/core";
import * as babel from "@babel/core";
import {
unstable_setDevServerHooks as setDevServerHooks,
createRequestHandler,
@ -831,6 +831,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = (_config) => {
// Pre-bundle router dependencies to avoid router duplicates.
// Mismatching routers cause `Error: You must render this element inside a <Remix> element`.
"react-router",
"react-router/dom",
// Check to avoid "Failed to resolve dependency: react-router-dom, present in 'optimizeDeps.include'"
...(hasDependency("react-router-dom")
? ["react-router-dom"]
@ -849,6 +850,7 @@ export const reactRouterVitePlugin: ReactRouterVitePlugin = (_config) => {
// see description for `optimizeDeps.include`
"react-router",
"react-router/dom",
"react-router-dom",
],
},

@ -1,7 +0,0 @@
/* eslint-env node */
if (process.env.NODE_ENV === "production") {
module.exports = require("./umd/react-router-dom.production.min.js");
} else {
module.exports = require("./umd/react-router-dom.development.js");
}

@ -24,18 +24,47 @@
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/main.js"
"node": {
"types": "./dist/index.d.ts",
"module-sync": "./dist/index.mjs",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"scripts": {
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"react-router": "workspace:*"
},
"devDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"react": ">=18",

@ -1,223 +0,0 @@
const path = require("path");
const babel = require("@rollup/plugin-babel").default;
const copy = require("rollup-plugin-copy");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const prettier = require("rollup-plugin-prettier");
const replace = require("@rollup/plugin-replace");
const { terser } = require("rollup-plugin-terser");
const typescript = require("@rollup/plugin-typescript");
const {
createBanner,
isBareModuleId,
getBuildDirectories,
PRETTY,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(name);
// JS modules for bundlers
const modules = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/index.mjs`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router DOM", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
extensions: [".ts", ".tsx"],
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
}),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
verbose: true,
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
// JS modules for <script type=module>
const webModules = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/react-router-dom.development.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router DOM", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
"@babel/preset-modules",
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/react-router-dom.production.min.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router DOM", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
[
"@babel/preset-modules",
{
// Don't spoof `.name` for Arrow Functions, which breaks when minified anyway.
loose: true,
},
],
[
"@babel/preset-react",
{
// Compile JSX Spread to Object.assign(), which is reliable in ESM browsers.
useBuiltIns: true,
},
],
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser({ ecma: 8, safari10: true }),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
// UMD modules for <script> tags and CommonJS (node)
const globals = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/umd/react-router-dom.development.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router DOM", version),
globals: {
react: "React",
"react-router": "ReactRouter",
},
name: "ReactRouterDOM",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/umd/react-router-dom.production.min.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
globals: {
react: "React",
"react-router": "ReactRouter",
},
name: "ReactRouterDOM",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: ["babel-plugin-dev-expression"],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
// Node entry points
const node = [
{
input: `${SOURCE_DIR}/node-main.js`,
output: {
file: `${OUTPUT_DIR}/main.js`,
format: "cjs",
banner: createBanner("React Router DOM", version),
},
plugins: [].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
return [...modules, ...webModules, ...globals, ...node];
};
/**
* @typedef {import('rollup').InputOptions} RollupInputOptions
* @typedef {import('rollup').OutputOptions} RollupOutputOptions
* @typedef {import('rollup').RollupOptions} RollupOptions
* @typedef {import('rollup').Plugin} RollupPlugin
*/

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -15,13 +15,37 @@
"typings": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"node": {
"types": "./dist/index.d.ts",
"module-sync": "./dist/index.mjs",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./package.json": "./package.json"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@react-router/node": "workspace:*"
@ -33,7 +57,9 @@
"express": "^4.19.2",
"node-mocks-http": "^1.10.1",
"supertest": "^6.3.3",
"typescript": "^5.1.6"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"express": "^4.17.1",

@ -1,55 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
createBanner,
getBuildDirectories,
remixBabelConfig,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-express"
);
return [
{
external: (id) => isBareModuleId(id),
input: `${SOURCE_DIR}/index.ts`,
output: {
banner: createBanner(name, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "auto",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts", ".tsx"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts", ".tsx"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -21,14 +21,29 @@
"./package.json": "./package.json"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"minimatch": "^9.0.0"
},
"devDependencies": {
"@react-router/dev": "workspace:*",
"typescript": "^5.1.6"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"@react-router/dev": "workspace:^",

@ -1,55 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
createBanner,
getBuildDirectories,
WATCH,
remixBabelConfig,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-fs-routes"
);
return [
{
external: (id) => isBareModuleId(id),
input: `${SOURCE_DIR}/index.ts`,
output: {
banner: createBanner(name, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "auto",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -11,12 +11,38 @@
"directory": "packages/react-router-node"
},
"license": "MIT",
"types": "dist/index.d.ts",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
"node": {
"types": "./dist/index.d.ts",
"module-sync": "./dist/index.mjs",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./install": {
"node": {
"types": "./dist/install.d.ts",
"module-sync": "./dist/install.mjs",
"default": "./dist/install.js"
},
"import": {
"types": "./dist/install.d.mts",
"default": "./dist/install.mjs"
},
"default": {
"types": "./dist/install.d.ts",
"default": "./dist/install.js"
}
},
"./package.json": "./package.json"
},
@ -25,7 +51,21 @@
"./dist/install.mjs"
],
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"sessions/**",
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@web3-storage/multipart-parser": "^1.0.0",
@ -36,7 +76,9 @@
"devDependencies": {
"@types/source-map-support": "^0.5.4",
"react-router": "workspace:*",
"typescript": "^5.1.6"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"react-router": "workspace:*",

@ -1,55 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
createBanner,
getBuildDirectories,
remixBabelConfig,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-node"
);
return [
{
input: `${SOURCE_DIR}/index.ts`,
external: (id) => isBareModuleId(id),
output: {
banner: createBanner(name, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "named",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts", ".tsx"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts", ".tsx"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -13,6 +13,8 @@
"emitDeclarationOnly": true,
"rootDir": ".",
"outDir": "./dist",
"noEmit": true,
"resolveJsonModule": true,
// Avoid naming conflicts between lib.dom.d.ts and globals.ts
"skipLibCheck": true

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts", "install.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs", "esm"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -21,11 +21,26 @@
"./package.json": "./package.json"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"devDependencies": {
"@react-router/dev": "workspace:*",
"typescript": "^5.1.6"
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"@react-router/dev": "workspace:^",

@ -1,55 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
isBareModuleId,
createBanner,
getBuildDirectories,
WATCH,
remixBabelConfig,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-remix-config-routes-adapter"
);
return [
{
external: (id) => isBareModuleId(id),
input: `${SOURCE_DIR}/index.ts`,
output: {
banner: createBanner(name, version),
dir: OUTPUT_DIR,
format: "cjs",
preserveModules: true,
exports: "auto",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -18,7 +18,21 @@
"react-router-serve": "bin.js"
},
"scripts": {
"tsc": "tsc"
"build": "wireit"
},
"wireit": {
"build": {
"command": "tsup",
"files": [
"*.ts",
"bin.js",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@react-router/express": "workspace:*",
@ -36,7 +50,10 @@
"@types/compression": "^1.7.0",
"@types/express": "^4.17.9",
"@types/morgan": "^1.9.2",
"@types/source-map-support": "^0.5.6"
"@types/source-map-support": "^0.5.6",
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"engines": {
"node": ">=20.0.0"

@ -1,63 +0,0 @@
const path = require("node:path");
const babel = require("@rollup/plugin-babel").default;
const typescript = require("@rollup/plugin-typescript");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const copy = require("rollup-plugin-copy");
const {
createBanner,
getBuildDirectories,
remixBabelConfig,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
/** @returns {import("rollup").RollupOptions[]} */
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(
name,
// We don't live in a folder matching our package name
"react-router-serve"
);
return [
{
external() {
return true;
},
input: `${SOURCE_DIR}/cli.ts`,
output: {
banner: createBanner(name, version),
dir: OUTPUT_DIR,
format: "cjs",
},
plugins: [
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
extensions: [".ts"],
...remixBabelConfig,
}),
typescript({
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
nodeResolve({ extensions: [".ts"] }),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
}),
{
name: "dynamic-import-polyfill",
renderDynamicImport() {
return {
left: "import(",
right: ")",
};
},
},
],
},
];
};

@ -0,0 +1,21 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["cli.ts"];
export default defineConfig([
{
clean: true,
entry,
format: ["cjs"],
outDir: "dist",
dts: true,
banner: {
js: createBanner(pkg.name, pkg.version),
},
},
]);

@ -1,4 +1,4 @@
// Expose old @remix-run/router API
// Expose old @remix-run/router API y2
export type { InitialEntry, Location, Path, To } from "./lib/router/history";
export type {
HydrationState,

@ -4,8 +4,6 @@ import * as ReactDOM from "react-dom";
import type { RouterProviderProps as BaseRouterProviderProps } from "react-router";
import { RouterProvider as BaseRouterProvider } from "react-router";
export { HydratedRouter } from "./hydrated-router";
export type RouterProviderProps = Omit<BaseRouterProviderProps, "flushSync">;
export function RouterProvider(props: Omit<RouterProviderProps, "flushSync">) {

@ -38,7 +38,8 @@ import {
stripBasename,
} from "../router/utils";
import "./global";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type * as _ from "./global";
import type {
SubmitOptions,
URLSearchParamsInit,
@ -108,7 +109,9 @@ const isBrowser =
// Core Web Vitals Technology Report. This way they can configure the `wappalyzer`
// to detect and properly classify live websites as being built with React Router:
// https://github.com/HTTPArchive/wappalyzer/blob/main/src/technologies/r.json
const REACT_ROUTER_VERSION = "0";
declare global {
const REACT_ROUTER_VERSION: string;
}
try {
if (isBrowser) {
window.__reactRouterVersion = REACT_ROUTER_VERSION;

@ -1,4 +1,5 @@
import "../global";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type * as _ from "../global";
export async function createRequestInit(
request: Request

@ -239,7 +239,11 @@ export async function loadRouteModule(
}
try {
let routeModule = await import(/* webpackIgnore: true */ route.module);
let routeModule = await import(
/* @vite-ignore */
/* webpackIgnore: true */
route.module
);
routeModulesCache[route.id] = routeModule;
return routeModule;
} catch (error: unknown) {
@ -262,7 +266,7 @@ export async function loadRouteModule(
window.__reactRouterContext &&
window.__reactRouterContext.isSpaMode &&
// @ts-expect-error
typeof import.meta.hot !== "undefined"
import.meta.hot
) {
// In SPA Mode (which implies vite) we don't want to perform a hard reload
// on dev-time errors since it's a vite compilation error and a reload is

@ -18,31 +18,67 @@
"license": "MIT",
"author": "Remix Software <hello@remix.run>",
"sideEffects": false,
"main": "./dist/main.js",
"types": "./dist/index.d.ts",
"main": "./dist/index.js",
"unpkg": "./dist/umd/react-router.production.min.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/main.js"
"node": {
"types": "./dist/index.d.ts",
"module-sync": "./dist/index.mjs",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"default": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"./types": {
"types": "./dist/lib/types.d.ts"
},
"./dom": {
"types": "./dist/dom-export.d.ts",
"import": "./dist/dom-export.mjs",
"require": "./dist/main-dom-export.js"
"node": {
"types": "./dist/dom-export.d.ts",
"module-sync": "./dist/dom-export.mjs",
"default": "./dist/dom-export.js"
},
"import": {
"types": "./dist/dom-export.d.mts",
"default": "./dist/dom-export.mjs"
},
"default": {
"types": "./dist/dom-export.d.ts",
"default": "./dist/dom-export.js"
}
},
"./package.json": "./package.json"
},
"scripts": {
"build": "wireit"
},
"wireit": {
"build": {
"command": "rimraf dist && tsup",
"files": [
"lib/**",
"*.ts",
"tsconfig.json",
"package.json"
],
"output": [
"dist/**"
]
}
},
"dependencies": {
"@types/cookie": "^0.6.0",
"@web3-storage/multipart-parser": "^1.0.0",
"cookie": "^1.0.1",
"react-router": "workspace:*",
"set-cookie-parser": "^2.6.0",
"source-map": "^0.7.3",
"turbo-stream": "2.4.0"
@ -50,7 +86,11 @@
"devDependencies": {
"@types/set-cookie-parser": "^2.4.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"rimraf": "^6.0.1",
"tsup": "^8.3.0",
"typescript": "^5.1.6",
"wireit": "0.14.9"
},
"peerDependencies": {
"react": ">=18",

@ -1,468 +0,0 @@
/* eslint-disable import/no-nodejs-modules */
const path = require("path");
const babel = require("@rollup/plugin-babel").default;
const copy = require("rollup-plugin-copy");
const nodeResolve = require("@rollup/plugin-node-resolve").default;
const prettier = require("rollup-plugin-prettier");
const replace = require("@rollup/plugin-replace");
const { terser } = require("rollup-plugin-terser");
const typescript = require("@rollup/plugin-typescript");
const {
babelPluginReplaceVersionPlaceholder,
createBanner,
isBareModuleId,
getBuildDirectories,
validateReplacedVersion,
PRETTY,
WATCH,
} = require("../../rollup.utils");
const { name, version } = require("./package.json");
module.exports = function rollup() {
const { SOURCE_DIR, OUTPUT_DIR } = getBuildDirectories(name);
// JS modules for bundlers
const modules = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/index.mjs`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
// eslint-disable-next-line no-restricted-globals
tsconfig: path.join(__dirname, "tsconfig.json"),
exclude: ["__tests__"],
noEmitOnError: !WATCH,
noForceEmit: true,
}),
copy({
targets: [{ src: "LICENSE.md", dest: SOURCE_DIR }],
verbose: true,
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/dom-export.tsx`,
output: {
file: `${OUTPUT_DIR}/dom-export.mjs`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
// eslint-disable-next-line no-restricted-globals
tsconfig: path.join(__dirname, "tsconfig.dom.json"),
noEmitOnError: !WATCH,
noForceEmit: true,
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/lib/types.ts`,
output: {
file: `${OUTPUT_DIR}/lib/types.mjs`,
format: "esm",
banner: createBanner("React Router", version),
},
external: isBareModuleId,
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
typescript({
// eslint-disable-next-line no-restricted-globals
tsconfig: path.join(__dirname, "tsconfig.dom.json"),
noEmitOnError: !WATCH,
noForceEmit: true,
}),
],
},
];
// JS modules for <script type=module>
const webModules = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/react-router.development.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
"@babel/preset-modules",
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/react-router.production.min.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
[
"@babel/preset-modules",
{
// Don't spoof `.name` for Arrow Functions, which breaks when minified anyway.
loose: true,
},
],
[
"@babel/preset-react",
{
// Compile JSX Spread to Object.assign(), which is reliable in ESM browsers.
useBuiltIns: true,
},
],
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
validateReplacedVersion(),
terser({ ecma: 8, safari10: true }),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/dom-export.tsx`,
output: {
file: `${OUTPUT_DIR}/react-router-dom.development.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
"@babel/preset-modules",
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/dom-export.tsx`,
output: {
file: `${OUTPUT_DIR}/react-router-dom.production.min.js`,
format: "esm",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
[
"@babel/preset-modules",
{
// Don't spoof `.name` for Arrow Functions, which breaks when minified anyway.
loose: true,
},
],
[
"@babel/preset-react",
{
// Compile JSX Spread to Object.assign(), which is reliable in ESM browsers.
useBuiltIns: true,
},
],
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser({ ecma: 8, safari10: true }),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
// UMD modules for <script> tags and CommonJS (node)
const globals = [
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/umd/react-router.development.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
globals: {
react: "React",
},
name: "ReactRouter",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/index.ts`,
output: {
file: `${OUTPUT_DIR}/umd/react-router.production.min.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
globals: {
react: "React",
},
name: "ReactRouter",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser(),
validateReplacedVersion(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/dom-export.tsx`,
output: {
file: `${OUTPUT_DIR}/umd/react-router-dom.development.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
globals: {
react: "React",
"react-router": "ReactRouter",
},
name: "ReactRouterDOMExport",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("development") },
}),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/dom-export.tsx`,
output: {
file: `${OUTPUT_DIR}/umd/react-router-dom.production.min.js`,
format: "umd",
sourcemap: !PRETTY,
banner: createBanner("React Router", version),
globals: {
react: "React",
"react-router": "ReactRouter",
},
name: "ReactRouterDomExport",
},
external: (id) => isBareModuleId(id),
plugins: [
nodeResolve({ extensions: [".tsx", ".ts"] }),
babel({
babelHelpers: "bundled",
exclude: /node_modules/,
presets: [
["@babel/preset-env", { loose: true }],
"@babel/preset-react",
"@babel/preset-typescript",
],
plugins: [
"babel-plugin-dev-expression",
babelPluginReplaceVersionPlaceholder(),
],
extensions: [".ts", ".tsx"],
}),
replace({
preventAssignment: true,
values: { "process.env.NODE_ENV": JSON.stringify("production") },
}),
terser(),
].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
// Node entry points
const node = [
{
input: `${SOURCE_DIR}/node-main.js`,
output: {
file: `${OUTPUT_DIR}/main.js`,
format: "cjs",
banner: createBanner("React Router", version),
},
plugins: [].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
{
input: `${SOURCE_DIR}/node-main-dom-export.js`,
output: {
file: `${OUTPUT_DIR}/main-dom-export.js`,
format: "cjs",
banner: createBanner("React Router", version),
},
plugins: [].concat(PRETTY ? prettier({ parser: "babel" }) : []),
},
];
return [...modules, ...webModules, ...globals, ...node];
};
/**
* @typedef {import('rollup').InputOptions} RollupInputOptions
* @typedef {import('rollup').OutputOptions} RollupOutputOptions
* @typedef {import('rollup').RollupOptions} RollupOptions
* @typedef {import('rollup').Plugin} RollupPlugin
*/

@ -16,6 +16,11 @@
"skipLibCheck": true,
"outDir": "dist",
"rootDir": "."
"rootDir": ".",
"noEmit": true,
"resolveJsonModule": true,
"paths": {
"react-router": ["./index.ts"]
}
}
}

@ -0,0 +1,44 @@
import { defineConfig } from "tsup";
// @ts-ignore - out of scope
import { createBanner } from "../../build.utils.js";
import pkg from "./package.json";
const entry = ["index.ts", "dom-export.ts", "lib/types.ts"];
export default defineConfig([
{
clean: false,
entry,
format: ["cjs"],
outDir: "dist",
dts: true,
external: [
/*.*/
],
banner: {
js: createBanner(pkg.name, pkg.version),
},
define: {
"import.meta.hot": "undefined",
REACT_ROUTER_VERSION: JSON.stringify(pkg.version),
},
},
{
clean: false,
entry,
format: ["esm"],
outDir: "dist",
dts: true,
external: [
/*.*/
],
banner: {
js: createBanner(pkg.name, pkg.version),
},
define: {
REACT_ROUTER_VERSION: JSON.stringify(pkg.version),
},
},
]);

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save