From 475b426ed1bf408d1d4471908400dc234d50c683 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 25 Jul 2018 13:45:42 +0200 Subject: [PATCH] Compile pages to .next/static directory (#4828) * Compile pages to .next/static//pages/ * Fix test * Export class instead of using exports * Use constant for static directory * Add comment about what the middleware does --- build/webpack.js | 2 +- .../webpack/plugins/pages-manifest-plugin.js | 2 +- .../webpack/plugins/react-loadable-plugin.js | 4 +- build/webpack/utils.js | 19 ++--- lib/constants.js | 7 +- lib/page-loader.js | 2 +- package.json | 1 - server/document.js | 12 +-- server/export.js | 48 +----------- server/hot-reloader.js | 58 ++++++++++++-- server/index.js | 78 ++++--------------- server/on-demand-entry-handler.js | 3 +- server/render.js | 10 +-- test/integration/ondemand/test/index.test.js | 8 +- .../integration/production/test/index.test.js | 2 +- .../_resolvedata/server/pages-manifest.json | 10 +-- .../development}/pages/_error.js | 0 .../development}/pages/index.js | 0 .../development}/pages/non-existent-child.js | 0 .../development}/pages/world.js | 0 test/isolated/require-page.test.js | 4 +- test/isolated/webpack-utils.test.js | 32 +++++--- yarn.lock | 10 --- 23 files changed, 134 insertions(+), 178 deletions(-) rename test/isolated/_resolvedata/server/{bundles => static/development}/pages/_error.js (100%) rename test/isolated/_resolvedata/server/{bundles => static/development}/pages/index.js (100%) rename test/isolated/_resolvedata/server/{bundles => static/development}/pages/non-existent-child.js (100%) rename test/isolated/_resolvedata/server/{bundles => static/development}/pages/world.js (100%) diff --git a/build/webpack.js b/build/webpack.js index 671a70b9..c8e1a365 100644 --- a/build/webpack.js +++ b/build/webpack.js @@ -128,7 +128,7 @@ export default async function getBaseWebpackConfig (dir: string, {dev = false, i .filter((p) => !!p) const outputPath = path.join(dir, config.distDir, isServer ? SERVER_DIRECTORY : '') - const pagesEntries = await getPages(dir, {nextPagesDir: DEFAULT_PAGES_DIR, dev, isServer, pageExtensions: config.pageExtensions.join('|')}) + const pagesEntries = await getPages(dir, {nextPagesDir: DEFAULT_PAGES_DIR, dev, buildId, isServer, pageExtensions: config.pageExtensions.join('|')}) const totalPages = Object.keys(pagesEntries).length const clientEntries = !isServer ? { // Backwards compatibility diff --git a/build/webpack/plugins/pages-manifest-plugin.js b/build/webpack/plugins/pages-manifest-plugin.js index 9034539c..69eda897 100644 --- a/build/webpack/plugins/pages-manifest-plugin.js +++ b/build/webpack/plugins/pages-manifest-plugin.js @@ -3,7 +3,7 @@ import { RawSource } from 'webpack-sources' import {PAGES_MANIFEST, ROUTE_NAME_REGEX} from '../../../lib/constants' // This plugin creates a pages-manifest.json from page entrypoints. -// This is used for mapping paths like `/` to `.next/dist/bundles/pages/index.js` when doing SSR +// This is used for mapping paths like `/` to `.next/server/static//pages/index.js` when doing SSR // It's also used by next export to provide defaultPathMap export default class PagesManifestPlugin { apply (compiler: any) { diff --git a/build/webpack/plugins/react-loadable-plugin.js b/build/webpack/plugins/react-loadable-plugin.js index e4796409..7f516c95 100644 --- a/build/webpack/plugins/react-loadable-plugin.js +++ b/build/webpack/plugins/react-loadable-plugin.js @@ -33,7 +33,7 @@ function buildManifest (compiler, compilation) { return manifest } -class ReactLoadablePlugin { +export class ReactLoadablePlugin { constructor (opts = {}) { this.filename = opts.filename } @@ -54,5 +54,3 @@ class ReactLoadablePlugin { }) } } - -exports.ReactLoadablePlugin = ReactLoadablePlugin diff --git a/build/webpack/utils.js b/build/webpack/utils.js index f4a11e5b..8be56e6c 100644 --- a/build/webpack/utils.js +++ b/build/webpack/utils.js @@ -1,13 +1,14 @@ import path from 'path' import promisify from '../../lib/promisify' import globModule from 'glob' +import {CLIENT_STATIC_FILES_PATH} from '../../lib/constants' const glob = promisify(globModule) -export async function getPages (dir, {nextPagesDir, dev, isServer, pageExtensions}) { +export async function getPages (dir, {nextPagesDir, dev, buildId, isServer, pageExtensions}) { const pageFiles = await getPagePaths(dir, {dev, isServer, pageExtensions}) - return getPageEntries(pageFiles, {nextPagesDir, isServer, pageExtensions}) + return getPageEntries(pageFiles, {nextPagesDir, buildId, isServer, pageExtensions}) } export async function getPagePaths (dir, {dev, isServer, pageExtensions}) { @@ -25,7 +26,7 @@ export async function getPagePaths (dir, {dev, isServer, pageExtensions}) { } // Convert page path into single entry -export function createEntry (filePath, {name, pageExtensions} = {}) { +export function createEntry (filePath, {buildId = '', name, pageExtensions} = {}) { const parsedPath = path.parse(filePath) let entryName = name || filePath @@ -41,35 +42,35 @@ export function createEntry (filePath, {name, pageExtensions} = {}) { } return { - name: path.join('bundles', entryName), + name: path.join(CLIENT_STATIC_FILES_PATH, buildId, entryName), files: [parsedPath.root ? filePath : `./${filePath}`] // The entry always has to be an array. } } // Convert page paths into entries -export function getPageEntries (pagePaths, {nextPagesDir, isServer = false, pageExtensions} = {}) { +export function getPageEntries (pagePaths, {nextPagesDir, buildId, isServer = false, pageExtensions} = {}) { const entries = {} for (const filePath of pagePaths) { - const entry = createEntry(filePath, {pageExtensions}) + const entry = createEntry(filePath, {pageExtensions, buildId}) entries[entry.name] = entry.files } const appPagePath = path.join(nextPagesDir, '_app.js') - const appPageEntry = createEntry(appPagePath, {name: 'pages/_app.js'}) // default app.js + const appPageEntry = createEntry(appPagePath, {buildId, name: 'pages/_app.js'}) // default app.js if (!entries[appPageEntry.name]) { entries[appPageEntry.name] = appPageEntry.files } const errorPagePath = path.join(nextPagesDir, '_error.js') - const errorPageEntry = createEntry(errorPagePath, {name: 'pages/_error.js'}) // default error.js + const errorPageEntry = createEntry(errorPagePath, {buildId, name: 'pages/_error.js'}) // default error.js if (!entries[errorPageEntry.name]) { entries[errorPageEntry.name] = errorPageEntry.files } if (isServer) { const documentPagePath = path.join(nextPagesDir, '_document.js') - const documentPageEntry = createEntry(documentPagePath, {name: 'pages/_document.js'}) // default _document.js + const documentPageEntry = createEntry(documentPagePath, {buildId, name: 'pages/_document.js'}) // default _document.js if (!entries[documentPageEntry.name]) { entries[documentPageEntry.name] = documentPageEntry.files } diff --git a/lib/constants.js b/lib/constants.js index 5fe9407f..97938900 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -14,9 +14,12 @@ export const BLOCKED_PAGES = [ '/_app', '/_error' ] -export const IS_BUNDLED_PAGE_REGEX = /^bundles[/\\]pages.*\.js$/ -export const ROUTE_NAME_REGEX = /^bundles[/\\]pages[/\\](.*)\.js$/ +// matches static//pages/.js +export const IS_BUNDLED_PAGE_REGEX = /^static[/\\][^/\\]+[/\\]pages.*\.js$/ +// matches static//pages/:page*.js +export const ROUTE_NAME_REGEX = /^static[/\\][^/\\]+[/\\]pages[/\\](.*)\.js$/ export const NEXT_PROJECT_ROOT = join(__dirname, '..', '..') export const NEXT_PROJECT_ROOT_DIST = join(NEXT_PROJECT_ROOT, 'dist') export const NEXT_PROJECT_ROOT_NODE_MODULES = join(NEXT_PROJECT_ROOT, 'node_modules') export const DEFAULT_PAGES_DIR = join(NEXT_PROJECT_ROOT_DIST, 'pages') +export const CLIENT_STATIC_FILES_PATH = 'static' diff --git a/lib/page-loader.js b/lib/page-loader.js index a2e85b51..938d3c8f 100644 --- a/lib/page-loader.js +++ b/lib/page-loader.js @@ -69,7 +69,7 @@ export default class PageLoader { const scriptRoute = route === '/' ? '/index.js' : `${route}.js` const script = document.createElement('script') - const url = `${this.assetPrefix}/_next/${encodeURIComponent(this.buildId)}/page${scriptRoute}` + const url = `${this.assetPrefix}/_next/static/${encodeURIComponent(this.buildId)}/pages${scriptRoute}` script.src = url script.onerror = () => { const error = new Error(`Error when loading route: ${route}`) diff --git a/package.json b/package.json index 251d6cd8..120e7cc0 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,6 @@ "unfetch": "3.0.0", "url": "0.11.0", "uuid": "3.1.0", - "walk": "2.3.9", "webpack": "4.16.1", "webpack-dev-middleware": "3.1.3", "webpack-hot-middleware": "2.22.2", diff --git a/server/document.js b/server/document.js index 92fe56c6..b77ab3e5 100644 --- a/server/document.js +++ b/server/document.js @@ -80,9 +80,9 @@ export class Head extends Component { return {(head || []).map((h, i) => React.cloneElement(h, { key: h.key || i }))} - {page !== '/_error' && } - - + {page !== '/_error' && } + + {this.getPreloadDynamicChunks()} {this.getPreloadMainLinks()} {styles || null} @@ -168,9 +168,9 @@ export class NextScript extends Component { })`: ''} ` }} />} - {page !== '/_error' &&