From fc095802196dd757410f0e5f40503213a8f6f273 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 27 Mar 2018 21:59:43 +0200 Subject: [PATCH 01/12] Initial implementation of next export without exportPathMap --- server/build/webpack/utils.js | 2 +- server/export.js | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/server/build/webpack/utils.js b/server/build/webpack/utils.js index d674e8a672a0e..eaa3398c01959 100644 --- a/server/build/webpack/utils.js +++ b/server/build/webpack/utils.js @@ -9,7 +9,7 @@ export async function getPages (dir, {dev, isServer, pageExtensions}) { return getPageEntries(pageFiles, {isServer, pageExtensions}) } -async function getPagePaths (dir, {dev, isServer, pageExtensions}) { +export async function getPagePaths (dir, {dev, isServer, pageExtensions}) { let pages if (dev) { diff --git a/server/export.js b/server/export.js index 0a0fe9bd4ffd9..8056a562bee68 100644 --- a/server/export.js +++ b/server/export.js @@ -8,16 +8,16 @@ import getConfig from './config' import {PHASE_EXPORT} from '../lib/constants' import { renderToHTML } from './render' import { getAvailableChunks } from './utils' -import { printAndExit } from '../lib/utils' import { setAssetPrefix } from '../lib/asset' import * as envConfig from '../lib/runtime-config' +import { getPages } from '../server/build/webpack/utils' export default async function (dir, options, configuration) { dir = resolve(dir) const nextConfig = configuration || getConfig(PHASE_EXPORT, dir) const nextDir = join(dir, nextConfig.distDir) - log(` using build directory: ${nextDir}`) + log(`> using build directory: ${nextDir}`) if (!existsSync(nextDir)) { console.error( @@ -73,10 +73,21 @@ export default async function (dir, options, configuration) { // Get the exportPathMap from the `next.config.js` if (typeof nextConfig.exportPathMap !== 'function') { - printAndExit( - '> Could not find "exportPathMap" function inside "next.config.js"\n' + - '> "next export" uses that function to build html pages.' - ) + console.log('> Could not find "exportPathMap" function inside "next.config.js". Using paths from "/pages" instead.') + nextConfig.exportPathMap = async () => { + const dev = false + const isServer = false + const pageExtensions = nextConfig.pageExtensions.join('|') + const pageEntries = await getPages(dir, {dev, isServer, pageExtensions}) + + const pathMap = {} + for (const pageEntryPath of Object.keys(pageEntries)) { + const page = pageEntryPath.replace(/^bundles\/pages/, '').replace(/\.js$/, '') + pathMap[page] = { page } + } + + return pathMap + } } const exportPathMap = await nextConfig.exportPathMap() @@ -115,7 +126,7 @@ export default async function (dir, options, configuration) { } for (const path of exportPaths) { - log(` exporting path: ${path}`) + log(`> exporting path: ${path}`) if (!path.startsWith('/')) { throw new Error(`path "${path}" doesn't start with a backslash`) } From af12570bbd2cdce293458fb0f28cc50e3fb266b5 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Tue, 27 Mar 2018 22:03:09 +0200 Subject: [PATCH 02/12] Shorter message --- server/export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/export.js b/server/export.js index 8056a562bee68..f6728444dadc0 100644 --- a/server/export.js +++ b/server/export.js @@ -73,7 +73,7 @@ export default async function (dir, options, configuration) { // Get the exportPathMap from the `next.config.js` if (typeof nextConfig.exportPathMap !== 'function') { - console.log('> Could not find "exportPathMap" function inside "next.config.js". Using paths from "/pages" instead.') + console.log('> No "exportPathMap" found in "next.config.js". Generating map from "./pages"') nextConfig.exportPathMap = async () => { const dev = false const isServer = false From f60a4fa2f6e4a4ac9ebd623a95cadaf133259aaa Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 28 Mar 2018 15:46:14 +0200 Subject: [PATCH 03/12] Set up flow --- .babelrc | 3 ++- .flowconfig | 3 +++ package.json | 1 + server/config.js | 20 ++++++++++++-------- yarn.lock | 2 +- 5 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 .flowconfig diff --git a/.babelrc b/.babelrc index 900da0c07bc95..2f687fa0ecaf4 100644 --- a/.babelrc +++ b/.babelrc @@ -1,7 +1,8 @@ { "presets": [ "env", - "react" + "react", + "flow" ], "plugins": [ "transform-object-rest-spread", diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000000000..6e14dc0618ae2 --- /dev/null +++ b/.flowconfig @@ -0,0 +1,3 @@ +[ignore] +/examples/.* +/examples/.* \ No newline at end of file diff --git a/package.json b/package.json index 50e583f65f49d..bbc0a53f5a2a5 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "babel-plugin-istanbul": "4.1.5", "babel-plugin-transform-remove-strict-mode": "0.0.2", "babel-preset-es2015": "6.24.1", + "babel-preset-flow": "6.23.0", "benchmark": "2.1.4", "cheerio": "0.22.0", "chromedriver": "2.32.3", diff --git a/server/config.js b/server/config.js index ecba94de38c0b..aef468ad8ec7b 100644 --- a/server/config.js +++ b/server/config.js @@ -1,3 +1,4 @@ +// @flow import findUp from 'find-up' const cache = new Map() @@ -11,28 +12,31 @@ const defaultConfig = { configOrigin: 'default', useFileSystemPublicRoutes: true, generateEtags: true, - pageExtensions: ['jsx', 'js'] // jsx before js because otherwise regex matching will match js first + pageExtensions: ['jsx', 'js'] } -export default function getConfig (phase, dir, customConfig) { +export default function getConfig (phase: string, dir: string, customConfig?: ?Object) { if (!cache.has(dir)) { cache.set(dir, loadConfig(phase, dir, customConfig)) } return cache.get(dir) } -export function loadConfig (phase, dir, customConfig) { +export function loadConfig (phase: string, dir: string, customConfig?: ?Object) { if (customConfig && typeof customConfig === 'object') { - customConfig.configOrigin = 'server' - return withDefaults(customConfig) + return withDefaults({ + configOrigin: 'server', + ...customConfig + }) } - const path = findUp.sync('next.config.js', { + const path: string = findUp.sync('next.config.js', { cwd: dir }) let userConfig = {} if (path && path.length) { + // $FlowFixMe const userConfigModule = require(path) userConfig = userConfigModule.default || userConfigModule if (typeof userConfigModule === 'function') { @@ -44,6 +48,6 @@ export function loadConfig (phase, dir, customConfig) { return withDefaults(userConfig) } -function withDefaults (config) { - return Object.assign({}, defaultConfig, config) +function withDefaults (config: Object) { + return {...defaultConfig, config} } diff --git a/yarn.lock b/yarn.lock index dae54d70702d1..aa0d8767cca58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1058,7 +1058,7 @@ babel-preset-es2015@6.24.1: babel-plugin-transform-es2015-unicode-regex "^6.24.1" babel-plugin-transform-regenerator "^6.24.1" -babel-preset-flow@^6.23.0: +babel-preset-flow@6.23.0, babel-preset-flow@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" dependencies: From d232646dfb527f8fdacb005c795ae8ca6c821d3a Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 28 Mar 2018 15:46:37 +0200 Subject: [PATCH 04/12] Create pages manifest --- server/build/plugins/pages-manifest-plugin.js | 26 +++++++++++++++++++ server/build/webpack.js | 2 ++ server/require.js | 22 +++++----------- .../_resolvedata/dist/bundles/pages/_error.js | 3 +++ .../_resolvedata/dist/pages-manifest.json | 6 +++++ test/isolated/require-page.test.js | 15 +++++------ 6 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 server/build/plugins/pages-manifest-plugin.js create mode 100644 test/isolated/_resolvedata/dist/bundles/pages/_error.js create mode 100644 test/isolated/_resolvedata/dist/pages-manifest.json diff --git a/server/build/plugins/pages-manifest-plugin.js b/server/build/plugins/pages-manifest-plugin.js new file mode 100644 index 0000000000000..8ca7b6c774265 --- /dev/null +++ b/server/build/plugins/pages-manifest-plugin.js @@ -0,0 +1,26 @@ +// @flow +import { RawSource } from 'webpack-sources' +import { MATCH_ROUTE_NAME } from '../../utils' + +export default class PagesManifestPlugin { + apply (compiler: any) { + compiler.plugin('emit', (compilation, callback) => { + const {entries} = compilation + const pages = {} + + for (const entry of entries) { + const pagePath = MATCH_ROUTE_NAME.exec(entry.name)[1] + + if (!pagePath) { + continue + } + + const {name} = entry + pages[`/${pagePath}`] = name + } + + compilation.assets['pages-manifest.json'] = new RawSource(JSON.stringify(pages)) + callback() + }) + } +} diff --git a/server/build/webpack.js b/server/build/webpack.js index 28338137a97d8..91be233cea18d 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -10,6 +10,7 @@ import PagesPlugin from './plugins/pages-plugin' import NextJsSsrImportPlugin from './plugins/nextjs-ssr-import' import DynamicChunksPlugin from './plugins/dynamic-chunks-plugin' import UnlinkFilePlugin from './plugins/unlink-file-plugin' +import PagesManifestPlugin from './plugins/pages-manifest-plugin' import findBabelConfig from './babel/find-config' const nextDir = path.join(__dirname, '..', '..', '..') @@ -254,6 +255,7 @@ export default async function getBaseWebpackConfig (dir, {dev = false, isServer 'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production') }), !dev && new webpack.optimize.ModuleConcatenationPlugin(), + isServer && new PagesManifestPlugin(), !isServer && new PagesPlugin(), !isServer && new DynamicChunksPlugin(), isServer && new NextJsSsrImportPlugin(), diff --git a/server/require.js b/server/require.js index 0ced446d0bc72..df2c1d19727f1 100644 --- a/server/require.js +++ b/server/require.js @@ -1,5 +1,4 @@ -import {join, parse, normalize, sep} from 'path' -import fs from 'mz/fs' +import {join, normalize, sep} from 'path' export function pageNotFoundError (page) { const err = new Error(`Cannot find module for page: ${page}`) @@ -33,7 +32,8 @@ export function normalizePagePath (page) { } export function getPagePath (page, {dir, dist}) { - const pageBundlesPath = join(dir, dist, 'dist', 'bundles', 'pages') + const serverBuildPath = join(dir, dist, 'dist') + const pagesManifest = require(join(serverBuildPath, 'pages-manifest.json')) try { page = normalizePagePath(page) @@ -42,24 +42,14 @@ export function getPagePath (page, {dir, dist}) { throw pageNotFoundError(page) } - const pagePath = join(pageBundlesPath, page) // Path to the page that is to be loaded - - // Don't allow wandering outside of the bundles directory - const pathDir = parse(pagePath).dir - if (pathDir.indexOf(pageBundlesPath) !== 0) { - console.error('Resolved page path goes outside of bundles path') + if (!pagesManifest[page]) { throw pageNotFoundError(page) } - return pagePath + return join(serverBuildPath, pagesManifest[page]) } export default async function requirePage (page, {dir, dist}) { - const pagePath = getPagePath(page, {dir, dist}) + '.js' - const fileExists = await fs.exists(pagePath) - if (!fileExists) { - throw pageNotFoundError(page) - } - + const pagePath = getPagePath(page, {dir, dist}) return require(pagePath) } diff --git a/test/isolated/_resolvedata/dist/bundles/pages/_error.js b/test/isolated/_resolvedata/dist/bundles/pages/_error.js new file mode 100644 index 0000000000000..0af8646cffcd5 --- /dev/null +++ b/test/isolated/_resolvedata/dist/bundles/pages/_error.js @@ -0,0 +1,3 @@ +module.exports = { + test: 'error' +} \ No newline at end of file diff --git a/test/isolated/_resolvedata/dist/pages-manifest.json b/test/isolated/_resolvedata/dist/pages-manifest.json new file mode 100644 index 0000000000000..b42b6e044bb68 --- /dev/null +++ b/test/isolated/_resolvedata/dist/pages-manifest.json @@ -0,0 +1,6 @@ +{ + "/index": "bundles/pages/index.js", + "/world": "bundles/pages/world.js", + "/_error": "bundles/pages/_error.js", + "/non-existent-child": "bundles/pages/non-existent-child.js" +} \ No newline at end of file diff --git a/test/isolated/require-page.test.js b/test/isolated/require-page.test.js index c3c0c2629db89..291bfb056b8be 100644 --- a/test/isolated/require-page.test.js +++ b/test/isolated/require-page.test.js @@ -3,10 +3,7 @@ import { join, sep } from 'path' import requirePage, {getPagePath, normalizePagePath, pageNotFoundError} from '../../dist/server/require' -const dir = '/path/to/some/project' -const dist = '.next' - -const pathToBundles = join(dir, dist, 'dist', 'bundles', 'pages') +const pathToBundles = join(__dirname, '_resolvedata', 'dist', 'bundles', 'pages') describe('pageNotFoundError', () => { it('Should throw error with ENOENT code', () => { @@ -42,17 +39,17 @@ describe('normalizePagePath', () => { describe('getPagePath', () => { it('Should append /index to the / page', () => { - const pagePath = getPagePath('/', {dir, dist}) - expect(pagePath).toBe(join(pathToBundles, `${sep}index`)) + const pagePath = getPagePath('/', {dir: __dirname, dist: '_resolvedata'}) + expect(pagePath).toBe(join(pathToBundles, `${sep}index.js`)) }) it('Should prepend / when a page does not have it', () => { - const pagePath = getPagePath('_error', {dir, dist}) - expect(pagePath).toBe(join(pathToBundles, `${sep}_error`)) + const pagePath = getPagePath('_error', {dir: __dirname, dist: '_resolvedata'}) + expect(pagePath).toBe(join(pathToBundles, `${sep}_error.js`)) }) it('Should throw with paths containing ../', () => { - expect(() => getPagePath('/../../package.json', {dir, dist})).toThrow() + expect(() => getPagePath('/../../package.json', {dir: __dirname, dist: '_resolvedata'})).toThrow() }) }) From c4d2af6a978a7dfc0d1b1974629da19bbccaadd7 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 28 Mar 2018 22:58:56 +0200 Subject: [PATCH 05/12] Use pagesManifest for next export --- lib/constants.js | 1 + server/build/plugins/pages-manifest-plugin.js | 3 +- server/export.js | 31 +++++++++---------- server/require.js | 3 +- test/isolated/require-page.test.js | 3 +- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/lib/constants.js b/lib/constants.js index 1877517a2ec7e..ec595fa6dad85 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -2,3 +2,4 @@ export const PHASE_EXPORT = 'phase-export' export const PHASE_PRODUCTION_BUILD = 'phase-production-build' export const PHASE_PRODUCTION_SERVER = 'phase-production-server' export const PHASE_DEVELOPMENT_SERVER = 'phase-development-server' +export const PAGES_MANIFEST = 'pages-manifest.json' diff --git a/server/build/plugins/pages-manifest-plugin.js b/server/build/plugins/pages-manifest-plugin.js index 8ca7b6c774265..b3803422e5fb9 100644 --- a/server/build/plugins/pages-manifest-plugin.js +++ b/server/build/plugins/pages-manifest-plugin.js @@ -1,6 +1,7 @@ // @flow import { RawSource } from 'webpack-sources' import { MATCH_ROUTE_NAME } from '../../utils' +import {PAGES_MANIFEST} from '../../../lib/constants' export default class PagesManifestPlugin { apply (compiler: any) { @@ -19,7 +20,7 @@ export default class PagesManifestPlugin { pages[`/${pagePath}`] = name } - compilation.assets['pages-manifest.json'] = new RawSource(JSON.stringify(pages)) + compilation.assets[PAGES_MANIFEST] = new RawSource(JSON.stringify(pages)) callback() }) } diff --git a/server/export.js b/server/export.js index f6728444dadc0..c2ed256468ebe 100644 --- a/server/export.js +++ b/server/export.js @@ -5,12 +5,11 @@ import walk from 'walk' import { extname, resolve, join, dirname, sep } from 'path' import { existsSync, readFileSync, writeFileSync } from 'fs' import getConfig from './config' -import {PHASE_EXPORT} from '../lib/constants' +import {PHASE_EXPORT, PAGES_MANIFEST} from '../lib/constants' import { renderToHTML } from './render' import { getAvailableChunks } from './utils' import { setAssetPrefix } from '../lib/asset' import * as envConfig from '../lib/runtime-config' -import { getPages } from '../server/build/webpack/utils' export default async function (dir, options, configuration) { dir = resolve(dir) @@ -27,6 +26,17 @@ export default async function (dir, options, configuration) { } const buildId = readFileSync(join(nextDir, 'BUILD_ID'), 'utf8') + const pagesManifest = require(join(nextDir, 'dist', PAGES_MANIFEST)) + + const pages = Object.keys(pagesManifest) + const defaultPathMap = {} + + for (const page of pages) { + if (page === '/_document') { + continue + } + defaultPathMap[page] = { page } + } // Initialize the output directory const outDir = options.outdir @@ -74,23 +84,12 @@ export default async function (dir, options, configuration) { // Get the exportPathMap from the `next.config.js` if (typeof nextConfig.exportPathMap !== 'function') { console.log('> No "exportPathMap" found in "next.config.js". Generating map from "./pages"') - nextConfig.exportPathMap = async () => { - const dev = false - const isServer = false - const pageExtensions = nextConfig.pageExtensions.join('|') - const pageEntries = await getPages(dir, {dev, isServer, pageExtensions}) - - const pathMap = {} - for (const pageEntryPath of Object.keys(pageEntries)) { - const page = pageEntryPath.replace(/^bundles\/pages/, '').replace(/\.js$/, '') - pathMap[page] = { page } - } - - return pathMap + nextConfig.exportPathMap = async (defaultMap) => { + return defaultMap } } - const exportPathMap = await nextConfig.exportPathMap() + const exportPathMap = await nextConfig.exportPathMap(defaultPathMap) const exportPaths = Object.keys(exportPathMap) // Start the rendering process diff --git a/server/require.js b/server/require.js index df2c1d19727f1..0f66ac12dbf90 100644 --- a/server/require.js +++ b/server/require.js @@ -1,4 +1,5 @@ import {join, normalize, sep} from 'path' +import {PAGES_MANIFEST} from '../lib/constants' export function pageNotFoundError (page) { const err = new Error(`Cannot find module for page: ${page}`) @@ -33,7 +34,7 @@ export function normalizePagePath (page) { export function getPagePath (page, {dir, dist}) { const serverBuildPath = join(dir, dist, 'dist') - const pagesManifest = require(join(serverBuildPath, 'pages-manifest.json')) + const pagesManifest = require(join(serverBuildPath, PAGES_MANIFEST)) try { page = normalizePagePath(page) diff --git a/test/isolated/require-page.test.js b/test/isolated/require-page.test.js index 291bfb056b8be..bdd368de9f91f 100644 --- a/test/isolated/require-page.test.js +++ b/test/isolated/require-page.test.js @@ -1,8 +1,9 @@ /* global describe, it, expect */ -import { join, sep } from 'path' +import { join } from 'path' import requirePage, {getPagePath, normalizePagePath, pageNotFoundError} from '../../dist/server/require' +const sep = '/' const pathToBundles = join(__dirname, '_resolvedata', 'dist', 'bundles', 'pages') describe('pageNotFoundError', () => { From 917d29c83af25e60a3127829da756673b81e4e2f Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Wed, 28 Mar 2018 23:34:16 +0200 Subject: [PATCH 06/12] Fix tests --- server/config.js | 8 +++----- yarn.lock | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/server/config.js b/server/config.js index aef468ad8ec7b..045a4ac8c3f38 100644 --- a/server/config.js +++ b/server/config.js @@ -24,10 +24,8 @@ export default function getConfig (phase: string, dir: string, customConfig?: ?O export function loadConfig (phase: string, dir: string, customConfig?: ?Object) { if (customConfig && typeof customConfig === 'object') { - return withDefaults({ - configOrigin: 'server', - ...customConfig - }) + customConfig.configOrigin = 'server' + return withDefaults(customConfig) } const path: string = findUp.sync('next.config.js', { cwd: dir @@ -49,5 +47,5 @@ export function loadConfig (phase: string, dir: string, customConfig?: ?Object) } function withDefaults (config: Object) { - return {...defaultConfig, config} + return Object.assign({}, defaultConfig, config) } diff --git a/yarn.lock b/yarn.lock index aa0d8767cca58..6b6ac8532356e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -464,8 +464,8 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" atob@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.0.3.tgz#19c7a760473774468f20b2d2d03372ad7d4cbf5d" + version "2.1.0" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.0.tgz#ab2b150e51d7b122b9efc8d7340c06b6c41076bc" autoprefixer@^6.3.1: version "6.7.7" @@ -1464,12 +1464,12 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000820" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000820.tgz#7c20e25cea1768b261b724f82e3a6a253aaa1468" + version "1.0.30000821" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000821.tgz#3fcdc67c446a94a9cdd848248a4e3e54b2da7419" caniuse-lite@^1.0.30000792: - version "1.0.30000820" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000820.tgz#6e36ee75187a2c83d26d6504a1af47cc580324d2" + version "1.0.30000821" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000821.tgz#0f3223f1e048ed96451c56ca6cf197058c42cb93" capture-stack-trace@^1.0.0: version "1.0.0" @@ -2373,8 +2373,8 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.30: - version "1.3.40" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.40.tgz#1fbd6d97befd72b8a6f921dc38d22413d2f6fddf" + version "1.3.41" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.41.tgz#7e33643e00cd85edfd17e04194f6d00e73737235" elegant-spinner@^1.0.1: version "1.0.1" @@ -2466,8 +2466,8 @@ es-to-primitive@^1.1.1: is-symbol "^1.0.1" es5-ext@^0.10.14, es5-ext@^0.10.35, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.41" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.41.tgz#bab3e982d750f0112f0cb9e6abed72c59eb33eb2" + version "0.10.42" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.42.tgz#8c07dd33af04d5dcd1310b5cef13bea63a89ba8d" dependencies: es6-iterator "~2.0.3" es6-symbol "~3.1.1" @@ -6870,8 +6870,8 @@ static-extend@^0.1.1: object-copy "^0.1.0" "statuses@>= 1.3.1 < 2": - version "1.4.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" statuses@~1.3.1: version "1.3.1" From 6b61954a3d3fdab845cce9d58d7904b7a8494bec Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 29 Mar 2018 00:23:25 +0200 Subject: [PATCH 07/12] Document defaultPathMap --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index f42a28a8de58e..33e849c4b14ed 100644 --- a/readme.md +++ b/readme.md @@ -1258,7 +1258,7 @@ Simply develop your app as you normally do with Next.js. Then create a custom Ne ```js // next.config.js module.exports = { - exportPathMap: function() { + exportPathMap: function(defaultPathMap) { return { '/': { page: '/' }, '/about': { page: '/about' }, From 9ad271c5fde91154fde2decc2b95df64da6349f1 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 29 Mar 2018 10:28:59 +0200 Subject: [PATCH 08/12] Replacing the path is no longer needed --- server/require.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/server/require.js b/server/require.js index 0f66ac12dbf90..9ed05c54af284 100644 --- a/server/require.js +++ b/server/require.js @@ -1,4 +1,4 @@ -import {join, normalize, sep} from 'path' +import {join, normalize} from 'path' import {PAGES_MANIFEST} from '../lib/constants' export function pageNotFoundError (page) { @@ -18,11 +18,6 @@ export function normalizePagePath (page) { page = `/${page}` } - // Windows compatibility - if (sep !== '/') { - page = page.replace(/\//g, sep) - } - // Throw when using ../ etc in the pathname const resolvedPage = normalize(page) if (page !== resolvedPage) { From ca5d934c9647750fb6594c69cf16d13b34826492 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 29 Mar 2018 12:14:21 +0200 Subject: [PATCH 09/12] Use posix normalize for consistent behaviour --- server/require.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/require.js b/server/require.js index 9ed05c54af284..dda23bc273818 100644 --- a/server/require.js +++ b/server/require.js @@ -1,4 +1,4 @@ -import {join, normalize} from 'path' +import {join, posix} from 'path' import {PAGES_MANIFEST} from '../lib/constants' export function pageNotFoundError (page) { @@ -19,7 +19,7 @@ export function normalizePagePath (page) { } // Throw when using ../ etc in the pathname - const resolvedPage = normalize(page) + const resolvedPage = posix.normalize(page) if (page !== resolvedPage) { throw new Error('Requested and resolved page mismatch') } From 370de74717764d0b0767dad62ff3515cae99f29a Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 29 Mar 2018 13:26:21 +0200 Subject: [PATCH 10/12] Remove second instance of examples --- .flowconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/.flowconfig b/.flowconfig index 6e14dc0618ae2..581592b12a09a 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,3 +1,2 @@ [ignore] -/examples/.* /examples/.* \ No newline at end of file From 13f08d3f810e3c304cea100da594e8522bb74111 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 29 Mar 2018 13:28:55 +0200 Subject: [PATCH 11/12] Add comment about what pages-manifest does --- server/build/plugins/pages-manifest-plugin.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/build/plugins/pages-manifest-plugin.js b/server/build/plugins/pages-manifest-plugin.js index b3803422e5fb9..d5d12f0fb82a1 100644 --- a/server/build/plugins/pages-manifest-plugin.js +++ b/server/build/plugins/pages-manifest-plugin.js @@ -3,6 +3,9 @@ import { RawSource } from 'webpack-sources' import { MATCH_ROUTE_NAME } from '../../utils' import {PAGES_MANIFEST} 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 +// It's also used by next export to provide defaultPathMap export default class PagesManifestPlugin { apply (compiler: any) { compiler.plugin('emit', (compilation, callback) => { From 0a3c0d9004430a551924618eecef17b604a6e1bc Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Fri, 30 Mar 2018 14:56:02 +0200 Subject: [PATCH 12/12] Make windows path a route --- server/build/plugins/pages-manifest-plugin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/build/plugins/pages-manifest-plugin.js b/server/build/plugins/pages-manifest-plugin.js index d5d12f0fb82a1..6052a0b9ed78a 100644 --- a/server/build/plugins/pages-manifest-plugin.js +++ b/server/build/plugins/pages-manifest-plugin.js @@ -20,7 +20,7 @@ export default class PagesManifestPlugin { } const {name} = entry - pages[`/${pagePath}`] = name + pages[`/${pagePath.replace(/\\/g, '/')}`] = name } compilation.assets[PAGES_MANIFEST] = new RawSource(JSON.stringify(pages))