Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/remix-run/remix into v2_esm
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-ebey committed Aug 8, 2023
2 parents e23a045 + b2d8691 commit 4f87808
Show file tree
Hide file tree
Showing 160 changed files with 1,212 additions and 2,788 deletions.
5 changes: 5 additions & 0 deletions .changeset/brown-seals-look.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": minor
---

Warn users about obsolete future flags in remix.config.js
9 changes: 9 additions & 0 deletions .changeset/curly-moons-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@remix-run/dev": minor
"@remix-run/server-runtime": minor
---

detect built mode via `build.mode`

Prevents mode mismatch between built Remix server entry and user-land server.
Additionally, all runtimes (including non-Node runtimes) can use `build.mode` to determine if HMR should be performed.
5 changes: 5 additions & 0 deletions .changeset/fix-stub-route-object-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/testing": patch
---

Fix types for `StubRouteObject` `children` property
44 changes: 44 additions & 0 deletions .github/workflows/deduplicate-yarn.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: ⚙️ Deduplicate yarn.lock

on:
push:
branches:
- dev
paths:
- ./yarn.lock

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
format:
if: github.repository == 'remix-run/remix'
runs-on: ubuntu-latest

steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3

- name: ⎔ Setup node
uses: actions/setup-node@v3
with:
node-version-file: ".nvmrc"
cache: "yarn"

- name: ️️⚙️ Dedupe yarn.lock
run: npx yarn-deduplicate && rm -rf ./node_modules && yarn

- name: 💪 Commit
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add .
if [ -z "$(git status --porcelain)" ]; then
echo "💿 no deduplication needed"
exit 0
fi
git commit -m "chore: deduplicate `yarn.lock`"
git push
echo "💿 https://github.com/$GITHUB_REPOSITORY/commit/$(git rev-parse HEAD)"
4 changes: 4 additions & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ You may need to make changes to a pre-release prior to publishing a final stable
- `git checkout dev; git merge --no-ff release-next`
- Convert the `remix@1.x.y` tag to a Release on Github with the name `v1.x.y` using he release notes prepared above

### Hotfix releases

Hotfix releases follow the same process as standard releases above, but the `release-*` branch should be branched off latest `main` instead of `dev`. Once the stable hotfix is published, the `release-*` branch should be merged back into both `main` and `dev` just like a normal release.

### Experimental releases

Experimental releases do not need to be branched off of `dev`. Experimental releases can be branched from anywhere as they are not intended for general use.
Expand Down
2 changes: 2 additions & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- alanhoskins
- Alarid
- alex-ketch
- alexmgrant
- alextes
- alexuxui
- alireza-bonab
Expand Down Expand Up @@ -449,6 +450,7 @@
- rossipedia
- RossJHagan
- RossMcMillan92
- roughee
- rowinbot
- rphlmr
- rtabulov
Expand Down
4 changes: 2 additions & 2 deletions docs/file-conventions/remix-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ relative to `remix.config.js`. Defaults to `".cache"`.
The delay, in milliseconds, before the dev server broadcasts a reload event.
There is no delay by default.

For `v2_dev`, the race conditions that necesitated this option have been eliminated.
For v2, the race conditions that necessitated this option have been eliminated.

## devServerPort (deprecated)

The port number to use for the dev websocket server. Defaults to 8002.

For `v2_dev`, use [`--port` / `v2_dev.port` option][port].
For v2, use [`--port` / `dev.port` option][port].

## ignoredRouteFiles

Expand Down
12 changes: 6 additions & 6 deletions docs/guides/data-writes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Data writes (some people call these mutations) in Remix are built on top of two
When the user submits a form, Remix will:

1. Call the action for the form
2. Reload all of the data for all of the routes on the page
2. Reload all the data for all the routes on the page

Many times people reach for global state management libraries in React like redux, data libs like apollo, and fetch wrappers like React Query in order to help manage getting server state into your components and keeping the UI in sync with it when the user changes it. Remix's HTML based API replaces the majority of use cases for these tools. Remix knows how to load the data as well as how to revalidate it after it changes when you use standard HTML APIs.

Expand Down Expand Up @@ -104,7 +104,7 @@ Let's consider a "new project" form.

When the user submits this form, the browser will serialize the fields into a request "body" (instead of URL search params) and "POST" it to the server. This is still a normal navigation as if the user clicked a link. The difference is two-fold: the user provided the data for the server and the browser sent the request as a "POST" instead of a "GET".

The data is made available to the server's request handler so you can create the record. After that, you return a response. In this case, you'd probably redirect to the newly-created project. A remix action would look something like this:
The data is made available to the server's request handler, so you can create the record. After that, you return a response. In this case, you'd probably redirect to the newly-created project. A remix action would look something like this:

```tsx filename=app/routes/projects.tsx
export async function action({ request }: ActionArgs) {
Expand Down Expand Up @@ -143,9 +143,9 @@ Whether you use `<form>` or `<Form>` though, you write the very same code. You c

Let's start with our project form from earlier but make it usable:

Let's say you've got the route `app/routes/projects.new.js` with this form in it:
Let's say you've got the route `app/routes/projects.new.tsx` with this form in it:

```tsx
```tsx filename=app/routes/projects.new.tsx
export default function NewProject() {
return (
<form method="post" action="/projects/new">
Expand Down Expand Up @@ -285,7 +285,7 @@ You can ship this code as-is. The browser will handle the pending UI and interru

### Graduate to `<Form>` and add pending UI

Let's use progressive enhancement to make this UX a bit more fancy. By changing it from `<form>` to `<Form>`, Remix will emulate the browser behavior with `fetch`. It will also give you access to the pending form data so you can build pending UI.
Let's use progressive enhancement to make this UX a bit more fancy. By changing it from `<form>` to `<Form>`, Remix will emulate the browser behavior with `fetch`. It will also give you access to the pending form data, so you can build pending UI.

```tsx lines=[2,11]
import { json, redirect } from "@remix-run/node"; // or cloudflare/deno
Expand Down Expand Up @@ -389,7 +389,7 @@ export default function NewProject() {

Pretty slick! Now when the user clicks "Create", the inputs go disabled, and the submit button's text changes. The whole operation should be faster now too since there's just one network request happening instead of a full page reload (which involves potentially more network requests, reading assets from the browser cache, parsing JavaScript, parsing CSS, etc.).

We didn't do much with `navigation` on this page, but it's got all the information about the submission (`navigation.formMethod`, `navigation.formAction`, `navigation.formEncType`), as well as all of the values being processed on the server on `navigation.formData`.
We didn't do much with `navigation` on this page, but it's got all the information about the submission (`navigation.formMethod`, `navigation.formAction`, `navigation.formEncType`), as well as all the values being processed on the server on `navigation.formData`.

### Animating in the Validation Errors

Expand Down
7 changes: 2 additions & 5 deletions docs/guides/envvars.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,8 @@ Then, you can pass those through via `getLoadContext` in your server file:
```ts
export const onRequest = createPagesFunctionHandler({
build,
getLoadContext(context) {
// Hand-off Cloudflare ENV vars to the Remix `context` object
return { env: context.env };
},
mode: process.env.NODE_ENV,
getLoadContext: (context) => ({ env: context.env }), // Hand-off Cloudflare ENV vars to the Remix `context` object
mode: build.mode,
});
```

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/manual-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ app.all(
? createDevRequestHandler(build)
: createRequestHandler({
build,
mode: process.env.NODE_ENV,
mode: build.mode,
})
);
```
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/mdx.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Remix has built-in support for using MDX at build-time in two ways:

## Routes

The simplest way to get started with MDX in Remix is to create a route module. Just like `.js` and `.ts` files in your `app/routes` directory, `.mdx` (and `.md`) files will participate in automatic file system based routing.
The simplest way to get started with MDX in Remix is to create a route module. Just like `.tsx`, `.js` and `.jsx` files in your `app/routes` directory, `.mdx` (and `.md`) files will participate in automatic file system based routing.

MDX routes allow you to define both meta and headers as if they were a code based route:

Expand Down Expand Up @@ -114,7 +114,7 @@ Besides just route level MDX, you can also import these files anywhere yourself

When you `import` a `.mdx` file, the exports of the module are:

- **default**: The react component for consumption
- **default**: The React component for consumption
- **attributes**: The frontmatter data as an object
- **filename**: The basename of the source file (e.g. "first-post.mdx")

Expand Down
4 changes: 2 additions & 2 deletions docs/guides/not-found.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ There are two primary cases where a Remix site should send a 404:
- The URL doesn't match any routes in the app
- Your loader didn't find any data

The first case is already handled by Remix, you don't have to throw a response yourself. It knows your routes so it knows if nothing matched (_consider using a [Splat Route][splat-route] to handle this case_). The second case is up to you, but it's really easy.
The first case is already handled by Remix, you don't have to throw a response yourself. It knows your routes, so it knows if nothing matched (_consider using a [Splat Route][splat-route] to handle this case_). The second case is up to you, but it's really easy.

## How to Send a 404

As soon as you know you don't have what the user is looking for you should _throw a response_.

```tsx filename=app/routes/page.$slug.js
```tsx filename=app/routes/page.$slug.tsx
export async function loader({ params }: LoaderArgs) {
const page = await db.page.findOne({
where: { slug: params.slug },
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/optimistic-ui.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default function ProjectRoute() {

One of the critical pieces here is that the project route renders a reusable component like `<ProjectView>`, because we'll be using it later for our optimistic version. Perhaps it looks like this:

```tsx filename=app/component/project.js
```tsx filename=app/component/project.tsx
export function ProjectView({ project }) {
return (
<div>
Expand Down Expand Up @@ -229,7 +229,7 @@ export default function NewProject() {
}
```

Now in the rare case of an error on the server, the UI reverts back to the form, all the state is still there and they have an error message. Nearly every other time, however, the UI responds instantly to the user, even though it's doing work in the background.
Now in the rare case of an error on the server, the UI reverts back to the form, all the state is still there, and they have an error message. Nearly every other time, however, the UI responds instantly to the user, even though it's doing work in the background.

## Client-side Validation

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/resource-routes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ If a route doesn't export a default component, it can be used as a Resource Rout

For example, consider a UI Route that renders a report, note the link:

```tsx filename=app/routes/reports.$id.js lines=[10-12]
```tsx filename=app/routes/reports.$id.tsx lines=[10-12]
export async function loader({ params }: LoaderArgs) {
return json(await getReport(params.id));
}
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/streaming.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ But it's still sub-optimal for two reasons:
Remix takes advantage of React 18's streaming and server-side support for `<Suspense />` boundaries using the [`defer` Response][defer] utility and [`<Await />`][await] component / [`useAsyncValue`][useasyncvalue] hook. By using these APIs, you can solve both of these problems:

1. Your data is no longer on a waterfall: document & data (in parallel) -> JavaScript
2. Your can easily switch between streaming and waiting for the data
2. You can easily switch between streaming and waiting for the data

![Graphs showing how document and slow data requests sent over the same response significantly speed up the largest contentful paint][graphs-showing-how-document-and-slow-data-requests-sent-over-the-same-response-significantly-speed-up-the-largest-contentful-paint]

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ export const links: LinksFunction = () => [

With this setup in place, you can also use [Tailwind's functions and directives][tailwind-functions-and-directives] anywhere in your CSS. Note that Tailwind will warn that no utility classes were detected in your source files if you never used it before.

If you're also using Remix's [built-in PostCSS support][built-in-post-css-support], the Tailwind PostCSS plugin will be automatically included if it's missing, but you can also choose to manually include the Tailwind plugin in your PostCSS config instead if you prefer.
Tailwind doesn't compile CSS for older browsers by default, so if you'd like to achieve this using a PostCSS-based tool like [Autoprefixer][autoprefixer], you'll need to leverage Remix's [built-in PostCSS support][built-in-post-css-support]. When using both PostCSS and Tailwind, the Tailwind plugin will be automatically included if it's missing, but you can also choose to manually include the Tailwind plugin in your PostCSS config instead if you prefer.

If you're using VS Code, it's recommended you install the [Tailwind IntelliSense extension][tailwind-intelli-sense-extension] for the best developer experience.

Expand Down
Loading

0 comments on commit 4f87808

Please sign in to comment.