mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
improve render
This commit is contained in:
parent
a8dcb52ac5
commit
4f21383e0f
|
@ -37,10 +37,10 @@ export function Head (props, context) {
|
|||
Head.contextTypes = { _documentProps: PropTypes.any }
|
||||
|
||||
export function Main (props, context) {
|
||||
const { html, data } = context._documentProps;
|
||||
const { html, data, staticMarkup } = context._documentProps;
|
||||
return <div>
|
||||
<div id='__next' dangerouslySetInnerHTML={{ __html: html }} />
|
||||
<script dangerouslySetInnerHTML={{ __html: '__NEXT_DATA__ = ' + htmlescape(data) }} />
|
||||
{staticMarkup ? null : <script dangerouslySetInnerHTML={{ __html: '__NEXT_DATA__ = ' + htmlescape(data) }} />}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,8 @@ export function DevTools (props, context) {
|
|||
DevTools.contextTypes = { _documentProps: PropTypes.any }
|
||||
|
||||
export function NextScript (props, context) {
|
||||
const { dev } = context._documentProps;
|
||||
const { dev, staticMarkup } = context._documentProps;
|
||||
if (staticMarkup) return null
|
||||
const src = !dev ? '/_next/next.bundle.js' : '/_next/next-dev.bundle.js'
|
||||
return <script type='text/javascript' src={src}/>
|
||||
}
|
||||
|
|
|
@ -31,14 +31,12 @@ export default class Server {
|
|||
await this.serveStatic(req, res, p)
|
||||
})
|
||||
|
||||
this.router.get('/:path+.json', async (req, res, params) => {
|
||||
const path = (params.path || []).join('/')
|
||||
await this.renderJSON(path, req, res)
|
||||
this.router.get('/:path+.json', async (req, res) => {
|
||||
await this.renderJSON(req, res)
|
||||
})
|
||||
|
||||
this.router.get('/:path*', async (req, res, params) => {
|
||||
const path = (params.path || []).join('/')
|
||||
await this.render(path, req, res)
|
||||
this.router.get('/:path*', async (req, res) => {
|
||||
await this.render(req, res)
|
||||
})
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
|
@ -58,33 +56,11 @@ export default class Server {
|
|||
}
|
||||
}
|
||||
|
||||
async render (path, req, res) {
|
||||
async render (req, res) {
|
||||
const { dir, dev } = this
|
||||
let html
|
||||
try {
|
||||
html = await render(path, { req, res }, { dir, dev })
|
||||
} catch (err) {
|
||||
let statusCode
|
||||
if ('ENOENT' === err.code) {
|
||||
statusCode = 404
|
||||
} else {
|
||||
console.error(err)
|
||||
statusCode = 500
|
||||
}
|
||||
res.statusCode = err.statusCode = statusCode
|
||||
html = await render('_error', { req, res, err }, { dir, dev })
|
||||
}
|
||||
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
res.setHeader('Content-Length', Buffer.byteLength(html))
|
||||
res.end(html)
|
||||
}
|
||||
|
||||
async renderJSON (path, req, res) {
|
||||
const { dir } = this
|
||||
let json
|
||||
try {
|
||||
json = await renderJSON(path, { dir })
|
||||
html = await render(req.url, { req, res }, { dir, dev })
|
||||
} catch (err) {
|
||||
if ('ENOENT' === err.code) {
|
||||
res.statusCode = 404
|
||||
|
@ -92,7 +68,25 @@ export default class Server {
|
|||
console.error(err)
|
||||
res.statusCode = 500
|
||||
}
|
||||
json = await renderJSON('_error', { dir })
|
||||
html = await render('/_error', { req, res, err }, { dir, dev })
|
||||
}
|
||||
|
||||
sendHTML(res, html)
|
||||
}
|
||||
|
||||
async renderJSON (req, res) {
|
||||
const { dir } = this
|
||||
let json
|
||||
try {
|
||||
json = await renderJSON(req.url, { dir })
|
||||
} catch (err) {
|
||||
if ('ENOENT' === err.code) {
|
||||
res.statusCode = 404
|
||||
} else {
|
||||
console.error(err)
|
||||
res.statusCode = 500
|
||||
}
|
||||
json = await renderJSON('/_error.json', { dir })
|
||||
}
|
||||
|
||||
const data = JSON.stringify(json)
|
||||
|
@ -101,6 +95,14 @@ export default class Server {
|
|||
res.end(data)
|
||||
}
|
||||
|
||||
async render404 (req, res) {
|
||||
const { dir, dev } = this
|
||||
|
||||
res.statusCode = 404
|
||||
const html = await render('/_error', { req, res }, { dir, dev })
|
||||
sendHTML(res, html)
|
||||
}
|
||||
|
||||
serveStatic (req, res, path) {
|
||||
return new Promise((resolve, reject) => {
|
||||
send(req, path)
|
||||
|
@ -116,3 +118,9 @@ export default class Server {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
function sendHTML (res, html) {
|
||||
res.setHeader('Content-Type', 'text/html')
|
||||
res.setHeader('Content-Length', Buffer.byteLength(html))
|
||||
res.end(html)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { relative, resolve } from 'path'
|
||||
import { parse } from 'url'
|
||||
import { createElement } from 'react'
|
||||
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
|
||||
import fs from 'mz/fs'
|
||||
|
@ -10,7 +11,12 @@ import Head from '../lib/head'
|
|||
import App from '../lib/app'
|
||||
import { StyleSheetServer } from '../lib/css'
|
||||
|
||||
export async function render (path, ctx, { dir = process.cwd(), dev = false } = {}) {
|
||||
export async function render (url, ctx = {}, {
|
||||
dir = process.cwd(),
|
||||
dev = false,
|
||||
staticMarkup = false
|
||||
} = {}) {
|
||||
const path = getPath(url)
|
||||
const p = await requireResolve(resolve(dir, '.next', 'pages', path))
|
||||
const mod = require(p)
|
||||
const Component = mod.default || mod
|
||||
|
@ -22,10 +28,10 @@ export async function render (path, ctx, { dir = process.cwd(), dev = false } =
|
|||
const app = createElement(App, {
|
||||
Component,
|
||||
props,
|
||||
router: new Router(ctx.req.url)
|
||||
router: new Router(ctx.req ? ctx.req.url : url)
|
||||
})
|
||||
|
||||
return renderToString(app)
|
||||
return (staticMarkup ? renderToStaticMarkup : renderToString)(app)
|
||||
})
|
||||
|
||||
const head = Head.rewind() || []
|
||||
|
@ -40,13 +46,19 @@ export async function render (path, ctx, { dir = process.cwd(), dev = false } =
|
|||
classNames: css.renderedClassNames
|
||||
},
|
||||
hotReload: false,
|
||||
dev
|
||||
dev,
|
||||
staticMarkup
|
||||
})
|
||||
|
||||
return '<!DOCTYPE html>' + renderToStaticMarkup(doc)
|
||||
}
|
||||
|
||||
export async function renderJSON (path, { dir = process.cwd() }) {
|
||||
export async function renderJSON (url, { dir = process.cwd() } = {}) {
|
||||
const path = getPath(url)
|
||||
const component = await read(resolve(dir, '.next', '_bundles', 'pages', path))
|
||||
return { component }
|
||||
}
|
||||
|
||||
function getPath (url) {
|
||||
return parse(url || '/').pathname.slice(1).replace(/\.json$/, '')
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue