-
Notifications
You must be signed in to change notification settings - Fork 0
How It Works
Naofumi Kagami edited this page Sep 13, 2022
·
4 revisions
The Next.js server acts as a BFF (Backend For Frontend). The following describes what this means for each specific scenario.
Assumption
- The browser requests the page at
http://localhost:3000/categories
- In your Next.js project directory, you have a file
/pages/categories/index.js
to render this page.
In this case, the following will happen.
- The browser will send a
GET /categories
request to the Next.js server. - The Next.js server will be route the request to the file
/pages/categories/index.js
. - The
/pages/categories/index.js
file for SSR contains agetServerSideProps()
function. InsidegetServerSideProps()
, the Next.js server will send aGET http://web:3000/categories
request to the Rails API server to retrieve information about the categories. - The Rails API server will return a JSON response to the Next.js server.
- The Next.js server will generate server-side rendered HTML and send it to the browser.
Assumption
- The browser requests the page at
http://localhost:3000/categories
- In your Next.js project directory, you DO NOT have a file
/pages/categories/index.js
to render this page.
In this case, the following will happen.
- The browser will send a
GET /categories
request to the Next.js server. - Since the Next.js server does not have a file at
/pages/categories/index.js
, Next.js cannot process this request. - Due to the
rewrites()
statement innextjs/next.config.js
(see below), the Next.js server will delegate the request to the Rails server. - The Rails server can handle the
GET /categories
request. It will generate an HTML response and send this to the Next.js server. - The Next.js server will send the HTML response to the browser.
nextjs/next.config.js
// https://nextjs.org/docs/migrating/incremental-adoption#rewrites
async rewrites() {
return {
// After checking all Next.js pages (including dynamic routes)
// and static files we proxy any other requests
fallback: [
{
source: '/:path*',
destination: `http://web:3000/:path*`,
},
],
}
},
Assumption
- The browser is currently displaying
http://localhost/categories/1/edit
. This is a React page. - The user enters information into the form and presses the
submit
button.
In this case, the following will happen.
- The form on the current page has the following attributes:
<form action="/api/categories/1" method="PATCH" onSubmit={handleSubmit}>
- The
handleSubmit()
function should look like the code below. ThehandleSubmit()
function will hand over form processing to thesubmitForm()
function. - The
handleSubmit()
function will send a PATCH request with the form data tohttp://localhost:3000/categories/1
from the browser. - The Next.js server will receive the
PATCH /categories/1
request. Due tonextjs/middleware.js
(see below), it will send the request to the Rails server. - The Rails server will receive the
PATCH /api/categories/1
request. It will update the database, and then it will send back a JSON response to the Next.js server. - The Next.js server will send the response, as is, to the browser.
- The browser will receive the JSON response. If the response is successful, then the browser will run the
success
callback. If it is unsuccessful, it will run thefailure
callback.
nextjs/pages/categories/[cid]/edit.js
const handleSubmit = async (event) => {
event.preventDefault()
submitForm({
form: event.currentTarget,
success: (response, jsonResult) => {
router.push(`/categories/${jsonResult.id}`)
},
failure: (response, jsonResult) => {
setErrors(jsonResult)
}
})
}
nextjs/middleware.js
// middleware.js
import { NextResponse } from 'next/server'
// This function can be marked `async` if using `await` inside
export function middleware(request) {
// Page Requests to the Next.js router (except '/api/*') are sent to
// the matching file in '/pages/'. However, these files cannot handle
// non-GET requests.
//
// Therefore, we send them directly to the API server before the Next.js router
// handles them.
if ( requestIsGet(request) ) { return }
if ( requestPathStartsWithApi(request) ) { return }
return NextResponse.rewrite('http://web:3000' + request.nextUrl.pathname
+ request.nextUrl.search)
}
function requestIsGet(request) {
return (request.method.toUpperCase() == 'GET')
}
function requestPathStartsWithApi(request) {
return (request.nextUrl.pathname.indexOf('/api/') != -1)
}
// See "Matching Paths" below to learn more
export const config = {
matcher: '/:path*',
}
- The form action is sent to the Next.js server (on
http://localhost:3000
) and not to the Rails server (onhttp://web:3000
). The browser should never access the Rails server directly. The Rails server is only accessible during development, and should be inaccessible in production.
I described the actions for a React page above. An ERB page behaves very similarly. The only difference is that an ERB page does not need a handleSubmit() function.