From 6e62442778d26d7ce301380fad8be000d51108ed Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Tue, 22 Oct 2024 10:07:53 +0100 Subject: [PATCH] feat(remix): generate remix vite application --- .../remix/generators/application.json | 5 - .../remix/generators/setup-tailwind.json | 5 - package.json | 4 +- packages/remix/migrations.json | 29 ++ packages/remix/package.json | 4 +- .../application.impl.spec.ts.snap | 469 +++++------------- .../application/application.impl.spec.ts | 71 +-- .../application/application.impl.ts | 67 +-- .../files/common/app/entry.client.tsx__tmpl__ | 18 + .../files/common/app/entry.server.tsx__tmpl__ | 140 ++++++ .../files/common/app/root.tsx__tmpl__ | 25 +- .../files/common/remix.config.js__tmpl__ | 17 - .../files/common/remix.env.d.ts__tmpl__ | 2 - .../files/common/tsconfig.app.json__tmpl__ | 7 +- .../files/common/tsconfig.json__tmpl__ | 9 +- .../files/common/vite.config.ts__tmpl__ | 25 + .../files/integrated/package.json__tmpl__ | 7 +- .../src/generators/application/lib/add-e2e.ts | 5 +- .../src/generators/application/schema.d.ts | 1 - .../src/generators/application/schema.json | 5 - .../remix/src/generators/init/init.spec.ts | 8 +- .../preset/lib/normalize-options.ts | 1 - .../src/generators/preset/preset.impl.ts | 1 - .../setup-tailwind.impl.spec.ts.snap | 144 ++---- .../files/postcss.config.js__tpl__ | 6 + .../generators/setup-tailwind/lib/index.ts | 1 - .../lib/update-remix-config.spec.ts | 79 --- .../setup-tailwind/lib/update-remix-config.ts | 48 -- .../src/generators/setup-tailwind/schema.d.ts | 1 - .../src/generators/setup-tailwind/schema.json | 5 - .../setup-tailwind.impl.spec.ts | 28 +- .../setup-tailwind/setup-tailwind.impl.ts | 22 +- .../src/generators/style/style.impl.spec.ts | 15 +- packages/remix/src/plugins/plugin.ts | 11 +- packages/remix/src/utils/remix-config.ts | 54 +- packages/remix/src/utils/remix-route-utils.ts | 8 +- packages/remix/src/utils/versions.ts | 5 +- packages/vite/src/utils/versions.ts | 1 + pnpm-lock.yaml | 59 ++- 39 files changed, 557 insertions(+), 855 deletions(-) create mode 100644 packages/remix/src/generators/application/files/common/app/entry.client.tsx__tmpl__ create mode 100644 packages/remix/src/generators/application/files/common/app/entry.server.tsx__tmpl__ delete mode 100644 packages/remix/src/generators/application/files/common/remix.config.js__tmpl__ delete mode 100644 packages/remix/src/generators/application/files/common/remix.env.d.ts__tmpl__ create mode 100644 packages/remix/src/generators/application/files/common/vite.config.ts__tmpl__ create mode 100644 packages/remix/src/generators/setup-tailwind/files/postcss.config.js__tpl__ delete mode 100644 packages/remix/src/generators/setup-tailwind/lib/index.ts delete mode 100644 packages/remix/src/generators/setup-tailwind/lib/update-remix-config.spec.ts delete mode 100644 packages/remix/src/generators/setup-tailwind/lib/update-remix-config.ts diff --git a/docs/generated/packages/remix/generators/application.json b/docs/generated/packages/remix/generators/application.json index 431fe31f8d75eb..2ddb29ae33ffec 100644 --- a/docs/generated/packages/remix/generators/application.json +++ b/docs/generated/packages/remix/generators/application.json @@ -20,11 +20,6 @@ "description": "The name of the application.", "x-priority": "important" }, - "js": { - "type": "boolean", - "description": "Generate JavaScript files rather than TypeScript files.", - "default": false - }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", diff --git a/docs/generated/packages/remix/generators/setup-tailwind.json b/docs/generated/packages/remix/generators/setup-tailwind.json index 215eca3cdc2514..2b41acb0af06de 100644 --- a/docs/generated/packages/remix/generators/setup-tailwind.json +++ b/docs/generated/packages/remix/generators/setup-tailwind.json @@ -21,11 +21,6 @@ "x-prompt": "What project would you like to add Tailwind to?", "pattern": "^[a-zA-Z].*$" }, - "js": { - "type": "boolean", - "description": "Generate a JavaScript config file instead of a TypeScript config file", - "default": false - }, "skipFormat": { "type": "boolean", "description": "Skip formatting files after generator runs", diff --git a/package.json b/package.json index 4c7f579bb86274..c2951f6aebe38f 100644 --- a/package.json +++ b/package.json @@ -92,8 +92,8 @@ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", "@pnpm/lockfile-types": "^6.0.0", "@reduxjs/toolkit": "1.9.0", - "@remix-run/dev": "^2.8.1", - "@remix-run/node": "^2.8.1", + "@remix-run/dev": "^2.13.1", + "@remix-run/node": "^2.13.1", "@rollup/plugin-babel": "^6.0.4", "@rollup/plugin-commonjs": "^25.0.7", "@rollup/plugin-image": "^3.0.3", diff --git a/packages/remix/migrations.json b/packages/remix/migrations.json index 093b4f237dcc91..6dd420c0aed805 100644 --- a/packages/remix/migrations.json +++ b/packages/remix/migrations.json @@ -131,6 +131,35 @@ "alwaysAddToPackageJson": true } } + }, + "20.1.0": { + "version": "20.1.0-beta.0", + "packages": { + "@remix-run/node": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + }, + "@remix-run/react": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + }, + "@remix-run/serve": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + }, + "@remix-run/dev": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + }, + "@remix-run/css-bundle": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + }, + "@remix-run/eslint-config": { + "version": "^2.13.1", + "alwaysAddToPackageJson": true + } + } } } } diff --git a/packages/remix/package.json b/packages/remix/package.json index dbb01fe77eec7a..b98b902165bf54 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -35,7 +35,9 @@ "tslib": "^2.3.1", "@phenomnomnominal/tsquery": "~5.0.1" }, - "peerDependencies": {}, + "peerDependencies": { + "@remix-run/dev": "^2.13.1" + }, "publishConfig": { "access": "public" }, diff --git a/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap b/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap index 80f44ab280dc32..23338adb44680b 100644 --- a/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap +++ b/packages/remix/src/generators/application/__snapshots__/application.impl.spec.ts.snap @@ -1,36 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Remix Application Integrated Repo --directory should create the application correctly 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo --directory should create the application correctly 2`] = ` -"import type { MetaFunction } from '@remix-run/node'; -import { +"import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react'; +import type { MetaFunction, LinksFunction } from '@remix-run/node'; export const meta: MetaFunction = () => [ { @@ -38,7 +16,20 @@ export const meta: MetaFunction = () => [ }, ]; -export default function App() { +export const links: LinksFunction = () => [ + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -48,18 +39,21 @@ export default function App() { - + {children} - ); } + +export default function App() { + return ; +} " `; -exports[`Remix Application Integrated Repo --directory should create the application correctly 3`] = ` +exports[`Remix Application Integrated Repo --directory should create the application correctly 2`] = ` "import NxWelcome from '../nx-welcome'; export default function Index() { @@ -73,36 +67,14 @@ export default function Index() { `; exports[`Remix Application Integrated Repo --directory should extract the layout directory from the directory options if it exists 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo --directory should extract the layout directory from the directory options if it exists 2`] = ` -"import type { MetaFunction } from '@remix-run/node'; -import { +"import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react'; +import type { MetaFunction, LinksFunction } from '@remix-run/node'; export const meta: MetaFunction = () => [ { @@ -110,7 +82,20 @@ export const meta: MetaFunction = () => [ }, ]; -export default function App() { +export const links: LinksFunction = () => [ + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -120,18 +105,21 @@ export default function App() { - + {children} - ); } + +export default function App() { + return ; +} " `; -exports[`Remix Application Integrated Repo --directory should extract the layout directory from the directory options if it exists 3`] = ` +exports[`Remix Application Integrated Repo --directory should extract the layout directory from the directory options if it exists 2`] = ` "import NxWelcome from '../nx-welcome'; export default function Index() { @@ -239,96 +227,7 @@ export default defineConfig({ " `; -exports[`Remix Application Integrated Repo --js should create the application correctly 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo --js should create the application correctly 2`] = ` -"import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from '@remix-run/react'; -export const meta = () => [ - { - title: 'New Remix App', - }, -]; -export default function App() { - return ( - - - - - - - - - - - - - - - ); -} -" -`; - -exports[`Remix Application Integrated Repo --js should create the application correctly 3`] = ` -"import NxWelcome from '../nx-welcome'; -export default function Index() { - return ( -
- -
- ); -} -" -`; - exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using jest 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using jest 2`] = ` "export default { displayName: 'test', preset: '../jest.preset.js', @@ -341,7 +240,7 @@ exports[`Remix Application Integrated Repo --unitTestRunner should generate the " `; -exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using jest 3`] = ` +exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using jest 2`] = ` "import { installGlobals } from '@remix-run/node'; import '@testing-library/jest-dom/matchers'; installGlobals(); @@ -349,27 +248,6 @@ installGlobals(); `; exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 2`] = ` "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; @@ -400,14 +278,14 @@ export default defineConfig({ " `; -exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 3`] = ` +exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 2`] = ` "import { installGlobals } from '@remix-run/node'; import '@testing-library/jest-dom/matchers'; installGlobals(); " `; -exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 4`] = ` +exports[`Remix Application Integrated Repo --unitTestRunner should generate the correct files for testing using vitest 3`] = ` "{ "extends": "./tsconfig.json", "compilerOptions": { @@ -441,36 +319,14 @@ exports[`Remix Application Integrated Repo --unitTestRunner should generate the `; exports[`Remix Application Integrated Repo should create the application correctly 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Integrated Repo should create the application correctly 2`] = ` -"import type { MetaFunction } from '@remix-run/node'; -import { +"import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react'; +import type { MetaFunction, LinksFunction } from '@remix-run/node'; export const meta: MetaFunction = () => [ { @@ -478,7 +334,20 @@ export const meta: MetaFunction = () => [ }, ]; -export default function App() { +export const links: LinksFunction = () => [ + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -488,18 +357,21 @@ export default function App() { - + {children} - ); } + +export default function App() { + return ; +} " `; -exports[`Remix Application Integrated Repo should create the application correctly 3`] = ` +exports[`Remix Application Integrated Repo should create the application correctly 2`] = ` "import NxWelcome from '../nx-welcome'; export default function Index() { @@ -534,96 +406,7 @@ export default defineConfig({ " `; -exports[`Remix Application Standalone Project Repo --js should create the application correctly 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Standalone Project Repo --js should create the application correctly 2`] = ` -"import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from '@remix-run/react'; -export const meta = () => [ - { - title: 'New Remix App', - }, -]; -export default function App() { - return ( - - - - - - - - - - - - - - - ); -} -" -`; - -exports[`Remix Application Standalone Project Repo --js should create the application correctly 3`] = ` -"import NxWelcome from '../nx-welcome'; -export default function Index() { - return ( -
- -
- ); -} -" -`; - exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 2`] = ` "export default { setupFilesAfterEnv: ['/test-setup.ts'], displayName: 'test', @@ -640,14 +423,14 @@ exports[`Remix Application Standalone Project Repo --unitTestRunner should gener " `; -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 3`] = ` +exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 2`] = ` "import { installGlobals } from '@remix-run/node'; import '@testing-library/jest-dom/matchers'; installGlobals(); " `; -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 4`] = ` +exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using jest 3`] = ` "import { createRemixStub } from '@remix-run/testing'; import { render, screen, waitFor } from '@testing-library/react'; import Index from '../../app/routes/_index'; @@ -668,27 +451,6 @@ test('renders loader data', async () => { `; exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 2`] = ` "/// import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; @@ -719,7 +481,7 @@ export default defineConfig({ " `; -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 3`] = ` +exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 2`] = ` "import { createRemixStub } from '@remix-run/testing'; import { render, screen, waitFor } from '@testing-library/react'; import Index from '../../app/routes/_index'; @@ -739,7 +501,7 @@ test('renders loader data', async () => { " `; -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 4`] = ` +exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 3`] = ` "{ "extends": "./tsconfig.json", "compilerOptions": { @@ -772,7 +534,7 @@ exports[`Remix Application Standalone Project Repo --unitTestRunner should gener " `; -exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 5`] = ` +exports[`Remix Application Standalone Project Repo --unitTestRunner should generate the correct files for testing using vitest 4`] = ` "import { installGlobals } from '@remix-run/node'; import '@testing-library/jest-dom/matchers'; installGlobals(); @@ -780,36 +542,14 @@ installGlobals(); `; exports[`Remix Application Standalone Project Repo should create the application correctly 1`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - -exports[`Remix Application Standalone Project Repo should create the application correctly 2`] = ` -"import type { MetaFunction } from '@remix-run/node'; -import { +"import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react'; +import type { MetaFunction, LinksFunction } from '@remix-run/node'; export const meta: MetaFunction = () => [ { @@ -817,7 +557,20 @@ export const meta: MetaFunction = () => [ }, ]; -export default function App() { +export const links: LinksFunction = () => [ + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -827,18 +580,21 @@ export default function App() { - + {children} - ); } + +export default function App() { + return ; +} " `; -exports[`Remix Application Standalone Project Repo should create the application correctly 3`] = ` +exports[`Remix Application Standalone Project Repo should create the application correctly 2`] = ` "import NxWelcome from '../nx-welcome'; export default function Index() { @@ -851,7 +607,7 @@ export default function Index() { " `; -exports[`Remix Application Standalone Project Repo should create the application correctly 4`] = ` +exports[`Remix Application Standalone Project Repo should create the application correctly 3`] = ` "import { createRemixStub } from '@remix-run/testing'; import { render, screen, waitFor } from '@testing-library/react'; import Index from '../../app/routes/_index'; @@ -871,9 +627,36 @@ test('renders loader data', async () => { " `; -exports[`Remix Application Standalone Project Repo should create the application correctly 5`] = `null`; +exports[`Remix Application Standalone Project Repo should create the application correctly 4`] = ` +"import { vitePlugin as remix } from '@remix-run/dev'; +import { defineConfig } from 'vite'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +declare module '@remix-run/node' { + interface Future { + v3_singleFetch: true; + } +} + +export default defineConfig({ + root: __dirname, + plugins: [ + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + v3_singleFetch: true, + v3_lazyRouteDiscovery: true, + }, + }), + nxViteTsPaths(), + ], +}); +" +`; -exports[`Remix Application Standalone Project Repo should create the application correctly 6`] = ` +exports[`Remix Application Standalone Project Repo should create the application correctly 5`] = ` "{ "root": true, "ignorePatterns": ["!**/*", "build", "public/build"], diff --git a/packages/remix/src/generators/application/application.impl.spec.ts b/packages/remix/src/generators/application/application.impl.spec.ts index 8ba7f29cd75358..7a41eefd1b4695 100644 --- a/packages/remix/src/generators/application/application.impl.spec.ts +++ b/packages/remix/src/generators/application/application.impl.spec.ts @@ -30,7 +30,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, '.'); - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); + expect(tree.exists('remix.config.js')).toBeFalsy(); expect(tree.read('app/root.tsx', 'utf-8')).toMatchSnapshot(); expect(tree.read('app/routes/_index.tsx', 'utf-8')).toMatchSnapshot(); expect( @@ -40,29 +40,6 @@ describe('Remix Application', () => { expect(tree.read('.eslintrc.json', 'utf-8')).toMatchSnapshot(); }); - describe(`--js`, () => { - it('should create the application correctly', async () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace(); - - // ACT - await applicationGenerator(tree, { - name: 'test', - directory: '.', - js: true, - rootProject: true, - addPlugin: true, - }); - - // ASSERT - expectTargetsToBeCorrect(tree, '.'); - - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); - expect(tree.read('app/root.js', 'utf-8')).toMatchSnapshot(); - expect(tree.read('app/routes/_index.js', 'utf-8')).toMatchSnapshot(); - }); - }); - describe('--unitTestRunner', () => { it('should generate the correct files for testing using vitest', async () => { // ARRANGE @@ -80,7 +57,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, '.'); - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); + expect(tree.exists('remix.config.js')).toBeFalsy(); expect(tree.read('vitest.config.ts', 'utf-8')).toMatchSnapshot(); expect( tree.read('tests/routes/_index.spec.tsx', 'utf-8') @@ -105,7 +82,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, '.'); - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); + expect(tree.exists('remix.config.js')).toBeFalsy(); expect(tree.read('jest.config.ts', 'utf-8')).toMatchSnapshot(); expect(tree.read('test-setup.ts', 'utf-8')).toMatchSnapshot(); expect( @@ -186,37 +163,13 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, appDir); - expect(tree.read(`${appDir}/remix.config.js`, 'utf-8')).toMatchSnapshot(); + expect(tree.exists(`${appDir}/remix.config.js`)).toBeFalsy(); expect(tree.read(`${appDir}/app/root.tsx`, 'utf-8')).toMatchSnapshot(); expect( tree.read(`${appDir}/app/routes/_index.tsx`, 'utf-8') ).toMatchSnapshot(); }); - describe('--js', () => { - it('should create the application correctly', async () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); - - // ACT - await applicationGenerator(tree, { - directory: 'test', - js: true, - addPlugin: true, - }); - - // ASSERT - expectTargetsToBeCorrect(tree, appDir); - - expect( - tree.read(`${appDir}/remix.config.js`, 'utf-8') - ).toMatchSnapshot(); - expect(tree.read(`${appDir}/app/root.js`, 'utf-8')).toMatchSnapshot(); - expect( - tree.read(`${appDir}/app/routes/_index.js`, 'utf-8') - ).toMatchSnapshot(); - }); - }); describe('--directory', () => { it('should create the application correctly', async () => { // ARRANGE @@ -233,9 +186,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, newAppDir); - expect( - tree.read(`${newAppDir}/remix.config.js`, 'utf-8') - ).toMatchSnapshot(); + expect(tree.exists(`${newAppDir}/remix.config.js`)).toBeFalsy(); expect( tree.read(`${newAppDir}/app/root.tsx`, 'utf-8') ).toMatchSnapshot(); @@ -259,9 +210,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, newAppDir); - expect( - tree.read(`${newAppDir}/remix.config.js`, 'utf-8') - ).toMatchSnapshot(); + expect(tree.exists(`${newAppDir}/remix.config.js`)).toBeFalsy(); expect( tree.read(`${newAppDir}/app/root.tsx`, 'utf-8') ).toMatchSnapshot(); @@ -286,9 +235,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, appDir); - expect( - tree.read(`${appDir}/remix.config.js`, 'utf-8') - ).toMatchSnapshot(); + expect(tree.exists(`${appDir}/remix.config.js`)).toBeFalsy(); expect( tree.read(`${appDir}/vitest.config.ts`, 'utf-8') ).toMatchSnapshot(); @@ -312,9 +259,7 @@ describe('Remix Application', () => { // ASSERT expectTargetsToBeCorrect(tree, appDir); - expect( - tree.read(`${appDir}/remix.config.js`, 'utf-8') - ).toMatchSnapshot(); + expect(tree.exists(`${appDir}/remix.config.js`)).toBeFalsy(); expect( tree.read(`${appDir}/jest.config.ts`, 'utf-8') ).toMatchSnapshot(); diff --git a/packages/remix/src/generators/application/application.impl.ts b/packages/remix/src/generators/application/application.impl.ts index ad6acdf5405dba..2a4edf2ad1f7bc 100644 --- a/packages/remix/src/generators/application/application.impl.ts +++ b/packages/remix/src/generators/application/application.impl.ts @@ -4,19 +4,16 @@ import { formatFiles, generateFiles, GeneratorCallback, - getPackageManagerCommand, joinPathFragments, offsetFromRoot, readJson, readProjectConfiguration, runTasksInSerial, - toJS, Tree, updateJson, updateProjectConfiguration, visitNotIgnoredFiles, } from '@nx/devkit'; -import { addBuildTargetDefaults } from '@nx/devkit/src/generators/target-defaults-utils'; import { logShowProjectCommand } from '@nx/devkit/src/utils/log-show-project-command'; import { initGenerator as jsInitGenerator } from '@nx/js'; import { extractTsConfigBase } from '@nx/js/src/utils/typescript/create-ts-config'; @@ -37,6 +34,7 @@ import { typescriptVersion, typesReactDomVersion, typesReactVersion, + viteVersion, } from '../../utils/versions'; import initGenerator from '../init/init'; import { updateDependencies } from '../utils/update-dependencies'; @@ -48,7 +46,7 @@ export function remixApplicationGenerator( options: NxRemixGeneratorSchema ) { return remixApplicationGeneratorInternal(tree, { - addPlugin: false, + addPlugin: true, ...options, }); } @@ -60,62 +58,26 @@ export async function remixApplicationGeneratorInternal( assertNotUsingTsSolutionSetup(tree, 'remix', 'application'); const options = await normalizeOptions(tree, _options); + if (!options.addPlugin) { + throw new Error( + `To generate a new Remix Vite application, you must use Inference Plugins. Check you do not have NX_ADD_PLUGINS=false or useInferencePlugins: false in your nx.json.` + ); + } + const tasks: GeneratorCallback[] = [ await initGenerator(tree, { skipFormat: true, - addPlugin: options.addPlugin, + addPlugin: true, }), await jsInitGenerator(tree, { skipFormat: true }), ]; - addBuildTargetDefaults(tree, '@nx/remix:build'); - addProjectConfiguration(tree, options.projectName, { root: options.projectRoot, sourceRoot: `${options.projectRoot}`, projectType: 'application', tags: options.parsedTags, - targets: !options.addPlugin - ? { - build: { - executor: '@nx/remix:build', - outputs: ['{options.outputPath}'], - options: { - outputPath: joinPathFragments('dist', options.projectRoot), - }, - }, - serve: { - executor: `@nx/remix:serve`, - options: { - command: `${ - getPackageManagerCommand().exec - } remix-serve build/index.js`, - manual: true, - port: 4200, - }, - }, - start: { - dependsOn: ['build'], - command: `remix-serve build/index.js`, - options: { - cwd: options.projectRoot, - }, - }, - ['serve-static']: { - dependsOn: ['build'], - command: `remix-serve build/index.js`, - options: { - cwd: options.projectRoot, - }, - }, - typecheck: { - command: `tsc --project tsconfig.app.json`, - options: { - cwd: options.projectRoot, - }, - }, - } - : {}, + targets: {}, }); const installTask = updateDependencies(tree); @@ -142,6 +104,7 @@ export async function remixApplicationGeneratorInternal( typesReactDomVersion, eslintVersion, typescriptVersion, + viteVersion, }; generateFiles( @@ -186,7 +149,7 @@ export async function remixApplicationGeneratorInternal( skipFormat: true, testEnvironment: 'jsdom', skipViteConfig: true, - addPlugin: options.addPlugin, + addPlugin: true, }); createOrEditViteConfig( tree, @@ -216,7 +179,7 @@ export async function remixApplicationGeneratorInternal( skipSerializers: false, skipPackageJson: false, skipFormat: true, - addPlugin: options.addPlugin, + addPlugin: true, }); const projectConfig = readProjectConfiguration(tree, options.projectName); if (projectConfig.targets['test']?.options) { @@ -267,10 +230,6 @@ export async function remixApplicationGeneratorInternal( ]); } - if (options.js) { - toJS(tree); - } - if (options.rootProject && tree.exists('tsconfig.base.json')) { // If this is a standalone project, merge tsconfig.json and tsconfig.base.json. const tsConfigBaseJson = readJson(tree, 'tsconfig.base.json'); diff --git a/packages/remix/src/generators/application/files/common/app/entry.client.tsx__tmpl__ b/packages/remix/src/generators/application/files/common/app/entry.client.tsx__tmpl__ new file mode 100644 index 00000000000000..94d5dc0de0fa3a --- /dev/null +++ b/packages/remix/src/generators/application/files/common/app/entry.client.tsx__tmpl__ @@ -0,0 +1,18 @@ +/** + * By default, Remix will handle hydrating your app on the client for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.client + */ + +import { RemixBrowser } from "@remix-run/react"; +import { startTransition, StrictMode } from "react"; +import { hydrateRoot } from "react-dom/client"; + +startTransition(() => { + hydrateRoot( + document, + + + + ); +}); diff --git a/packages/remix/src/generators/application/files/common/app/entry.server.tsx__tmpl__ b/packages/remix/src/generators/application/files/common/app/entry.server.tsx__tmpl__ new file mode 100644 index 00000000000000..45db3229c68af0 --- /dev/null +++ b/packages/remix/src/generators/application/files/common/app/entry.server.tsx__tmpl__ @@ -0,0 +1,140 @@ +/** + * By default, Remix will handle generating the HTTP Response for you. + * You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ + * For more information, see https://remix.run/file-conventions/entry.server + */ + +import { PassThrough } from "node:stream"; + +import type { AppLoadContext, EntryContext } from "@remix-run/node"; +import { createReadableStreamFromReadable } from "@remix-run/node"; +import { RemixServer } from "@remix-run/react"; +import { isbot } from "isbot"; +import { renderToPipeableStream } from "react-dom/server"; + +const ABORT_DELAY = 5_000; + +export default function handleRequest( + request: Request, + 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") || "") + ? handleBotRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ) + : handleBrowserRequest( + request, + responseStatusCode, + responseHeaders, + remixContext + ); +} + +function handleBotRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onAllReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} + +function handleBrowserRequest( + request: Request, + responseStatusCode: number, + responseHeaders: Headers, + remixContext: EntryContext +) { + return new Promise((resolve, reject) => { + let shellRendered = false; + const { pipe, abort } = renderToPipeableStream( + , + { + onShellReady() { + shellRendered = true; + const body = new PassThrough(); + const stream = createReadableStreamFromReadable(body); + + responseHeaders.set("Content-Type", "text/html"); + + resolve( + new Response(stream, { + headers: responseHeaders, + status: responseStatusCode, + }) + ); + + pipe(body); + }, + onShellError(error: unknown) { + reject(error); + }, + onError(error: unknown) { + responseStatusCode = 500; + // Log streaming rendering errors from inside the shell. Don't log + // errors encountered during initial shell rendering since they'll + // reject and get logged in handleDocumentRequest. + if (shellRendered) { + console.error(error); + } + }, + } + ); + + setTimeout(abort, ABORT_DELAY); + }); +} diff --git a/packages/remix/src/generators/application/files/common/app/root.tsx__tmpl__ b/packages/remix/src/generators/application/files/common/app/root.tsx__tmpl__ index 7b97b10c540dac..f2bcdcbcb366e6 100644 --- a/packages/remix/src/generators/application/files/common/app/root.tsx__tmpl__ +++ b/packages/remix/src/generators/application/files/common/app/root.tsx__tmpl__ @@ -1,18 +1,30 @@ -import type { MetaFunction } from "@remix-run/node"; import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from "@remix-run/react"; +import type { MetaFunction, LinksFunction } from "@remix-run/node"; export const meta: MetaFunction = () => ([{ title: "New Remix App", }]); -export default function App() { +export const links: LinksFunction = () => [ + { rel: "preconnect", href: "https://fonts.googleapis.com" }, + { + rel: "preconnect", + href: "https://fonts.gstatic.com", + crossOrigin: "anonymous", + }, + { + rel: "stylesheet", + href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap", + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -22,11 +34,14 @@ export default function App() { - + {children} - ); } + +export default function App() { + return ; +} diff --git a/packages/remix/src/generators/application/files/common/remix.config.js__tmpl__ b/packages/remix/src/generators/application/files/common/remix.config.js__tmpl__ deleted file mode 100644 index eb50539c38210d..00000000000000 --- a/packages/remix/src/generators/application/files/common/remix.config.js__tmpl__ +++ /dev/null @@ -1,17 +0,0 @@ -import {createWatchPaths} from '@nx/remix'; -import {dirname} from 'path'; -import {fileURLToPath} from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - ignoredRouteFiles: ["**/.*"], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; diff --git a/packages/remix/src/generators/application/files/common/remix.env.d.ts__tmpl__ b/packages/remix/src/generators/application/files/common/remix.env.d.ts__tmpl__ deleted file mode 100644 index dcf8c45e1d4cf6..00000000000000 --- a/packages/remix/src/generators/application/files/common/remix.env.d.ts__tmpl__ +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/packages/remix/src/generators/application/files/common/tsconfig.app.json__tmpl__ b/packages/remix/src/generators/application/files/common/tsconfig.app.json__tmpl__ index 2d7e289f966107..72fbe340e2c3b1 100644 --- a/packages/remix/src/generators/application/files/common/tsconfig.app.json__tmpl__ +++ b/packages/remix/src/generators/application/files/common/tsconfig.app.json__tmpl__ @@ -1,11 +1,14 @@ { "extends": "./tsconfig.json", "include": [ - "remix.env.d.ts", "app/**/*.ts", "app/**/*.tsx", "app/**/*.js", - "app/**/*.jsx" + "app/**/*.jsx", + "**/.server/**/*.ts", + "**/.server/**/*.tsx", + "**/.client/**/*.ts", + "**/.client/**/*.tsx" ], "exclude": [ "tests/**/*.spec.ts", diff --git a/packages/remix/src/generators/application/files/common/tsconfig.json__tmpl__ b/packages/remix/src/generators/application/files/common/tsconfig.json__tmpl__ index 99c99823c327a2..2166bde140a258 100644 --- a/packages/remix/src/generators/application/files/common/tsconfig.json__tmpl__ +++ b/packages/remix/src/generators/application/files/common/tsconfig.json__tmpl__ @@ -2,16 +2,19 @@ "extends": "<%= offsetFromRoot %>tsconfig.base.json", "compilerOptions": { "lib": ["DOM", "DOM.Iterable", "ES2019"], + "types": ["@remix-run/node", "vite/client"], "isolatedModules": true, "esModuleInterop": true, "jsx": "react-jsx", - "moduleResolution": "node", + "module": "ESNext", + "moduleResolution": "Bundler", "resolveJsonModule": true, - "target": "ES2019", + "target": "ES2022", "strict": true, "allowJs": true, + "skipLibCheck": true, "forceConsistentCasingInFileNames": true, - // Remix takes care of building everything in `remix build`. + // Vite takes care of building everything. "noEmit": true }, "include": [], diff --git a/packages/remix/src/generators/application/files/common/vite.config.ts__tmpl__ b/packages/remix/src/generators/application/files/common/vite.config.ts__tmpl__ new file mode 100644 index 00000000000000..a79433a5900c1c --- /dev/null +++ b/packages/remix/src/generators/application/files/common/vite.config.ts__tmpl__ @@ -0,0 +1,25 @@ +import { vitePlugin as remix } from '@remix-run/dev'; +import { defineConfig } from 'vite'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +declare module '@remix-run/node' { + interface Future { + v3_singleFetch: true; + } +} + +export default defineConfig({ + root: __dirname, + plugins: [ + remix({ + future: { + v3_fetcherPersist: true, + v3_relativeSplatPath: true, + v3_throwAbortReason: true, + v3_singleFetch: true, + v3_lazyRouteDiscovery: true, + }, + }), + nxViteTsPaths(), + ], +}); diff --git a/packages/remix/src/generators/application/files/integrated/package.json__tmpl__ b/packages/remix/src/generators/application/files/integrated/package.json__tmpl__ index 8b3736be1414ce..ea1aab3d4d4414 100644 --- a/packages/remix/src/generators/application/files/integrated/package.json__tmpl__ +++ b/packages/remix/src/generators/application/files/integrated/package.json__tmpl__ @@ -1,8 +1,6 @@ { "private": true, "name": "<%= projectName %>", - "description": "", - "license": "", "scripts": {}, "type": "module", "dependencies": { @@ -18,10 +16,11 @@ "@types/react": "<%= typesReactVersion %>", "@types/react-dom": "<%= typesReactDomVersion %>", "eslint": "<%= eslintVersion %>", - "typescript": "<%= typescriptVersion %>" + "typescript": "<%= typescriptVersion %>", + "vite": "<%= viteVersion %>", }, "engines": { - "node": ">=14" + "node": ">=20" }, "sideEffects": false } diff --git a/packages/remix/src/generators/application/lib/add-e2e.ts b/packages/remix/src/generators/application/lib/add-e2e.ts index 303a271bc3c4c2..f496b1fd940a75 100644 --- a/packages/remix/src/generators/application/lib/add-e2e.ts +++ b/packages/remix/src/generators/application/lib/add-e2e.ts @@ -83,10 +83,7 @@ export async function addE2E(tree: Tree, options: NormalizedSchema) { tree, '@nx/cypress/plugin', buildTarget, - joinPathFragments( - options.e2eProjectRoot, - `cypress.config.${options.js ? 'js' : 'ts'}` - ) + joinPathFragments(options.e2eProjectRoot, `cypress.config.ts`) ); } diff --git a/packages/remix/src/generators/application/schema.d.ts b/packages/remix/src/generators/application/schema.d.ts index e3a31477a1fcff..ddecf258963eb2 100644 --- a/packages/remix/src/generators/application/schema.d.ts +++ b/packages/remix/src/generators/application/schema.d.ts @@ -4,7 +4,6 @@ export interface NxRemixGeneratorSchema { directory: string; name?: string; tags?: string; - js?: boolean; linter?: Linter | LinterType; unitTestRunner?: 'vitest' | 'jest' | 'none'; e2eTestRunner?: 'cypress' | 'playwright' | 'none'; diff --git a/packages/remix/src/generators/application/schema.json b/packages/remix/src/generators/application/schema.json index 4992be7de5f470..0a133441750caa 100644 --- a/packages/remix/src/generators/application/schema.json +++ b/packages/remix/src/generators/application/schema.json @@ -20,11 +20,6 @@ "description": "The name of the application.", "x-priority": "important" }, - "js": { - "type": "boolean", - "description": "Generate JavaScript files rather than TypeScript files.", - "default": false - }, "linter": { "description": "The tool to use for running lint checks.", "type": "string", diff --git a/packages/remix/src/generators/init/init.spec.ts b/packages/remix/src/generators/init/init.spec.ts index b75cc510edad4e..8fc1d44e83ef14 100644 --- a/packages/remix/src/generators/init/init.spec.ts +++ b/packages/remix/src/generators/init/init.spec.ts @@ -18,13 +18,13 @@ describe('Remix Init Generator', () => { const pkgJson = readJson(tree, 'package.json'); expect(pkgJson.dependencies).toMatchInlineSnapshot(` { - "@remix-run/serve": "^2.8.1", + "@remix-run/serve": "^2.13.1", } `); expect(pkgJson.devDependencies).toMatchInlineSnapshot(` { "@nx/web": "0.0.1", - "@remix-run/dev": "^2.8.1", + "@remix-run/dev": "^2.13.1", } `); @@ -70,13 +70,13 @@ describe('Remix Init Generator', () => { const pkgJson = readJson(tree, 'package.json'); expect(pkgJson.dependencies).toMatchInlineSnapshot(` { - "@remix-run/serve": "^2.8.1", + "@remix-run/serve": "^2.13.1", } `); expect(pkgJson.devDependencies).toMatchInlineSnapshot(` { "@nx/web": "0.0.1", - "@remix-run/dev": "^2.8.1", + "@remix-run/dev": "^2.13.1", } `); }); diff --git a/packages/remix/src/generators/preset/lib/normalize-options.ts b/packages/remix/src/generators/preset/lib/normalize-options.ts index 7ebd7f54470ee1..79bee819d63ecf 100644 --- a/packages/remix/src/generators/preset/lib/normalize-options.ts +++ b/packages/remix/src/generators/preset/lib/normalize-options.ts @@ -7,7 +7,6 @@ export interface NormalizedSchema extends RemixGeneratorSchema { parsedTags: string[]; unitTestRunner?: 'jest' | 'none' | 'vitest'; e2eTestRunner?: 'cypress' | 'none'; - js?: boolean; } export function normalizeOptions( diff --git a/packages/remix/src/generators/preset/preset.impl.ts b/packages/remix/src/generators/preset/preset.impl.ts index c023fe203a4b12..3a303053b5d243 100644 --- a/packages/remix/src/generators/preset/preset.impl.ts +++ b/packages/remix/src/generators/preset/preset.impl.ts @@ -26,7 +26,6 @@ export default async function (tree: Tree, _options: RemixGeneratorSchema) { rootProject: true, unitTestRunner: options.unitTestRunner ?? 'vitest', e2eTestRunner: options.e2eTestRunner ?? 'cypress', - js: options.js ?? false, addPlugin: addPluginDefault, }); tasks.push(appGenTask); diff --git a/packages/remix/src/generators/setup-tailwind/__snapshots__/setup-tailwind.impl.spec.ts.snap b/packages/remix/src/generators/setup-tailwind/__snapshots__/setup-tailwind.impl.spec.ts.snap index 3d9139aa130d47..899be3df978b41 100644 --- a/packages/remix/src/generators/setup-tailwind/__snapshots__/setup-tailwind.impl.spec.ts.snap +++ b/packages/remix/src/generators/setup-tailwind/__snapshots__/setup-tailwind.impl.spec.ts.snap @@ -1,86 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`setup-tailwind generator should add a js tailwind config to an application correctly 1`] = ` -"import { createGlobPatternsForDependencies } from '@nx/react/tailwind'; -export default { - content: [ - './app/**/*.{js,jsx,ts,tsx}', - ...createGlobPatternsForDependencies(__dirname), - ], - theme: { - extend: {}, - }, - plugins: [], -}; -" -`; - -exports[`setup-tailwind generator should add a js tailwind config to an application correctly 2`] = ` -"@tailwind base; -@tailwind components; -@tailwind utilities; -" -`; - -exports[`setup-tailwind generator should add a js tailwind config to an application correctly 3`] = ` -"import { - Links, - LiveReload, - Meta, - Outlet, - Scripts, - ScrollRestoration, -} from '@remix-run/react'; -import twStyles from './tailwind.css'; -export const links = () => [{ rel: 'stylesheet', href: twStyles }]; -export const meta = () => [ - { - title: 'New Remix App', - }, -]; -export default function App() { - return ( - - - - - - - - - - - - - - - ); -} -" -`; - -exports[`setup-tailwind generator should add a js tailwind config to an application correctly 4`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; - -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - tailwind: true, - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; -" -`; - exports[`setup-tailwind generator should add a tailwind config to an application correctly 1`] = ` "import type { Config } from 'tailwindcss'; import { createGlobPatternsForDependencies } from '@nx/react/tailwind'; @@ -99,26 +18,32 @@ export default { `; exports[`setup-tailwind generator should add a tailwind config to an application correctly 2`] = ` +"export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; +" +`; + +exports[`setup-tailwind generator should add a tailwind config to an application correctly 3`] = ` "@tailwind base; @tailwind components; @tailwind utilities; " `; -exports[`setup-tailwind generator should add a tailwind config to an application correctly 3`] = ` -"import type { MetaFunction, LinksFunction } from '@remix-run/node'; -import { +exports[`setup-tailwind generator should add a tailwind config to an application correctly 4`] = ` +"import { Links, - LiveReload, Meta, Outlet, Scripts, ScrollRestoration, } from '@remix-run/react'; +import type { MetaFunction, LinksFunction } from '@remix-run/node'; import twStyles from './tailwind.css'; -export const links: LinksFunction = () => [ - { rel: 'stylesheet', href: twStyles }, -]; export const meta: MetaFunction = () => [ { @@ -126,7 +51,21 @@ export const meta: MetaFunction = () => [ }, ]; -export default function App() { +export const links: LinksFunction = () => [ + { rel: 'stylesheet', href: twStyles }, + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, +]; + +export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -136,35 +75,16 @@ export default function App() { - + {children} - ); } -" -`; - -exports[`setup-tailwind generator should add a tailwind config to an application correctly 4`] = ` -"import { createWatchPaths } from '@nx/remix'; -import { dirname } from 'path'; -import { fileURLToPath } from 'url'; -const __dirname = dirname(fileURLToPath(import.meta.url)); - -/** - * @type {import('@remix-run/dev').AppConfig} - */ -export default { - tailwind: true, - ignoredRouteFiles: ['**/.*'], - // appDirectory: "app", - // assetsBuildDirectory: "public/build", - // serverBuildPath: "build/index.js", - // publicPath: "/build/", - watchPaths: () => createWatchPaths(__dirname), -}; +export default function App() { + return ; +} " `; diff --git a/packages/remix/src/generators/setup-tailwind/files/postcss.config.js__tpl__ b/packages/remix/src/generators/setup-tailwind/files/postcss.config.js__tpl__ new file mode 100644 index 00000000000000..2aa7205d4b402a --- /dev/null +++ b/packages/remix/src/generators/setup-tailwind/files/postcss.config.js__tpl__ @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/packages/remix/src/generators/setup-tailwind/lib/index.ts b/packages/remix/src/generators/setup-tailwind/lib/index.ts deleted file mode 100644 index f614834a1bba88..00000000000000 --- a/packages/remix/src/generators/setup-tailwind/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './update-remix-config'; diff --git a/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.spec.ts b/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.spec.ts deleted file mode 100644 index 5589194eba1737..00000000000000 --- a/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.spec.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { stripIndents } from '@nx/devkit'; -import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; -import { updateRemixConfig } from './update-remix-config'; - -describe('updateRemixConfig', () => { - it('should add tailwind property to an existing config that doesnt have it', () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace(); - tree.write( - `remix.config.js`, - stripIndents`module.exports = { - ignoredRouteFiles: ['**/.*'], - watchPaths: ['../../libs'] - };` - ); - - // ACT - updateRemixConfig(tree, '.'); - - // ASSERT - expect(tree.read('remix.config.js', 'utf-8')).toMatchInlineSnapshot(` - "module.exports = { - tailwind: true, - ignoredRouteFiles: ['**/.*'], - watchPaths: ['../../libs'] - };" - `); - }); - - it('should update tailwind property if the config has it and set to false', () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace(); - tree.write( - `remix.config.js`, - stripIndents`module.exports = { - ignoredRouteFiles: ['**/.*'], - tailwind: false, - watchPaths: ['../../libs'] - };` - ); - - // ACT - updateRemixConfig(tree, '.'); - - // ASSERT - expect(tree.read('remix.config.js', 'utf-8')).toMatchInlineSnapshot(` - "module.exports = { - ignoredRouteFiles: ['**/.*'], - tailwind: true, - watchPaths: ['../../libs'] - };" - `); - }); - - it('should not update tailwind property if the config has it and set to true', () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace(); - tree.write( - `remix.config.js`, - stripIndents`module.exports = { - ignoredRouteFiles: ['**/.*'], - tailwind: true, - watchPaths: ['../../libs'] - };` - ); - - // ACT - updateRemixConfig(tree, '.'); - - // ASSERT - expect(tree.read('remix.config.js', 'utf-8')).toMatchInlineSnapshot(` - "module.exports = { - ignoredRouteFiles: ['**/.*'], - tailwind: true, - watchPaths: ['../../libs'] - };" - `); - }); -}); diff --git a/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.ts b/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.ts deleted file mode 100644 index 22189d93582d91..00000000000000 --- a/packages/remix/src/generators/setup-tailwind/lib/update-remix-config.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { joinPathFragments, type Tree } from '@nx/devkit'; -import { tsquery } from '@phenomnomnominal/tsquery'; -import { getRemixConfigPathFromProjectRoot } from '../../../utils/remix-config'; - -export function updateRemixConfig(tree: Tree, projectRoot: string) { - const pathToRemixConfig = getRemixConfigPathFromProjectRoot( - tree, - projectRoot - ); - const fileContents = tree.read(pathToRemixConfig, 'utf-8'); - - const REMIX_CONFIG_OBJECT_SELECTOR = 'ObjectLiteralExpression'; - const ast = tsquery.ast(fileContents); - - const nodes = tsquery(ast, REMIX_CONFIG_OBJECT_SELECTOR, { - visitAllChildren: true, - }); - if (nodes.length === 0) { - throw new Error(`Remix Config is not valid, unable to update the file.`); - } - - const configObjectNode = nodes[0]; - - const propertyNodes = tsquery(configObjectNode, 'PropertyAssignment', { - visitAllChildren: true, - }); - - for (const propertyNode of propertyNodes) { - const nodeText = propertyNode.getText(); - if (nodeText.includes('tailwind') && nodeText.includes('true')) { - return; - } else if (nodeText.includes('tailwind') && nodeText.includes('false')) { - const updatedFileContents = `${fileContents.slice( - 0, - propertyNode.getStart() - )}tailwind: true${fileContents.slice(propertyNode.getEnd())}`; - tree.write(pathToRemixConfig, updatedFileContents); - return; - } - } - - const updatedFileContents = `${fileContents.slice( - 0, - configObjectNode.getStart() + 1 - )}\ntailwind: true,${fileContents.slice(configObjectNode.getStart() + 1)}`; - - tree.write(pathToRemixConfig, updatedFileContents); -} diff --git a/packages/remix/src/generators/setup-tailwind/schema.d.ts b/packages/remix/src/generators/setup-tailwind/schema.d.ts index 2a098d99ba4166..a15c80d58df520 100644 --- a/packages/remix/src/generators/setup-tailwind/schema.d.ts +++ b/packages/remix/src/generators/setup-tailwind/schema.d.ts @@ -1,5 +1,4 @@ export interface SetupTailwindSchema { project: string; - js?: boolean; skipFormat?: boolean; } diff --git a/packages/remix/src/generators/setup-tailwind/schema.json b/packages/remix/src/generators/setup-tailwind/schema.json index 01827985c55315..9b49050ae7d2ac 100644 --- a/packages/remix/src/generators/setup-tailwind/schema.json +++ b/packages/remix/src/generators/setup-tailwind/schema.json @@ -20,11 +20,6 @@ "x-prompt": "What project would you like to add Tailwind to?", "pattern": "^[a-zA-Z].*$" }, - "js": { - "type": "boolean", - "description": "Generate a JavaScript config file instead of a TypeScript config file", - "default": false - }, "skipFormat": { "type": "boolean", "description": "Skip formatting files after generator runs", diff --git a/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.spec.ts b/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.spec.ts index 1a5fc07d7fe806..d4d1472cc53483 100644 --- a/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.spec.ts +++ b/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.spec.ts @@ -21,35 +21,11 @@ describe('setup-tailwind generator', () => { // ASSERT expect(tree.exists('tailwind.config.ts')).toBeTruthy(); expect(tree.read('tailwind.config.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.exists('postcss.config.js')).toBeTruthy(); + expect(tree.read('postcss.config.js', 'utf-8')).toMatchSnapshot(); expect(tree.exists('app/tailwind.css')).toBeTruthy(); expect(tree.read('app/tailwind.css', 'utf-8')).toMatchSnapshot(); expect(tree.read('app/root.tsx', 'utf-8')).toMatchSnapshot(); - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); - expect( - readJson(tree, 'package.json').dependencies['tailwindcss'] - ).toBeTruthy(); - }); - - it('should add a js tailwind config to an application correctly', async () => { - // ARRANGE - const tree = createTreeWithEmptyWorkspace(); - await applicationGenerator(tree, { - name: 'test', - directory: '.', - js: true, - rootProject: true, - }); - - // ACT - await setupTailwind(tree, { project: 'test', js: true }); - - // ASSERT - expect(tree.exists('tailwind.config.js')).toBeTruthy(); - expect(tree.read('tailwind.config.js', 'utf-8')).toMatchSnapshot(); - expect(tree.exists('app/tailwind.css')).toBeTruthy(); - expect(tree.read('app/tailwind.css', 'utf-8')).toMatchSnapshot(); - expect(tree.read('app/root.js', 'utf-8')).toMatchSnapshot(); - expect(tree.read('remix.config.js', 'utf-8')).toMatchSnapshot(); expect( readJson(tree, 'package.json').dependencies['tailwindcss'] ).toBeTruthy(); diff --git a/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.ts b/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.ts index 7cf86afb6e17f8..666e41127b0076 100644 --- a/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.ts +++ b/packages/remix/src/generators/setup-tailwind/setup-tailwind.impl.ts @@ -5,13 +5,15 @@ import { installPackagesTask, joinPathFragments, readProjectConfiguration, - toJS, type Tree, } from '@nx/devkit'; import { upsertLinksFunction } from '../../utils/upsert-links-function'; -import { tailwindVersion } from '../../utils/versions'; -import { updateRemixConfig } from './lib'; +import { + autoprefixerVersion, + postcssVersion, + tailwindVersion, +} from '../../utils/versions'; import type { SetupTailwindSchema } from './schema'; export default async function setupTailwind( @@ -25,18 +27,10 @@ export default async function setupTailwind( ); } - updateRemixConfig(tree, project.root); - generateFiles(tree, joinPathFragments(__dirname, 'files'), project.root, { tpl: '', }); - if (options.js) { - tree.rename( - joinPathFragments(project.root, 'app/root.js'), - joinPathFragments(project.root, 'app/root.tsx') - ); - } const pathToRoot = joinPathFragments(project.root, 'app/root.tsx'); upsertLinksFunction( tree, @@ -50,14 +44,12 @@ export default async function setupTailwind( tree, { tailwindcss: tailwindVersion, + postcss: postcssVersion, + autoprefixer: autoprefixerVersion, }, {} ); - if (options.js) { - toJS(tree); - } - if (!options.skipFormat) { await formatFiles(tree); } diff --git a/packages/remix/src/generators/style/style.impl.spec.ts b/packages/remix/src/generators/style/style.impl.spec.ts index f08e872a280581..3033d88a94436a 100644 --- a/packages/remix/src/generators/style/style.impl.spec.ts +++ b/packages/remix/src/generators/style/style.impl.spec.ts @@ -9,7 +9,7 @@ import presetGenerator from '../preset/preset.impl'; import routeGenerator from '../route/route.impl'; import styleGenerator from './style.impl'; -describe('route', () => { +describe('style', () => { let tree: Tree; beforeEach(() => { @@ -63,21 +63,10 @@ describe('route', () => { it('should place styles correctly when app dir is changed', async () => { await applicationGenerator(tree, { name: 'demo', directory: 'apps/demo' }); - tree.write( - 'apps/demo/remix.config.js', - ` - /** - * @type {import('@remix-run/dev').AppConfig} - */ - module.exports = { - ignoredRouteFiles: ["**/.*"], - appDirectory: "my-custom-dir", - };` - ); (remixConfigUtils.getRemixConfigValues as jest.Mock) = jest.fn(() => Promise.resolve({ ignoredRouteFiles: ['**/.*'], - appDirectory: 'my-custom-dir', + appDirectory: 'apps/demo/my-custom-dir', }) ); diff --git a/packages/remix/src/plugins/plugin.ts b/packages/remix/src/plugins/plugin.ts index b84e171e5dfdb8..1bff582ded6229 100644 --- a/packages/remix/src/plugins/plugin.ts +++ b/packages/remix/src/plugins/plugin.ts @@ -338,17 +338,22 @@ async function getBuildPaths( // do nothing } const { resolveConfig } = await loadViteDynamicImport(); - const viteBuildConfig = await resolveConfig( + const viteBuildConfig = (await resolveConfig( { configFile: configPath, mode: 'development', }, 'build' - ); + )) as any; return { buildDirectory: viteBuildConfig.build?.outDir ?? 'build', - serverBuildPath: viteBuildConfig.build?.outDir ?? 'build', + serverBuildPath: viteBuildConfig.build?.outDir + ? join( + dirname(viteBuildConfig.build?.outDir), + `server/${viteBuildConfig.__remixPluginContext?.remixConfig.serverBuildFile}` + ) + : 'build', assetsBuildDirectory: 'build/client', }; } diff --git a/packages/remix/src/utils/remix-config.ts b/packages/remix/src/utils/remix-config.ts index 2e97e6dc2da70a..a9916bb1fb5ed0 100644 --- a/packages/remix/src/utils/remix-config.ts +++ b/packages/remix/src/utils/remix-config.ts @@ -5,7 +5,26 @@ import { workspaceRoot, } from '@nx/devkit'; import type { AppConfig } from '@remix-run/dev'; -import { createContext, SourceTextModule } from 'vm'; +import { loadViteDynamicImport } from './executor-utils'; + +export function getRemixConfigPathDetails(tree: Tree, projectName: string) { + const project = readProjectConfiguration(tree, projectName); + if (!project) throw new Error(`Project does not exist: ${projectName}`); + + for (const ext of ['.mjs', '.cjs', '.js', '.mts', '.cts', '.ts']) { + const configPath = joinPathFragments(project.root, `vite.config${ext}`); + if (tree.exists(configPath)) { + return [configPath, 'vite']; + } + } + + for (const ext of ['.mjs', '.cjs', '.js']) { + const configPath = joinPathFragments(project.root, `remix.config${ext}`); + if (tree.exists(configPath)) { + return [configPath, 'classic']; + } + } +} export function getRemixConfigPath(tree: Tree, projectName: string) { const project = readProjectConfiguration(tree, projectName); @@ -39,21 +58,32 @@ export function getRemixConfigPathFromProjectRoot( const _remixConfigCache: Record = {}; export async function getRemixConfigValues(tree: Tree, projectName: string) { - const remixConfigPath = joinPathFragments( - workspaceRoot, - getRemixConfigPath(tree, projectName) - ); + const [configPath, configType] = getRemixConfigPathDetails(tree, projectName); + const remixConfigPath = joinPathFragments(workspaceRoot, configPath); const cacheKey = `${projectName}/${remixConfigPath}`; let appConfig = _remixConfigCache[cacheKey]; + let resolvedConfig: any; if (!appConfig) { - try { - const importedConfig = await Function( - `return import("${remixConfigPath}?t=${Date.now()}")` - )(); - appConfig = (importedConfig?.default || importedConfig) as AppConfig; - } catch { - appConfig = require(remixConfigPath); + if (configType === 'vite') { + const { resolveConfig } = await loadViteDynamicImport(); + const viteBuildConfig = (await resolveConfig( + { + configFile: configPath, + mode: 'development', + }, + 'build' + )) as any; + appConfig = viteBuildConfig.__remixPluginContext?.remixConfig; + } else { + try { + const importedConfig = await Function( + `return import("${remixConfigPath}?t=${Date.now()}")` + )(); + appConfig = (importedConfig?.default || importedConfig) as AppConfig; + } catch { + appConfig = require(remixConfigPath); + } } _remixConfigCache[cacheKey] = appConfig; } diff --git a/packages/remix/src/utils/remix-route-utils.ts b/packages/remix/src/utils/remix-route-utils.ts index 36da8f6c2d1ea6..ac4ba4c9c89e3e 100644 --- a/packages/remix/src/utils/remix-route-utils.ts +++ b/packages/remix/src/utils/remix-route-utils.ts @@ -5,6 +5,7 @@ import { Tree, } from '@nx/devkit'; import { getRemixConfigValues } from './remix-config'; +import { relative } from 'path'; /** * @@ -91,5 +92,10 @@ export async function resolveRemixAppDirectory( const project = readProjectConfiguration(tree, projectName); const remixConfig = await getRemixConfigValues(tree, projectName); - return joinPathFragments(project.root, remixConfig.appDirectory ?? 'app'); + return joinPathFragments( + project.root, + remixConfig.appDirectory + ? relative(project.root, remixConfig.appDirectory) + : 'app' + ); } diff --git a/packages/remix/src/utils/versions.ts b/packages/remix/src/utils/versions.ts index c2e2ae4901264f..b399a2828f0e66 100644 --- a/packages/remix/src/utils/versions.ts +++ b/packages/remix/src/utils/versions.ts @@ -2,7 +2,7 @@ import { readJson, Tree } from '@nx/devkit'; export const nxVersion = require('../../package.json').version; -export const remixVersion = '^2.8.1'; +export const remixVersion = '^2.13.1'; export const isbotVersion = '^4.4.0'; export const reactVersion = '^18.2.0'; export const reactDomVersion = '^18.2.0'; @@ -11,10 +11,13 @@ export const typesReactDomVersion = '^18.2.0'; export const eslintVersion = '^8.56.0'; export const typescriptVersion = '~5.5.2'; export const tailwindVersion = '^3.3.0'; +export const postcssVersion = '^8.4.38'; +export const autoprefixerVersion = '^10.4.19'; export const testingLibraryReactVersion = '^14.1.2'; // TODO(colum): Unpin this when @testing-library/jest-dom pushes a fix export const testingLibraryJestDomVersion = '6.4.2'; export const testingLibraryUserEventsVersion = '^14.5.2'; +export const viteVersion = '^5.0.0'; export function getRemixVersion(tree: Tree): string { return getPackageVersion(tree, '@remix-run/dev') ?? remixVersion; diff --git a/packages/vite/src/utils/versions.ts b/packages/vite/src/utils/versions.ts index f121493edb7b8b..c107ddc895ce33 100644 --- a/packages/vite/src/utils/versions.ts +++ b/packages/vite/src/utils/versions.ts @@ -1,4 +1,5 @@ export const nxVersion = require('../../package.json').version; +// Also update @nx/remix/utils/versions when changing vite version export const viteVersion = '^5.0.0'; export const vitestVersion = '^1.3.1'; export const vitePluginReactVersion = '^4.2.0'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3faff579f52b9b..c97c106b30f90c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -365,11 +365,11 @@ importers: specifier: 1.9.0 version: 1.9.0(react-redux@8.0.5(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1))(react@18.3.1) '@remix-run/dev': - specifier: ^2.8.1 - version: 2.12.0(@remix-run/react@2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)(ts-node@10.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@20.16.10)(typescript@5.5.4))(typescript@5.5.4)(vite@5.0.8(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)) + specifier: ^2.13.1 + version: 2.13.1(@remix-run/react@2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)(ts-node@10.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@20.16.10)(typescript@5.5.4))(typescript@5.5.4)(vite@5.0.8(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)) '@remix-run/node': - specifier: ^2.8.1 - version: 2.12.0(typescript@5.5.4) + specifier: ^2.13.1 + version: 2.13.1(typescript@5.5.4) '@rollup/plugin-babel': specifier: ^6.0.4 version: 6.0.4(@babel/core@7.25.2)(@types/babel__core@7.20.5)(rollup@4.22.0) @@ -5396,13 +5396,13 @@ packages: react-redux: optional: true - '@remix-run/dev@2.12.0': - resolution: {integrity: sha512-/87YQORdlJg5YChd7nVBM/hRXHZA4GfUjhKbZyNrh03bazCQBF+6EsXbzpJ6cCFOpZgecsN0Xv648Qw0VuJjwg==} + '@remix-run/dev@2.13.1': + resolution: {integrity: sha512-7+06Dail6zMyRlRvgrZ4cmQjs2gUb+M24iP4jbmql+0B7VAAPwzCRU0x+BF5z8GSef13kDrH3iXv/BQ2O2yOgw==} engines: {node: '>=18.0.0'} hasBin: true peerDependencies: - '@remix-run/react': ^2.12.0 - '@remix-run/serve': ^2.12.0 + '@remix-run/react': ^2.13.1 + '@remix-run/serve': ^2.13.1 typescript: ^5.1.0 vite: ^5.1.0 wrangler: ^3.28.2 @@ -5416,8 +5416,8 @@ packages: wrangler: optional: true - '@remix-run/node@2.12.0': - resolution: {integrity: sha512-83Jaoc6gpSuD4e6rCk7N5ZHAXNmDw4fJC+kPeDCsd6+wLtTLSi7u9Zo9/Q7moLZ3oyH+aR+LGdkxLULYv+Q6Og==} + '@remix-run/node@2.13.1': + resolution: {integrity: sha512-2ly7bENj2n2FNBdEN60ZEbNCs5dAOex/QJoo6EZ8RNFfUQxVKAZkMwfQ4ETV2SLWDgkRLj3Jo5n/dx7O2ZGhGw==} engines: {node: '>=18.0.0'} peerDependencies: typescript: ^5.1.0 @@ -5440,6 +5440,10 @@ packages: resolution: {integrity: sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==} engines: {node: '>=14.0.0'} + '@remix-run/router@1.20.0': + resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==} + engines: {node: '>=14.0.0'} + '@remix-run/server-runtime@2.12.0': resolution: {integrity: sha512-o9ukOr3XKmyY8UufTrDdkgD3fiy+z+f4qEzvCQnvC0+EasCyN9hb1Vbui6Koo/5HKvahC4Ga8RcWyvhykKrG3g==} engines: {node: '>=18.0.0'} @@ -5449,6 +5453,15 @@ packages: typescript: optional: true + '@remix-run/server-runtime@2.13.1': + resolution: {integrity: sha512-2DfBPRcHKVzE4bCNsNkKB50BhCCKF73x+jiS836OyxSIAL+x0tguV2AEjmGXefEXc5AGGzoxkus0AUUEYa29Vg==} + engines: {node: '>=18.0.0'} + peerDependencies: + typescript: ^5.1.0 + peerDependenciesMeta: + typescript: + optional: true + '@remix-run/web-blob@3.1.0': resolution: {integrity: sha512-owGzFLbqPH9PlKb8KvpNJ0NO74HWE2euAn61eEiyCXX/oteoVzTVSN8mpLgDjaxBf2btj5/nUllSUgpyd6IH6g==} @@ -22875,7 +22888,7 @@ snapshots: react: 18.3.1 react-redux: 8.0.5(@types/react-dom@18.3.0)(@types/react@18.3.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(redux@4.2.1) - '@remix-run/dev@2.12.0(@remix-run/react@2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)(ts-node@10.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@20.16.10)(typescript@5.5.4))(typescript@5.5.4)(vite@5.0.8(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6))': + '@remix-run/dev@2.13.1(@remix-run/react@2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4))(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6)(ts-node@10.9.1(@swc/core@1.5.7(@swc/helpers@0.5.11))(@types/node@20.16.10)(typescript@5.5.4))(typescript@5.5.4)(vite@5.0.8(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6))': dependencies: '@babel/core': 7.25.2 '@babel/generator': 7.25.6 @@ -22887,10 +22900,10 @@ snapshots: '@babel/types': 7.25.6 '@mdx-js/mdx': 2.3.0 '@npmcli/package-json': 4.0.1 - '@remix-run/node': 2.12.0(typescript@5.5.4) + '@remix-run/node': 2.13.1(typescript@5.5.4) '@remix-run/react': 2.12.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) - '@remix-run/router': 1.19.2 - '@remix-run/server-runtime': 2.12.0(typescript@5.5.4) + '@remix-run/router': 1.20.0 + '@remix-run/server-runtime': 2.13.1(typescript@5.5.4) '@types/mdx': 2.0.13 '@vanilla-extract/integration': 6.5.0(@types/node@20.16.10)(less@4.1.3)(sass@1.55.0)(stylus@0.59.0)(terser@5.31.6) arg: 5.0.2 @@ -22950,9 +22963,9 @@ snapshots: - ts-node - utf-8-validate - '@remix-run/node@2.12.0(typescript@5.5.4)': + '@remix-run/node@2.13.1(typescript@5.5.4)': dependencies: - '@remix-run/server-runtime': 2.12.0(typescript@5.5.4) + '@remix-run/server-runtime': 2.13.1(typescript@5.5.4) '@remix-run/web-fetch': 4.4.2 '@web3-storage/multipart-parser': 1.0.0 cookie-signature: 1.2.1 @@ -22976,6 +22989,8 @@ snapshots: '@remix-run/router@1.19.2': {} + '@remix-run/router@1.20.0': {} + '@remix-run/server-runtime@2.12.0(typescript@5.5.4)': dependencies: '@remix-run/router': 1.19.2 @@ -22988,6 +23003,18 @@ snapshots: optionalDependencies: typescript: 5.5.4 + '@remix-run/server-runtime@2.13.1(typescript@5.5.4)': + dependencies: + '@remix-run/router': 1.20.0 + '@types/cookie': 0.6.0 + '@web3-storage/multipart-parser': 1.0.0 + cookie: 0.6.0 + set-cookie-parser: 2.7.0 + source-map: 0.7.3 + turbo-stream: 2.4.0 + optionalDependencies: + typescript: 5.5.4 + '@remix-run/web-blob@3.1.0': dependencies: '@remix-run/web-stream': 1.1.0