mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Always load pages with ".js" extension (#3393)
* Always fetch pages with '.js' extention from client side. * Load error page always from _error.js rather _error/index.js * Load pages from page.js instead of page/index.js from the client for static exports. * Update index.js * Simplify the path re-write logic in the webpack pages-plugin.
This commit is contained in:
parent
a8c344fa19
commit
820e3ff716
|
@ -5,15 +5,15 @@ import Clock from './Clock'
|
|||
|
||||
@inject('store') @observer
|
||||
class Page extends React.Component {
|
||||
componentDidMount() {
|
||||
componentDidMount () {
|
||||
this.props.store.start()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
componentWillUnmount () {
|
||||
this.props.store.stop()
|
||||
}
|
||||
|
||||
render() {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<h1>{this.props.title}</h1>
|
||||
|
|
|
@ -5,18 +5,18 @@ import { initStore } from '../store'
|
|||
import Page from '../components/Page'
|
||||
|
||||
export default class Counter extends React.Component {
|
||||
static getInitialProps({ req }) {
|
||||
static getInitialProps ({ req }) {
|
||||
const isServer = !!req
|
||||
const store = initStore(isServer)
|
||||
return { initialState: getSnapshot(store), isServer }
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.store = initStore(props.isServer, props.initialState)
|
||||
}
|
||||
|
||||
render() {
|
||||
render () {
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<Page title='Index Page' linkTo='/other' />
|
||||
|
|
|
@ -5,18 +5,18 @@ import { initStore } from '../store'
|
|||
import Page from '../components/Page'
|
||||
|
||||
export default class Counter extends React.Component {
|
||||
static getInitialProps({ req }) {
|
||||
static getInitialProps ({ req }) {
|
||||
const isServer = !!req
|
||||
const store = initStore(isServer)
|
||||
return { initialState: getSnapshot(store), isServer }
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
constructor (props) {
|
||||
super(props)
|
||||
this.store = initStore(props.isServer, props.initialState)
|
||||
}
|
||||
|
||||
render() {
|
||||
render () {
|
||||
return (
|
||||
<Provider store={this.store}>
|
||||
<Page title='Other Page' linkTo='/' />
|
||||
|
|
|
@ -5,32 +5,31 @@ let store = null
|
|||
const Store = types
|
||||
.model({
|
||||
lastUpdate: types.Date,
|
||||
light: false,
|
||||
light: false
|
||||
})
|
||||
.actions((self) => {
|
||||
let timer;
|
||||
function start() {
|
||||
let timer
|
||||
function start () {
|
||||
timer = setInterval(() => {
|
||||
// mobx-state-tree doesn't allow anonymous callbacks changing data
|
||||
// pass off to another action instead
|
||||
self.update();
|
||||
self.update()
|
||||
})
|
||||
}
|
||||
|
||||
function update() {
|
||||
function update () {
|
||||
self.lastUpdate = Date.now()
|
||||
self.light = true
|
||||
}
|
||||
|
||||
function stop() {
|
||||
clearInterval(timer);
|
||||
function stop () {
|
||||
clearInterval(timer)
|
||||
}
|
||||
|
||||
return { start, stop, update }
|
||||
})
|
||||
|
||||
|
||||
export function initStore(isServer, snapshot = null) {
|
||||
export function initStore (isServer, snapshot = null) {
|
||||
if (isServer) {
|
||||
store = Store.create({ lastUpdate: Date.now() })
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global window, document, __NEXT_DATA__ */
|
||||
/* global window, document */
|
||||
import EventEmitter from './EventEmitter'
|
||||
|
||||
const webpackModule = module
|
||||
|
@ -69,10 +69,7 @@ export default class PageLoader {
|
|||
|
||||
loadScript (route) {
|
||||
route = this.normalizeRoute(route)
|
||||
|
||||
if (__NEXT_DATA__.nextExport) {
|
||||
route = route === '/' ? '/index.js' : `${route}/index.js`
|
||||
}
|
||||
route = route === '/' ? '/index.js' : `${route}.js`
|
||||
|
||||
const script = document.createElement('script')
|
||||
const url = `${this.assetPrefix}/_next/${encodeURIComponent(this.buildId)}/page${route}`
|
||||
|
|
|
@ -28,6 +28,16 @@ export default class PagesPlugin {
|
|||
|
||||
routeName = `/${routeName.replace(/(^|\/)index$/, '')}`
|
||||
|
||||
// If there's file named pageDir/index.js
|
||||
// We are going to rewrite it as pageDir.js
|
||||
// With this, we can statically decide the filepath of the page
|
||||
// based on the page name.
|
||||
const rule = /^bundles[/\\]pages[/\\].*[/\\]index\.js$/
|
||||
if (rule.test(chunk.name)) {
|
||||
delete compilation.assets[chunk.name]
|
||||
chunk.name = chunk.name.replace(/[/\\]index\.js$/, `.js`)
|
||||
}
|
||||
|
||||
const content = page.source()
|
||||
const newContent = `
|
||||
window.__NEXT_REGISTER_PAGE('${routeName}', function() {
|
||||
|
|
|
@ -80,13 +80,13 @@ export class Head extends Component {
|
|||
|
||||
render () {
|
||||
const { head, styles, __NEXT_DATA__ } = this.context._documentProps
|
||||
const { pathname, buildId, assetPrefix, nextExport } = __NEXT_DATA__
|
||||
const pagePathname = getPagePathname(pathname, nextExport)
|
||||
const { pathname, buildId, assetPrefix } = __NEXT_DATA__
|
||||
const pagePathname = getPagePathname(pathname)
|
||||
|
||||
return <head {...this.props}>
|
||||
{(head || []).map((h, i) => React.cloneElement(h, { key: i }))}
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} as='script' />
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error/index.js`} as='script' />
|
||||
<link rel='preload' href={`${assetPrefix}/_next/${buildId}/page/_error.js`} as='script' />
|
||||
{this.getPreloadDynamicChunks()}
|
||||
{this.getPreloadMainLinks()}
|
||||
{styles || null}
|
||||
|
@ -174,8 +174,8 @@ export class NextScript extends Component {
|
|||
|
||||
render () {
|
||||
const { staticMarkup, __NEXT_DATA__, chunks } = this.context._documentProps
|
||||
const { pathname, nextExport, buildId, assetPrefix } = __NEXT_DATA__
|
||||
const pagePathname = getPagePathname(pathname, nextExport)
|
||||
const { pathname, buildId, assetPrefix } = __NEXT_DATA__
|
||||
const pagePathname = getPagePathname(pathname)
|
||||
|
||||
__NEXT_DATA__.chunks = chunks
|
||||
|
||||
|
@ -197,15 +197,17 @@ export class NextScript extends Component {
|
|||
`
|
||||
}} />}
|
||||
<script async id={`__NEXT_PAGE__${pathname}`} type='text/javascript' src={`${assetPrefix}/_next/${buildId}/page${pagePathname}`} />
|
||||
<script async id={`__NEXT_PAGE__/_error`} type='text/javascript' src={`${assetPrefix}/_next/${buildId}/page/_error/index.js`} />
|
||||
<script async id={`__NEXT_PAGE__/_error`} type='text/javascript' src={`${assetPrefix}/_next/${buildId}/page/_error.js`} />
|
||||
{staticMarkup ? null : this.getDynamicChunks()}
|
||||
{staticMarkup ? null : this.getScripts()}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
function getPagePathname (pathname, nextExport) {
|
||||
if (!nextExport) return pathname
|
||||
if (pathname === '/') return '/index.js'
|
||||
return `${pathname}/index.js`
|
||||
function getPagePathname (pathname) {
|
||||
if (pathname === '/') {
|
||||
return '/index.js'
|
||||
}
|
||||
|
||||
return `${pathname}.js`
|
||||
}
|
||||
|
|
|
@ -141,11 +141,13 @@ function copyPages (nextDir, outDir, buildId) {
|
|||
}
|
||||
|
||||
let destFilePath = null
|
||||
if (/index\.js$/.test(filename)) {
|
||||
if (relativeFilePath === `${sep}index.js`) {
|
||||
destFilePath = join(outDir, '_next', buildId, 'page', relativeFilePath)
|
||||
} else {
|
||||
const newRelativeFilePath = relativeFilePath.replace(/\.js/, `${sep}index.js`)
|
||||
} else if (/index\.js$/.test(filename)) {
|
||||
const newRelativeFilePath = relativeFilePath.replace(`${sep}index.js`, '.js')
|
||||
destFilePath = join(outDir, '_next', buildId, 'page', newRelativeFilePath)
|
||||
} else {
|
||||
destFilePath = join(outDir, '_next', buildId, 'page', relativeFilePath)
|
||||
}
|
||||
|
||||
cp(fullFilePath, destFilePath)
|
||||
|
|
|
@ -201,7 +201,10 @@ export default class Server {
|
|||
|
||||
'/_next/:buildId/page/:path*': async (req, res, params) => {
|
||||
const paths = params.path || ['']
|
||||
const page = `/${paths.join('/')}`
|
||||
// We need to remove `.js` from the page otherwise it won't work with
|
||||
// page rewrites
|
||||
// eg:- we re-write page/index.js into page.js
|
||||
const page = `/${paths.join('/')}`.replace('.js', '')
|
||||
|
||||
if (!this.handleBuildId(params.buildId, res)) {
|
||||
const error = new Error('INVALID_BUILD_ID')
|
||||
|
|
Loading…
Reference in a new issue