From 372ff695ab14466f08147e24984a3629da8066cb Mon Sep 17 00:00:00 2001 From: Chance Strickland Date: Tue, 3 May 2022 08:47:58 -0600 Subject: [PATCH] fix(remix-dev): support JSX in `.js` route files (#3059) --- docs/api/conventions.md | 2 +- docs/guides/typescript.md | 4 +-- integration/js-routes-test.ts | 42 +++++++++++++++++++++++++++ packages/remix-dev/compiler/routes.ts | 3 ++ rollup.config.js | 6 ++-- 5 files changed, 50 insertions(+), 7 deletions(-) create mode 100644 integration/js-routes-test.ts diff --git a/docs/api/conventions.md b/docs/api/conventions.md index 23b2d1e29a9..61194de06d0 100644 --- a/docs/api/conventions.md +++ b/docs/api/conventions.md @@ -178,7 +178,7 @@ There are a few conventions that Remix uses you should be aware of. Setting up routes in Remix is as simple as creating files in your `app` directory. These are the conventions you should know to understand how routing in Remix works. -Please note that you can use either `.jsx` or `.tsx` file extensions depending on whether or not you use TypeScript. We'll stick with `.tsx` in the examples to avoid duplication (and because we ❤️ TypeScript). +Please note that you can use either `.js`, `.jsx` or `.tsx` file extensions depending on whether or not you use TypeScript. We'll stick with `.tsx` in the examples to avoid duplication (and because we ❤️ TypeScript). #### Root Layout Route diff --git a/docs/guides/typescript.md b/docs/guides/typescript.md index 2a2eda5e960..8e810b1757e 100644 --- a/docs/guides/typescript.md +++ b/docs/guides/typescript.md @@ -6,9 +6,7 @@ title: TypeScript Remix seamlessly supports both JavaScript and TypeScript. If you name a file with a `.ts` or `.tsx` extension, it will treat it as TypeScript (`.tsx` is for TypeScript files [with JSX](https://www.typescriptlang.org/docs/handbook/jsx.html) in them). But it isn't required. You can write all your files as `.js` files if you don't want TypeScript. -To use JSX without TypeScript, you need to use the `.jsx` extension. - -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: +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=[11] { diff --git a/integration/js-routes-test.ts b/integration/js-routes-test.ts new file mode 100644 index 00000000000..4b3777218b5 --- /dev/null +++ b/integration/js-routes-test.ts @@ -0,0 +1,42 @@ +import { test } from "@playwright/test"; + +import { createAppFixture, createFixture, js } from "./helpers/create-fixture"; +import type { AppFixture } from "./helpers/create-fixture"; +import { PlaywrightFixture } from "./helpers/playwright-fixture"; + +test.describe(".js route files", () => { + let appFixture: AppFixture; + + test.beforeAll(async () => { + appFixture = await createAppFixture( + await createFixture({ + files: { + "app/routes/js.js": js` + export default () =>
Rendered with .js ext
; + `, + "app/routes/jsx.jsx": js` + export default () =>
Rendered with .jsx ext
; + `, + }, + }) + ); + }); + + test.afterAll(async () => { + await appFixture.close(); + }); + + test("should render all .js routes", async ({ page }) => { + let app = new PlaywrightFixture(appFixture, page); + await app.goto("/js"); + await page.waitForSelector("[data-testid='route-js']"); + test.expect(await page.content()).toContain("Rendered with .js ext"); + }); + + test("should render all .jsx routes", async ({ page }) => { + let app = new PlaywrightFixture(appFixture, page); + await app.goto("/jsx"); + await page.waitForSelector("[data-testid='route-jsx']"); + test.expect(await page.content()).toContain("Rendered with .jsx ext"); + }); +}); diff --git a/packages/remix-dev/compiler/routes.ts b/packages/remix-dev/compiler/routes.ts index 06b9f36a595..22764cfb728 100644 --- a/packages/remix-dev/compiler/routes.ts +++ b/packages/remix-dev/compiler/routes.ts @@ -53,6 +53,9 @@ export async function getRouteModuleExports( format: "esm", metafile: true, write: false, + loader: { + ".js": "jsx", + }, logLevel: "silent", plugins: [mdxPlugin(config)], }); diff --git a/rollup.config.js b/rollup.config.js index 35584354ea7..96b38c57b71 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -887,9 +887,9 @@ function copyToPlaygrounds() { await fse.copy(writtenDir, destDir); // tickle live reload by touching the server entry - let serverEntry = ["entry.server.tsx", "entry.server.jsx"].find( - (entryPath) => - fse.existsSync(path.join(playgroundDir, "app", entryPath)) + let serverEntry = ["tsx", "js", "jsx"].find( + (entryPathExtension) => + fse.existsSync(path.join(playgroundDir, "app", `entry.server.${entryPathExtension}`)) ); let serverEntryPath = path.join(playgroundDir, "app", serverEntry); let serverEntryContent = await fse.readFile(serverEntryPath);