mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Split out Loadable.Capture and make NoSSR smaller (#5060)
This commit is contained in:
parent
3ede818252
commit
ead5a8bc3c
|
@ -35,35 +35,21 @@ type LoadableOptions = {
|
|||
const isServerSide = typeof window === 'undefined'
|
||||
|
||||
export function noSSR (LoadableInitializer: (loadableOptions: LoadableOptions) => ElementType, loadableOptions: LoadableOptions) {
|
||||
let LoadableComponent
|
||||
|
||||
// Removing webpack and modules means react-loadable won't try preloading
|
||||
delete loadableOptions.webpack
|
||||
delete loadableOptions.modules
|
||||
|
||||
// This check is neccesary to prevent react-loadable from initializing on the server
|
||||
if (!isServerSide) {
|
||||
LoadableComponent = LoadableInitializer(loadableOptions)
|
||||
return LoadableInitializer(loadableOptions)
|
||||
}
|
||||
|
||||
return class NoSSR extends React.Component<any, {mounted: boolean}> {
|
||||
state = { mounted: false }
|
||||
// This will only be rendered on the server side
|
||||
return () => <loadableOptions.loading error={null} isLoading pastDelay={false} timedOut={false} />
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.setState({mounted: true})
|
||||
}
|
||||
|
||||
render () {
|
||||
const {mounted} = this.state
|
||||
|
||||
if (mounted && LoadableComponent) {
|
||||
return <LoadableComponent {...this.props} />
|
||||
}
|
||||
|
||||
// Run loading component on the server and when mounting, when mounted we load the LoadableComponent
|
||||
return <loadableOptions.loading error={null} isLoading pastDelay={false} timedOut={false} />
|
||||
}
|
||||
}
|
||||
function DefaultLoading () {
|
||||
return <p>loading...</p>
|
||||
}
|
||||
|
||||
export default function dynamic (dynamicOptions: any, options: NextDynamicOptions) {
|
||||
|
@ -73,14 +59,14 @@ export default function dynamic (dynamicOptions: any, options: NextDynamicOption
|
|||
loading: ({error, isLoading}) => {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
if (isLoading) {
|
||||
return <p>loading...</p>
|
||||
return <DefaultLoading />
|
||||
}
|
||||
if (error) {
|
||||
return <p>{error.message}<br />{error.stack}</p>
|
||||
}
|
||||
}
|
||||
|
||||
return <p>loading...</p>
|
||||
return <DefaultLoading />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
48
lib/loadable-capture.js
Normal file
48
lib/loadable-capture.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
@copyright (c) 2017-present James Kyle <me@thejameskyle.com>
|
||||
MIT License
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
|
||||
*/
|
||||
// https://github.com/jamiebuilds/react-loadable/blob/v5.5.0/src/index.js
|
||||
// Just the `Capture` class which is only used with SSR
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class Capture extends React.Component {
|
||||
static propTypes = {
|
||||
report: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
loadable: PropTypes.shape({
|
||||
report: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
};
|
||||
|
||||
getChildContext () {
|
||||
return {
|
||||
loadable: {
|
||||
report: this.props.report
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return React.Children.only(this.props.children)
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWAR
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
|
||||
*/
|
||||
// https://github.com/jamiebuilds/react-loadable/blob/v5.5.0/src/index.js
|
||||
// Modified to be compatible with webpack 4 / Next.js
|
||||
|
@ -27,14 +27,6 @@ import PropTypes from 'prop-types'
|
|||
const ALL_INITIALIZERS = []
|
||||
const READY_INITIALIZERS = []
|
||||
|
||||
function isWebpackReady (getModuleIds) {
|
||||
return getModuleIds().every(moduleId => {
|
||||
return (
|
||||
typeof moduleId !== 'undefined'
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function load (loader) {
|
||||
let promise = loader()
|
||||
|
||||
|
@ -115,10 +107,6 @@ function render (loaded, props) {
|
|||
}
|
||||
|
||||
function createLoadableComponent (loadFn, options) {
|
||||
if (!options.loading) {
|
||||
throw new Error('react-loadable requires a `loading` component')
|
||||
}
|
||||
|
||||
let opts = Object.assign(
|
||||
{
|
||||
loader: null,
|
||||
|
@ -145,9 +133,7 @@ function createLoadableComponent (loadFn, options) {
|
|||
|
||||
if (typeof opts.webpack === 'function') {
|
||||
READY_INITIALIZERS.push(() => {
|
||||
if (isWebpackReady(opts.webpack)) {
|
||||
return init()
|
||||
}
|
||||
return init()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -279,32 +265,6 @@ function LoadableMap (opts) {
|
|||
|
||||
Loadable.Map = LoadableMap
|
||||
|
||||
class Capture extends React.Component {
|
||||
static propTypes = {
|
||||
report: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
static childContextTypes = {
|
||||
loadable: PropTypes.shape({
|
||||
report: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
};
|
||||
|
||||
getChildContext () {
|
||||
return {
|
||||
loadable: {
|
||||
report: this.props.report
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return React.Children.only(this.props.children)
|
||||
}
|
||||
}
|
||||
|
||||
Loadable.Capture = Capture
|
||||
|
||||
function flushInitializers (initializers) {
|
||||
let promises = []
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import { loadGetInitialProps, isResSent } from '../lib/utils'
|
|||
import Head, { defaultHead } from '../lib/head'
|
||||
import ErrorDebug from '../lib/error-debug'
|
||||
import Loadable from '../lib/loadable'
|
||||
import LoadableCapture from '../lib/loadable-capture'
|
||||
import { BUILD_MANIFEST, REACT_LOADABLE_MANIFEST, SERVER_DIRECTORY, CLIENT_STATIC_FILES_PATH } from '../lib/constants'
|
||||
|
||||
// Based on https://github.com/jamiebuilds/react-loadable/pull/132
|
||||
|
@ -125,13 +126,13 @@ async function doRender (req, res, pathname, query, {
|
|||
}
|
||||
}
|
||||
|
||||
const app = <Loadable.Capture report={moduleName => reactLoadableModules.push(moduleName)}>
|
||||
const app = <LoadableCapture report={moduleName => reactLoadableModules.push(moduleName)}>
|
||||
<EnhancedApp {...{
|
||||
Component: EnhancedComponent,
|
||||
router,
|
||||
...props
|
||||
}} />
|
||||
</Loadable.Capture>
|
||||
</LoadableCapture>
|
||||
|
||||
const render = staticMarkup ? renderToStaticMarkup : renderToString
|
||||
|
||||
|
|
Loading…
Reference in a new issue