Skip to content

Commit

Permalink
Merge pull request #128 from netlify/v2
Browse files Browse the repository at this point in the history
feat!: update to Remix 2
  • Loading branch information
ascorbic committed Nov 2, 2023
2 parents 64a3f24 + 2e4e990 commit 8b381c3
Show file tree
Hide file tree
Showing 18 changed files with 130 additions and 168 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
export default {
extends: ["@remix-run/eslint-config", "@remix-run/eslint-config/node"],
};
26 changes: 8 additions & 18 deletions app/entry.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,11 @@ import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";

function hydrate() {
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
}

if (window.requestIdleCallback) {
window.requestIdleCallback(hydrate);
} else {
// Safari doesn't support requestIdleCallback
// https://caniuse.com/requestidlecallback
window.setTimeout(hydrate, 1);
}
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
22 changes: 1 addition & 21 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1 @@
import type { EntryContext } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
import { renderToString } from "react-dom/server";

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
const markup = renderToString(
<RemixServer context={remixContext} url={request.url} />
);

responseHeaders.set("Content-Type", "text/html");

return new Response("<!DOCTYPE html>" + markup, {
headers: responseHeaders,
status: responseStatusCode,
});
}
export { handleRequest as default } from "@netlify/remix-adapter";
10 changes: 4 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
{
"private": true,
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix build",
"predev": "rimraf ./public/_redirects",
"dev": "remix dev",
"start": "netlify serve",
"typecheck": "tsc -b"
},
"dependencies": {
"@netlify/functions": "^1.3.0",
"@remix-run/node": "*",
"@remix-run/react": "*",
"cross-env": "^7.0.3",
Expand All @@ -20,11 +19,10 @@
"@remix-run/dev": "*",
"@remix-run/eslint-config": "*",
"@remix-run/serve": "*",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.8",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"eslint": "^8.27.0",
"rimraf": "^4.1.4",
"typescript": "^5.1.0"
"typescript": "^5.2.2"
},
"engines": {
"node": ">=18"
Expand Down
22 changes: 5 additions & 17 deletions remix.config.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,10 @@
const baseConfig =
process.env.NODE_ENV === "production"
? // when running the Netify CLI or building on Netlify, we want to use
{
server: "./server.js",
serverBuildPath: ".netlify/functions-internal/server.js",
}
: // otherwise support running remix dev, i.e. no custom server
undefined;
import { config } from "@netlify/remix-adapter";

/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
...baseConfig,
ignoredRouteFiles: ["**/.*"],
// See https://remix.run/docs/en/main/file-conventions/route-files-v2
future: {
v2_routeConvention: true,
}
export default {
...(process.env.NODE_ENV === "production" ? config : undefined),
// This works out of the box with the Netlify adapter, but you can
// add your own custom config here if you want to.
//
// See https://remix.run/docs/en/v1/file-conventions/remix-config
// See https://remix.run/file-conventions/remix-config
};
13 changes: 7 additions & 6 deletions remix.init/README-edge.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,26 @@ npm install
Run

```sh
netlify dev
npm run dev
```

Open up [http://localhost:8888](http://localhost:8888), and you're ready to go!

### Serve your site locally

Run
To serve your site locally in a production-like environment, run

```sh
npm netlify serve
npm run start
```

to serve your site locally at [http://localhost:8888](http://localhost:8888).
Your site will be available at [http://localhost:8888](http://localhost:8888). Note that it will not auto-reload when you make changes.

## Excluding routes

You can exclude routes for non-Remix code such as custom Netlify Functions or Edge Functions. To do this, add an additional entry in the array like in the example below:

````diff
```diff
export const config = {
cache: "manual",
path: "/*",
Expand All @@ -70,6 +70,7 @@ export const config = {
- excluded_patterns: ["/_assets/*"],
+ excluded_patterns: ["/_assets/*", "/api/*"],
};
```

## Deployment

Expand All @@ -81,4 +82,4 @@ netlify deploy --build

# production deployment
netlify deploy --build --prod
````
```
8 changes: 4 additions & 4 deletions remix.init/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,21 @@ Run
netlify dev
```

Open up [http://localhost:8888](http://localhost:8888), and you're ready to go!
Open up [http://localhost:3000](http://localhost:3000), and you're ready to go!

### Adding Redirects and Rewrites

To add redirects and rewrites, add them to the `netlify.toml` file or to the [\_app_redirects](_app_redirects) file. For more information about redirects and rewrites, see the [Netlify docs](https://docs.netlify.com/routing/redirects/).
To add redirects and rewrites, add them to the `netlify.toml` file. For more information about redirects and rewrites, see the [Netlify docs](https://docs.netlify.com/routing/redirects/).

### Serve your site locally

Run
To serve your site locally in a production-like environment, run

```sh
npm run start
```

to serve your site locally at [http://localhost:8888](http://localhost:8888).
Your site will be available at [http://localhost:8888](http://localhost:8888). Note that it will not auto-reload when you make changes.

## Deployment

Expand Down
7 changes: 0 additions & 7 deletions remix.init/_app_redirects

This file was deleted.

23 changes: 1 addition & 22 deletions remix.init/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1 @@
import type { EntryContext } from "@remix-run/node";
import { RemixServer } from "@remix-run/react";
// Looking to use renderReadableStream? See https://github.com/netlify/remix-template/discussions/100
import { renderToString } from "react-dom/server";

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
) {
const markup = renderToString(
<RemixServer context={remixContext} url={request.url} />
);

responseHeaders.set("Content-Type", "text/html");

return new Response("<!DOCTYPE html>" + markup, {
headers: responseHeaders,
status: responseStatusCode,
});
}
export { handleRequest as default } from "@netlify/remix-edge-adapter";
81 changes: 50 additions & 31 deletions remix.init/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ const fs = require("fs/promises");
const { join } = require("path");
const PackageJson = require("@npmcli/package-json");
const execa = require("execa");
const { Command } = require('commander');
const { Command } = require("commander");

const foldersToExclude = [".github", ".git"];
const foldersToExclude = [".github"];

// Netlify Edge Functions template file changes
const edgeFilesToCopy = [
["README-edge.md", "README.md"],
["netlify-edge-toml", "netlify.toml"],
["server.js"],
["server.ts"],
["remix.config.js"],
["entry.server.tsx", "app/entry.server.tsx"],
["root.tsx", "app/root.tsx"],
Expand All @@ -22,10 +22,9 @@ const edgeFilesToCopy = [
const filesToCopy = [
["README.md"],
["netlify-toml", "netlify.toml"],
["_app_redirects"],
["redirects", ".redirects"],
];


async function copyTemplateFiles({ files, rootDirectory }) {
for (const [file, target] of files) {
let sourceFile = file;
Expand All @@ -41,10 +40,7 @@ async function copyTemplateFiles({ files, rootDirectory }) {
async function updatePackageJsonForEdge(directory) {
const packageJson = await PackageJson.load(directory);
const {
dependencies: {
"@remix-run/node": _node,
...dependencies
},
dependencies: { "@remix-run/node": _node, ...dependencies },
scripts,
...restOfPackageJson
} = packageJson.content;
Expand All @@ -53,13 +49,14 @@ async function updatePackageJsonForEdge(directory) {
// dev script is the same as the start script for Netlify Edge, "cross-env NODE_ENV=production netlify dev"
scripts: {
...scripts,
predev: "rimraf ./.netlify/edge-functions/",
dev: 'remix dev --manual -c "ntl dev --framework=#static"',
},
...restOfPackageJson,
dependencies: {
...dependencies,
"@netlify/edge-functions": "^2.0.0",
"@netlify/remix-edge-adapter": "1.2.0",
"@netlify/remix-edge-adapter": "^3.0.0",
"@netlify/remix-runtime": "^2.0.0",
},
});

Expand All @@ -69,19 +66,25 @@ async function updatePackageJsonForEdge(directory) {
async function updatePackageJsonForFunctions(directory) {
const packageJson = await PackageJson.load(directory);
const {
dependencies: {
"@remix-run/node": _node,
...dependencies
},
dependencies: { "@remix-run/node": _node, ...dependencies },
scripts,
...restOfPackageJson
} = packageJson.content;

packageJson.update({
...restOfPackageJson,
scripts: {
...scripts,
build: "npm run redirects:enable && remix build",
dev: "npm run redirects:disable && remix dev",
"redirects:enable": "shx cp .redirects public/_redirects",
"redirects:disable": "shx rm -f public/_redirects",
},
dependencies: {
...dependencies,
"@netlify/remix-adapter": "^1.0.0",
"@netlify/functions": "^2.0.0",
"@netlify/remix-adapter": "^2.0.0",
shx: "^0.3.4",
},
});

Expand All @@ -104,7 +107,24 @@ async function removeNonTemplateFiles({ rootDirectory, folders }) {
}
}

async function main({ rootDirectory }) {
async function installAdditionalDependencies({
rootDirectory,
packageManager,
}) {
try {
console.log(`Installing additional dependencies with ${packageManager}.`);
const npmInstall = await execa(packageManager, ["install"], {
cwd: rootDirectory,
stdio: "inherit",
});
} catch (e) {
console.log(
`Unable to install additional packages. Run ${packageManager} install in the root of the new project, "${rootDirectory}".`
);
}
}

async function main({ rootDirectory, packageManager }) {
await removeNonTemplateFiles({
rootDirectory,
folders: foldersToExclude,
Expand All @@ -116,6 +136,7 @@ async function main({ rootDirectory }) {
rootDirectory,
});
await updatePackageJsonForFunctions(rootDirectory);
await installAdditionalDependencies({ rootDirectory, packageManager });
return;
}

Expand All @@ -126,30 +147,28 @@ async function main({ rootDirectory }) {

await updatePackageJsonForEdge(rootDirectory);

// The Netlify Edge Functions template has different and additional dependencies to install.
try {
console.log("installing additional npm packages...");
const npmInstall = await execa("npm", ["install"], { cwd: rootDirectory });
console.log(npmInstall.stdout);
} catch (e) {
console.log(
`Unable to install additional packages. Run npm install in the root of the new project, "${rootDirectory}".`
);
}
await installAdditionalDependencies({ rootDirectory, packageManager });
}

async function shouldUseEdge() {

// parse the top level command args to see if edge was passed in
const program = new Command();
program
.option('--netlify-edge', 'explicitly use Netlify Edge Functions to serve this Remix site.', undefined)
.option('--no-netlify-edge', 'explicitly do NOT use Netlify Edge Functions to serve this Remix site - use Serverless Functions instead.', undefined)
.option(
"--netlify-edge",
"explicitly use Netlify Edge Functions to serve this Remix site.",
undefined
)
.option(
"--no-netlify-edge",
"explicitly do NOT use Netlify Edge Functions to serve this Remix site - use Serverless Functions instead.",
undefined
);
program.allowUnknownOption().parse();

const passedEdgeOption = program.opts().netlifyEdge;

if(passedEdgeOption !== true && passedEdgeOption !== false){
if (passedEdgeOption !== true && passedEdgeOption !== false) {
const { edge } = await inquirer.prompt([
{
name: "edge",
Expand Down

0 comments on commit 8b381c3

Please sign in to comment.