1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
next.js/packages/next/build/webpack/loaders/next-serverless-loader.ts
Tim Neutkens 07c6e2852f
Export render instead of default for serverless target (#5979)
Extends on #5927, instead of `.default` we'll expose `.render` which is semantically more correct / mirrors the naming of the custom server API.

I've updated the spec in #5927 to reflect this change.

(copied from #5927):

```js
const http = require('http')
const page = require('./.next/serverless/about.js')
const server = new http.Server((req, res) => page.render(req, res))
server.listen(3000, () => console.log('Listening on http://localhost:3000'))
```
2019-01-02 14:59:28 +01:00

93 lines
2.8 KiB
TypeScript

import {loader} from 'webpack'
import {join} from 'path'
import {parse} from 'querystring'
import { BUILD_MANIFEST, REACT_LOADABLE_MANIFEST } from 'next-server/constants'
export type ServerlessLoaderQuery = {
page: string,
distDir: string,
absolutePagePath: string,
absoluteAppPath: string,
absoluteDocumentPath: string,
absoluteErrorPath: string,
buildId: string,
assetPrefix: string,
generateEtags: string
}
const nextServerlessLoader: loader.Loader = function () {
const {
distDir,
absolutePagePath,
page,
buildId,
assetPrefix,
absoluteAppPath,
absoluteDocumentPath,
absoluteErrorPath,
generateEtags
}: ServerlessLoaderQuery = typeof this.query === 'string' ? parse(this.query.substr(1)) : this.query
const buildManifest = join(distDir, BUILD_MANIFEST).replace(/\\/g, '/')
const reactLoadableManifest = join(distDir, REACT_LOADABLE_MANIFEST).replace(/\\/g, '/')
return `
import {parse} from 'url'
import {renderToHTML} from 'next-server/dist/server/render';
import {sendHTML} from 'next-server/dist/server/send-html';
import buildManifest from '${buildManifest}';
import reactLoadableManifest from '${reactLoadableManifest}';
import Document from '${absoluteDocumentPath}';
import Error from '${absoluteErrorPath}';
import App from '${absoluteAppPath}';
import Component from '${absolutePagePath}';
async function renderReqToHTML(req, res) {
const options = {
App,
Document,
buildManifest,
reactLoadableManifest,
buildId: "${buildId}",
assetPrefix: "${assetPrefix}"
}
const parsedUrl = parse(req.url, true)
try {
${page === '/_error' ? `res.statusCode = 404` : ''}
const result = await renderToHTML(req, res, "${page}", parsedUrl.query, {
...options,
Component
})
return result
} catch (err) {
if (err.code === 'ENOENT') {
res.statusCode = 404
const result = await renderToHTML(req, res, "/_error", parsedUrl.query, {
...options,
Component: Error
})
return result
} else {
console.error(err)
res.statusCode = 500
const result = await renderToHTML(req, res, "/_error", parsedUrl.query, {
...options,
Component: Error,
err
})
return result
}
}
}
export async function render (req, res) {
try {
const html = await renderReqToHTML(req, res)
sendHTML(req, res, html, {generateEtags: ${generateEtags}})
} catch(err) {
console.error(err)
res.statusCode = 500
res.end('Internal Server Error')
}
}
`
}
export default nextServerlessLoader