rsnext/packages/next/build/webpack/loaders/next-serverless-loader.ts
Tim Neutkens 3e51ddb8af
Move syntax formatting to prettier (#7454)
* Run prettier over packages/**/*.js

* Run prettier over packages/**/*.ts

* Run prettier over examples

* Remove tslint

* Run prettier over examples

* Run prettier over all markdown files

* Run prettier over json files
2019-05-29 13:57:26 +02:00

120 lines
3.7 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
assetPrefix: string
ampBindInitData: boolean | string
generateEtags: string
dynamicBuildId?: string | boolean
canonicalBase: string
}
const nextServerlessLoader: loader.Loader = function() {
const {
distDir,
absolutePagePath,
page,
canonicalBase,
assetPrefix,
ampBindInitData,
absoluteAppPath,
absoluteDocumentPath,
absoluteErrorPath,
generateEtags,
dynamicBuildId,
}: 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';
${
page.includes('/$')
? `import {getRouteMatch} from 'next-server/dist/lib/router/utils';`
: ''
}
import buildManifest from '${buildManifest}';
import reactLoadableManifest from '${reactLoadableManifest}';
import Document from '${absoluteDocumentPath}';
import Error from '${absoluteErrorPath}';
import App from '${absoluteAppPath}';
import Component from '${absolutePagePath}';
export default Component
export const _app = App
export async function renderReqToHTML(req, res, fromExport) {
const options = {
App,
Document,
buildManifest,
reactLoadableManifest,
canonicalBase: "${canonicalBase}",
buildId: "__NEXT_REPLACE__BUILD_ID__",
dynamicBuildId: ${dynamicBuildId === true || dynamicBuildId === 'true'},
assetPrefix: "${assetPrefix}",
ampBindInitData: ${ampBindInitData === true ||
ampBindInitData === 'true'}
}
const parsedUrl = parse(req.url, true)
const renderOpts = Object.assign(
{
Component,
dataOnly: req.headers && (req.headers.accept || '').indexOf('application/amp.bind+json') !== -1,
},
options,
)
try {
${page === '/_error' ? `res.statusCode = 404` : ''}
${
page.includes('/$')
? `const params = getRouteMatch("${page}")(parsedUrl.pathname) || {};`
: `const params = {};`
}
const result = await renderToHTML(req, res, "${page}", Object.assign({}, parsedUrl.query, params), renderOpts)
if (fromExport) return { html: result, renderOpts }
return result
} catch (err) {
if (err.code === 'ENOENT') {
res.statusCode = 404
const result = await renderToHTML(req, res, "/_error", parsedUrl.query, Object.assign({}, options, {
Component: Error
}))
return result
} else {
console.error(err)
res.statusCode = 500
const result = await renderToHTML(req, res, "/_error", parsedUrl.query, Object.assign({}, 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