Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize Deno template #9932

Open
wants to merge 40 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
5ca3397
Modernize deno template
redabacha Sep 2, 2024
a908ba6
Merge branch 'dev' into modernize-deno-template
redabacha Sep 2, 2024
454a13c
Install Deno for unit tests
redabacha Sep 2, 2024
1e48a52
Update deno scripts in package.json
redabacha Sep 2, 2024
b94e223
Don't pass --node-modules-dir flag to deno install
redabacha Sep 2, 2024
1228943
Add vite deno integration test
redabacha Sep 2, 2024
3daf1b6
Make vite deno integration test work
redabacha Sep 2, 2024
1f222bc
Install deno for integration tests
redabacha Sep 2, 2024
d58caab
Wait on 127.0.0.1 for only deno
redabacha Sep 2, 2024
9576356
Allow scripts when installing deps with deno
redabacha Sep 2, 2024
ead6719
Use viteConfig.basic for vite deno integration test
redabacha Sep 2, 2024
0b86c3d
ugly attempt to get windows msedge test passing
redabacha Sep 2, 2024
196db71
Cleanup solution for windows msedge test a bit
redabacha Sep 3, 2024
00ab18e
Add typegen instructions in deno template README.md
redabacha Sep 4, 2024
07a9fe7
Remove extraneous console.log
redabacha Sep 4, 2024
3d86009
Add vite deno build integration test
redabacha Sep 5, 2024
197fc8c
Update viteDevCmd to use nodeSync instead of node
redabacha Sep 5, 2024
21704c4
Update deploy instructions in deno template README.md
redabacha Sep 5, 2024
c83c7e4
Add changesets
redabacha Sep 5, 2024
619f6e8
Merge branch 'dev' into modernize-deno-template
redabacha Sep 9, 2024
155c20d
Merge branch 'dev' into modernize-deno-template
redabacha Sep 16, 2024
1fa4672
Merge branch 'dev' into modernize-deno-template
redabacha Sep 18, 2024
c5bc59b
Merge branch 'dev' into modernize-deno-template
redabacha Sep 19, 2024
24e3ee5
Merge branch 'dev' of https://github.com/redabacha/remix into moderni…
redabacha Oct 9, 2024
a3c1bcc
feat: only support deno 2
redabacha Oct 9, 2024
1954f5b
Merge branch 'dev' into modernize-deno-template
redabacha Oct 9, 2024
d4004f3
feat: update workflow install deno action
redabacha Oct 9, 2024
0795f97
Use new nodeModulesDir option
redabacha Oct 9, 2024
4f728c9
Update ignore rules for deno
redabacha Oct 9, 2024
65afd86
Use pnpm workspace for vite-deno-template integration test
redabacha Oct 9, 2024
60f9808
Remove package.json from deno gitignore
redabacha Oct 10, 2024
2095f21
Remove remix version pinning in deno template
redabacha Oct 10, 2024
7513f3b
Add --frozen-lockfile to 2nd pnpm install
redabacha Oct 10, 2024
b185f29
Only assert for react devtools message on non-webkit browsers
redabacha Oct 10, 2024
72e2a9f
Merge branch 'dev' of https://github.com/redabacha/remix into moderni…
redabacha Oct 11, 2024
343f23e
Update pnpm lockfile
redabacha Oct 11, 2024
62fe2d1
Merge branch 'dev' into modernize-deno-template
redabacha Oct 11, 2024
f4a1e48
Merge branch 'dev' into modernize-deno-template
redabacha Oct 11, 2024
0b65afb
Update templates.md
redabacha Oct 12, 2024
3907b73
Merge branch 'dev' of https://github.com/redabacha/remix into moderni…
redabacha Oct 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ jobs:
node-version-file: ".nvmrc"
cache: "pnpm"

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: 📥 Install deps
run: pnpm install --frozen-lockfile

Expand All @@ -42,11 +47,6 @@ jobs:
- name: 👔 Format
run: pnpm format

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: 👔 Format Deno files
run: pnpm format:deno

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ jobs:
node-version-file: ".nvmrc"
cache: "pnpm"

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"
Expand All @@ -40,10 +45,5 @@ jobs:
- name: 🔬 Lint
run: pnpm lint

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: 🔬 Lint deno files
run: pnpm lint:deno
5 changes: 5 additions & 0 deletions .github/workflows/shared-test-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ jobs:
node-version: ${{ matrix.node }}
cache: "pnpm"

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/shared-test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ jobs:
node-version: ${{ matrix.node }}
cache: "pnpm"

- name: 🦕 Install Deno
uses: denoland/setup-deno@v1
with:
deno-version: vx.x.x

- name: Disable GitHub Actions Annotations
run: |
echo "::remove-matcher owner=tsc::"
Expand Down
6 changes: 0 additions & 6 deletions .vscode/deno_resolve_npm_imports.json

This file was deleted.

5 changes: 3 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"typescript.tsdk": "node_modules/typescript/lib",
"deno.enablePaths": ["./packages/remix-deno/"],
"deno.importMap": "./.vscode/deno_resolve_npm_imports.json"
"deno.config": "./templates/deno/deno.jsonc",
"deno.enablePaths": ["./packages/remix-deno/", "./templates/deno"],
"deno.disablePaths": ["./templates/deno/app"]
}
4 changes: 4 additions & 0 deletions integration/helpers/vite-deno-template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
/app/deno.d.ts
/build
/package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import { cssBundleHref } from "@remix-run/css-bundle";
import type { LinksFunction } from "@remix-run/deno";
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import * as React from "react";

export const links: LinksFunction = () => [
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
];

export default function App() {
return (
Expand All @@ -27,7 +19,6 @@ export default function App() {
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { MetaFunction } from "@remix-run/deno";
import * as React from "react";
import type { MetaFunction } from "@remix-run/react";

export const meta: MetaFunction = () => {
return [
Expand Down
25 changes: 25 additions & 0 deletions integration/helpers/vite-deno-template/deno.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"tasks": {
"build": "deno run -A 'npm:@remix-run/dev@*' vite:build",
"dev": "deno run -A 'npm:@remix-run/dev@*' vite:dev",
"typecheck": "deno check '**/*' && deno run -A npm:typescript@^5.5.4/tsc",
"typegen": "deno types > ./app/deno.d.ts"
},
"exclude": ["app/", "build/"],
"nodeModulesDir": true,
"unstable": ["kv"],
"imports": {
// These remix packages should be treated like workspace:* dependencies.
"@remix-run/dev": "npm:@remix-run/dev@*",
"@remix-run/react": "npm:@remix-run/react@*",
"@remix-run/server-runtime": "npm:@remix-run/server-runtime@*",
"@types/react": "npm:@types/react@^18.3.5",
"@types/react-dom": "npm:@types/react-dom@^18.3.0",
"isbot": "npm:isbot@^5.1.17",
"react": "npm:react@^18.3.1",
"react-dom": "npm:react-dom@^18.3.1",
"typescript": "npm:typescript@^5.5.4",
"vite": "npm:vite@^5.4.2",
"vite-tsconfig-paths": "npm:vite-tsconfig-paths@^5.0.1"
}
}
32 changes: 32 additions & 0 deletions integration/helpers/vite-deno-template/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"include": [
"app/**/*.ts",
"app/**/*.tsx",
"app/**/.server/**/*.ts",
"app/**/.server/**/*.tsx",
"app/**/.client/**/*.ts",
"app/**/.client/**/*.tsx"
],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["vite/client"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},

// Vite takes care of building everything, not tsc.
"noEmit": true
}
}
16 changes: 16 additions & 0 deletions integration/helpers/vite-deno-template/vite.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { vitePlugin as remix } from "@remix-run/dev";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";

export default defineConfig({
plugins: [
remix({
future: {
v3_fetcherPersist: true,
v3_relativeSplatPath: true,
v3_throwAbortReason: true,
},
}),
tsconfigPaths(),
],
});
119 changes: 103 additions & 16 deletions integration/helpers/vite.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import type { Page } from "@playwright/test";
import { test as base, expect } from "@playwright/test";
import dedent from "dedent";
import fse from "fs-extra";
import getPort from "get-port";
import glob from "glob";
import { spawn, spawnSync, type ChildProcess } from "node:child_process";
import path from "node:path";
import fs from "node:fs/promises";
import path from "node:path";
import type { Readable } from "node:stream";
import url from "node:url";
import fse from "fs-extra";
import shell from "shelljs";
import stripIndent from "strip-indent";
import waitOn from "wait-on";
import getPort from "get-port";
import shell from "shelljs";
import glob from "glob";
import dedent from "dedent";
import type { Page } from "@playwright/test";
import { test as base, expect } from "@playwright/test";

const denoBin = "deno"; // assume deno is globally installed
const remixBin = "node_modules/@remix-run/dev/dist/cli.js";
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
const root = path.resolve(__dirname, "../..");
Expand Down Expand Up @@ -90,7 +91,10 @@ export const EXPRESS_SERVER = (args: {
app.listen(port, () => console.log('http://localhost:' + port));
`;

type TemplateName = "vite-template" | "vite-cloudflare-template";
type TemplateName =
| "vite-template"
| "vite-cloudflare-template"
| "vite-deno-template";

export async function createProject(
files: Record<string, string> = {},
Expand Down Expand Up @@ -204,15 +208,25 @@ type ServerArgs = {
};

const createDev =
(nodeArgs: string[]) =>
(
runtime: typeof node | typeof deno,
args: string[],
waitOnAddress = "localhost"
) =>
async ({ cwd, port, env, basename }: ServerArgs): Promise<() => unknown> => {
let proc = node(nodeArgs, { cwd, env });
await waitForServer(proc, { port, basename });
let proc = runtime(args, { cwd, env });
await waitForServer(proc, { port, basename }, waitOnAddress);
return () => proc.kill();
};

export const viteDev = createDev([remixBin, "vite:dev"]);
export const customDev = createDev(["./server.mjs"]);
export const viteDev = createDev(node, [remixBin, "vite:dev"]);
export const viteDevDeno = createDev(
deno,
["run", "-A", remixBin, "vite:dev"],
"127.0.0.1" // https://github.com/jeffbski/wait-on/issues/109
);

export const customDev = createDev(node, ["./server.mjs"]);

// Used for testing errors thrown on build when we don't want to start and
// wait for the server
Expand Down Expand Up @@ -240,6 +254,13 @@ type Fixtures = {
port: number;
cwd: string;
}>;
viteDevDeno: (
files: Files,
templateName?: TemplateName
) => Promise<{
port: number;
cwd: string;
}>;
customDev: (files: Files) => Promise<{
port: number;
cwd: string;
Expand Down Expand Up @@ -272,6 +293,55 @@ export const test = base.extend<Fixtures>({
stop?.();
},
// eslint-disable-next-line no-empty-pattern
viteDevDeno: async ({}, use) => {
let stop: (() => unknown) | undefined;
await use(async (files, template) => {
let port = await getPort();
let cwd = await createProject(await files({ port }), template);

// Install dependencies as late as possible so Node won't accidentally import them and cause access denied errors in Deno on Windows
redabacha marked this conversation as resolved.
Show resolved Hide resolved
let installProc = spawnSync(denoBin, ["install", "--no-lock"], {
cwd,
env: { ...process.env, DENO_FUTURE: "1" },
stdio: "pipe",
});
if (installProc.status !== 0) {
throw new Error(
[
"Failed to install Deno dependencies",
"",
"exit code: " + installProc.status,
`stdout: \n${installProc.stdout.toString("utf8")}\n`,
`stderr: \n${installProc.stderr.toString("utf8")}\n`,
].join("\n")
);
}
let copyProc = spawnSync(
process.argv[0],
[
"./scripts/copy-build-to-dist.mjs",
`--deno-node-modules-paths=${cwd}/node_modules`,
],
{ stdio: "pipe" }
);
if (copyProc.status !== 0) {
throw new Error(
[
"Failed to copy build artifacts for Deno",
"",
"exit code: " + copyProc.status,
`stdout: \n${copyProc.stdout.toString("utf8")}\n`,
`stderr: \n${copyProc.stderr.toString("utf8")}\n`,
].join("\n")
);
}

stop = await viteDevDeno({ cwd, port });
return { port, cwd };
});
stop?.();
},
// eslint-disable-next-line no-empty-pattern
customDev: async ({}, use) => {
let stop: (() => unknown) | undefined;
await use(async (files) => {
Expand Down Expand Up @@ -331,15 +401,32 @@ function node(
return proc;
}

function deno(
args: string[],
options: { cwd: string; env?: Record<string, string> }
) {
let proc = spawn(denoBin, args, {
cwd: options.cwd,
env: {
...process.env,
...colorEnv,
...options.env,
},
stdio: "pipe",
});
return proc;
}

async function waitForServer(
proc: ChildProcess & { stdout: Readable; stderr: Readable },
args: { port: number; basename?: string }
args: { port: number; basename?: string },
waitOnAddress = "localhost"
) {
let devStdout = bufferize(proc.stdout);
let devStderr = bufferize(proc.stderr);

await waitOn({
resources: [`http://localhost:${args.port}${args.basename ?? "/"}`],
resources: [`http://${waitOnAddress}:${args.port}${args.basename ?? "/"}`],
timeout: 10000,
}).catch((err) => {
let stdout = devStdout();
Expand Down
Loading
Loading