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/server/document.js

219 lines
6.2 KiB
JavaScript
Raw Normal View History

/* eslint-disable */
import React, { Component } from 'react'
import PropTypes from 'prop-types'
2016-12-16 18:42:40 +00:00
import htmlescape from 'htmlescape'
import flush from 'styled-jsx/server'
2016-12-16 18:42:40 +00:00
const Fragment = React.Fragment || function Fragment ({ children }) {
Universal Webpack (#3578) * Speed up next build * Document webpack config * Speed up next build * Remove comment * Add comment * Clean up rules * Add comments * Run in parallel * Push plugins seperately * Create a new chunk for react * Don’t uglify react since it’s already uglified. Move react to commons in development * Use the minified version directly * Re-add globpattern * Move loaders into a separate variable * Add comment linking to Dan’s explanation * Remove dot * Add universal webpack * Initial dev support * Fix linting * Add changes from Arunoda's work * Made next dev works. But super slow and no HMR support. * Fix client side hot reload * Server side hmr * Only in dev * Add on-demand-entries client + hot-middleware * Add .babelrc support * Speed up on demand entries by running in parallel * Serve static generated files * Add missing config in dev * Add sass support * Add support for .map * Add cssloader config and fix .jsx support * Rename * use same defaults as css-loader. Fix linting * Add NoEmitErrorsPlugin * Add clientBootstrap * Use webpackhotmiddleware on the multi compiler * alpha.3 * Use babel 16.2.x * Fix reloading after error * Remove comment * Release 5.0.0-univeral-alpha.1 * Remove check for React 16 * Release 5.0.0-universal-alpha.2 * React hot loader v4 * Use our static file rendering machanism to serve pages. This should work well since the file path for a page is predictable. * Release 5.0.0-universal-alpha.3 * Remove optional loaders * Release 5.0.0-universal-alpha.4 * Remove clientBootstrap * Remove renderScript * Make sure pages bundles are served correctly * Remove unused import * Revert to using the same code as canary * Fix hot loader * Release 5.0.0-universal-alpha.5 * Check if externals dir exist before applying config * Add typescript support * Add support for transpiling certain packages in node_modules Thanks to @giuseppeg’s work in https://github.com/zeit/next.js/pull/3319 * Add BABEL_DISABLE_CACHE support * Make sourcemaps in production opt-in * Revert "Add support for transpiling certain packages in node_modules" This reverts commit d4b1d9babfb4b9ed4f4b12d56d52dee233e862da. In favor of a better api around this. * Support typescript through next.config.js * Remove comments * Bring back commons.js calculation * Remove unused dependencies * Move base.config.js to webpack.js * Make sure to only invalidate webpackDevMiddleware one after other. * Allow babel-loder caching by default. * Add comment about preact support * Bring back buildir replace * Remove obsolete plugin * Remove build replace, speed up build * Resolve page entries like pages/day/index.js to pages/day.js * Add componentDidCatch back * Compile to bundles * Use config.distDir everywhere * Make sure the file is an array * Remove console.log * Apply optimization to uglifyjs * Add comment pointing to source * Create entries the same way in dev and production * Remove unused and broken pagesGlobPattern * day/index.js is automatically turned into day.js at build time * Remove poweredByHeader option * Load pages with the correct path. * Release 5.0.0-universal-alpha.6 * Make sure react-dom/server can be overwritten by module-alias * Only add react-hot-loader babel plugin in dev * Release 5.0.0-universal-alpha.7 * Revert tests * Release 5.0.0-universal-alpha.10 * Make sure next/head is working properly. * Add wepack alias for 'next' back. * Make sure overriding className in next/head works * Alias react too * Add missing r * Fragment fallback has to wrap the children * Use min.js * Remove css.js * Remove wallaby.js * Release 5.0.0-universal-alpha.11 * Resolve relative to workdir instead of next * Make sure we touch the right file * Resolve next modules * Remove dotjsx removal plugins since we use webpack on the server * Revert "Resolve relative to workdir instead of next" This reverts commit a13f3e4ab565df9e2c9a3dfc8eb4009c0c2e02ed. * Externalize any locally loaded module lives outside of app dir. * Remove server aliases * Check node_modules reliably * Add symlink to next for tests * Make sure dynamic imports work locally. This is why we need it: https://github.com/webpack/webpack/blob/b545b519b2024e3f8be3041385bd326bf5d24449/lib/MainTemplate.js#L68 We need to have the finally clause in the above in __webpack_require__. webpack output option strictModuleExceptionHandling does that. * dynmaic -> dynamic * Remove webpack-node-externals * Make sure dynamic imports support SSR. * Remove css support in favor of next-css * Make sure we load path from `/` since it’s included in the path matching * Catch when ensurepage couldn’t be fulfilled for `.js.map` * Register require cache flusher for both client and server * Add comment explaining this is to facilitate hot reloading * Only load module when needed * Remove unused modules * Release 5.0.0-universal-alpha.12 * Only log the `found babel` message once * Make sure ondemand entries working correctly. Now we are just using a single instance of OnDemandEntryHandler. * Better sourcemaps * Release 5.0.0-universal-alpha.13 * Lock uglify version to 1.1.6 * Release 5.0.0-universal-alpha.14 * Fix a typo. * Introduce multi-zones support for mircofrontends * Add section on css
2018-01-30 15:40:52 +00:00
return <div>{children}</div>
}
2016-12-16 18:42:40 +00:00
export default class Document extends Component {
static childContextTypes = {
_documentProps: PropTypes.any
}
2016-12-16 18:42:40 +00:00
static getInitialProps ({ renderPage }) {
const { html, head, buildManifest } = renderPage()
const styles = flush()
return { html, head, styles, buildManifest }
2016-12-16 18:42:40 +00:00
}
getChildContext () {
return { _documentProps: this.props }
}
render () {
return <html>
<Head />
<body>
<Main />
<NextScript />
</body>
</html>
}
}
export class Head extends Component {
static contextTypes = {
_documentProps: PropTypes.any
}
static propTypes = {
nonce: PropTypes.string
}
getCssLinks () {
const { assetPrefix, files } = this.context._documentProps
if(!files || files.length === 0) {
return null
}
return files.map((file) => {
// Only render .css files here
if(!/\.css$/.exec(file)) {
return null
}
return <link
key={file}
nonce={this.props.nonce}
rel='stylesheet'
href={`${assetPrefix}/_next/${file}`}
/>
})
}
getPreloadDynamicChunks () {
const { dynamicImports, assetPrefix } = this.context._documentProps
return dynamicImports.map((bundle) => {
return <link
rel='preload'
key={bundle.file}
href={`${assetPrefix}/_next/${bundle.file}`}
2017-04-12 10:41:54 +00:00
as='script'
nonce={this.props.nonce}
2017-04-12 10:41:54 +00:00
/>
})
}
getPreloadMainLinks () {
const { assetPrefix, files } = this.context._documentProps
if(!files || files.length === 0) {
return null
}
return files.map((file) => {
// Only render .js files here
if(!/\.js$/.exec(file)) {
return null
}
return <link
key={file}
nonce={this.props.nonce}
rel='preload'
href={`${assetPrefix}/_next/${file}`}
as='script'
/>
})
}
2016-12-16 18:42:40 +00:00
render () {
const { head, styles, assetPrefix, __NEXT_DATA__ } = this.context._documentProps
const { page, pathname, buildId } = __NEXT_DATA__
const pagePathname = getPagePathname(pathname)
2017-04-12 10:41:54 +00:00
let children = this.props.children
// show a warning if Head contains <title> (only in development)
if (process.env.NODE_ENV !== 'production') {
children = React.Children.map(children, (child) => {
if (child && child.type === 'title') {
console.warn("Warning: <title> should not be used in _document.js's <Head>. https://err.sh/next.js/no-document-title")
}
return child
})
}
return <head {...this.props}>
{head}
{page !== '/_error' && <link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} as='script' nonce={this.props.nonce} />}
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} as='script' nonce={this.props.nonce} />
<link rel='preload' href={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} as='script' nonce={this.props.nonce} />
{this.getPreloadDynamicChunks()}
2017-04-12 10:41:54 +00:00
{this.getPreloadMainLinks()}
{this.getCssLinks()}
{styles || null}
{children}
2016-12-16 18:42:40 +00:00
</head>
}
}
export class Main extends Component {
static contextTypes = {
_documentProps: PropTypes.any
}
render () {
const { html } = this.context._documentProps
return (
<div id='__next' dangerouslySetInnerHTML={{ __html: html }} />
)
2016-12-16 18:42:40 +00:00
}
}
export class NextScript extends Component {
static contextTypes = {
_documentProps: PropTypes.any
}
static propTypes = {
nonce: PropTypes.string
}
getDynamicChunks () {
const { dynamicImports, assetPrefix } = this.context._documentProps
return dynamicImports.map((bundle) => {
return <script
async
key={bundle.file}
src={`${assetPrefix}/_next/${bundle.file}`}
nonce={this.props.nonce}
/>
})
2016-12-16 18:42:40 +00:00
}
getScripts () {
const { assetPrefix, files } = this.context._documentProps
if(!files || files.length === 0) {
return null
}
return files.map((file) => {
// Only render .js files here
if(!/\.js$/.exec(file)) {
return null
}
return <script
key={file}
src={`${assetPrefix}/_next/${file}`}
nonce={this.props.nonce}
async
/>
})
}
static getInlineScriptSource (documentProps) {
const { __NEXT_DATA__ } = documentProps
const { page, pathname } = __NEXT_DATA__
2018-09-17 11:19:19 +00:00
return `__NEXT_DATA__ = ${htmlescape(__NEXT_DATA__)};__NEXT_LOADED_PAGES__=[];__NEXT_REGISTER_PAGE=function(r,f){__NEXT_LOADED_PAGES__.push([r, f])}${page === '/_error' ? `;__NEXT_REGISTER_PAGE(${htmlescape(pathname)},function(){var e = new Error('Page does not exist: ${htmlescape(pathname)}');e.statusCode=404;return {error:e}})`:''}`
}
2016-12-16 18:42:40 +00:00
render () {
const { staticMarkup, assetPrefix, devFiles, __NEXT_DATA__ } = this.context._documentProps
const { page, pathname, buildId } = __NEXT_DATA__
const pagePathname = getPagePathname(pathname)
return <Fragment>
{devFiles ? devFiles.map((file) => <script key={file} src={`${assetPrefix}/_next/${file}`} nonce={this.props.nonce} />) : null}
{staticMarkup ? null : <script nonce={this.props.nonce} dangerouslySetInnerHTML={{
__html: NextScript.getInlineScriptSource(this.context._documentProps)
}} />}
{page !== '/_error' && <script async id={`__NEXT_PAGE__${pathname}`} src={`${assetPrefix}/_next/static/${buildId}/pages${pagePathname}`} nonce={this.props.nonce} />}
<script async id={`__NEXT_PAGE__/_app`} src={`${assetPrefix}/_next/static/${buildId}/pages/_app.js`} nonce={this.props.nonce} />
<script async id={`__NEXT_PAGE__/_error`} src={`${assetPrefix}/_next/static/${buildId}/pages/_error.js`} nonce={this.props.nonce} />
{staticMarkup ? null : this.getDynamicChunks()}
{staticMarkup ? null : this.getScripts()}
</Fragment>
2016-12-16 18:42:40 +00:00
}
}
function getPagePathname (pathname) {
if (pathname === '/') {
return '/index.js'
}
return `${pathname}.js`
}