From 4ac96a8bb615d231619b2f6c95496c5e5f371984 Mon Sep 17 00:00:00 2001 From: George Pantazis Date: Mon, 30 Jan 2017 09:33:32 -0800 Subject: [PATCH] Add configuration to specify the name of the `pages` directory. --- bin/next-build | 11 ++++++---- bin/next-dev | 11 ++++++---- bin/next-init | 13 ++++++----- lib/router/router.js | 4 ++-- .../build/loaders/hot-self-accept-loader.js | 5 ++++- server/build/plugins/json-pages-plugin.js | 11 +++++++++- server/build/plugins/watch-pages-plugin.js | 10 ++++----- server/build/webpack.js | 14 ++++++------ server/config.js | 3 ++- server/hot-reloader.js | 4 +++- server/index.js | 4 ++-- server/render.js | 22 ++++++++++++++----- 12 files changed, 73 insertions(+), 39 deletions(-) diff --git a/bin/next-build b/bin/next-build index 6a964540ec1243..26d542c3a01fde 100755 --- a/bin/next-build +++ b/bin/next-build @@ -2,6 +2,7 @@ import { resolve, join } from 'path' import { existsSync } from 'fs' import parseArgs from 'minimist' +import getConfig from '../server/config' import build from '../server/build' import { printAndExit } from '../lib/utils' @@ -29,18 +30,20 @@ if (argv.help) { } const dir = resolve(argv._[0] || '.') +const config = getConfig(dir) +const pagesDirectory = config.pagesDirectory // Check if pages dir exists and warn if not if (!existsSync(dir)) { printAndExit(`> No such directory exists as the project root: ${dir}`) } -if (!existsSync(join(dir, 'pages'))) { - if (existsSync(join(dir, '..', 'pages'))) { - printAndExit('> No `pages` directory found. Did you mean to run `next` in the parent (`../`) directory?') +if (!existsSync(join(dir, pagesDirectory))) { + if (existsSync(join(dir, '..', pagesDirectory))) { + printAndExit(`> No \`${pagesDirectory}\` directory found. Did you mean to run \`next\` in the parent (\`../\`) directory?`) } - printAndExit('> Couldn\'t find a `pages` directory. Please create one under the project root') + printAndExit(`> Couldn't find a \`${pagesDirectory}\` directory. Please create one under the project root`) } build(dir) diff --git a/bin/next-dev b/bin/next-dev index d5055a3cf20042..c434aba115961d 100755 --- a/bin/next-dev +++ b/bin/next-dev @@ -4,6 +4,7 @@ import { resolve, join } from 'path' import parseArgs from 'minimist' import { existsSync, readFileSync } from 'fs' import Server from '../server' +import getConfig from '../server/config' import { printAndExit } from '../lib/utils' import pkgUp from 'pkg-up' @@ -40,18 +41,20 @@ if (argv.help) { } const dir = resolve(argv._[0] || '.') +const config = getConfig(dir) +const pagesDirectory = config.pagesDirectory // Check if pages dir exists and warn if not if (!existsSync(dir)) { printAndExit(`> No such directory exists as the project root: ${dir}`) } -if (!existsSync(join(dir, 'pages'))) { - if (existsSync(join(dir, '..', 'pages'))) { - printAndExit('> No `pages` directory found. Did you mean to run `next` in the parent (`../`) directory?') +if (!existsSync(join(dir, pagesDirectory))) { + if (existsSync(join(dir, '..', pagesDirectory))) { + printAndExit(`> No \`${pagesDirectory}\` directory found. Did you mean to run \`next\` in the parent (\`../\`) directory?`) } - printAndExit('> Couldn\'t find a `pages` directory. Please create one under the project root') + printAndExit(`> Couldn't find a \`${pagesDirectory}\` directory. Please create one under the project root`) } const srv = new Server({ dir, dev: true }) diff --git a/bin/next-init b/bin/next-init index e67817ba7d5d3d..ccc646568d52b8 100755 --- a/bin/next-init +++ b/bin/next-init @@ -3,6 +3,7 @@ import { resolve, join, basename } from 'path' import parseArgs from 'minimist' import { exists, writeFile, mkdir } from 'mz/fs' import mkdirp from 'mkdirp-then' +import getConfig from '../server/config' const argv = parseArgs(process.argv.slice(2), { alias: { @@ -29,9 +30,11 @@ if (argv.help) { } const dir = resolve(argv._[0] || '.') +const config = getConfig(dir) +const pagesDirectory = config.pagesDirectory -if (basename(dir) === 'pages') { - console.warn('Your root directory is named "pages". This looks suspicious. You probably want to go one directory up.') +if (basename(dir) === pagesDirectory) { + console.warn(`Your root directory is named "${pagesDirectory}". This looks suspicious. You probably want to go one directory up.`) process.exit(1) } @@ -49,9 +52,9 @@ exists(dir) await mkdir(join(dir, 'static')) } - if (!await exists(join(dir, 'pages'))) { - await mkdir(join(dir, 'pages')) - await writeFile(join(dir, 'pages', 'index.js'), basePage) + if (!await exists(join(dir, pagesDirectory))) { + await mkdir(join(dir, pagesDirectory)) + await writeFile(join(dir, pagesDirectory, 'index.js'), basePage) } }) .catch((err) => { diff --git a/lib/router/router.js b/lib/router/router.js index a830726aee49ae..016757eb43b4b3 100644 --- a/lib/router/router.js +++ b/lib/router/router.js @@ -307,8 +307,8 @@ export default class Router extends EventEmitter { } doFetchRoute (route) { - const { buildId } = window.__NEXT_DATA__ - const url = `/_next/${encodeURIComponent(buildId)}/pages${route}` + const { buildId, pagesDirectory } = window.__NEXT_DATA__ + const url = `/_next/${encodeURIComponent(buildId)}/${pagesDirectory}${route}` return fetch(url, { method: 'GET', headers: { 'Accept': 'application/json' } diff --git a/server/build/loaders/hot-self-accept-loader.js b/server/build/loaders/hot-self-accept-loader.js index b33a31755f8bcd..95ebabce2e1cdd 100644 --- a/server/build/loaders/hot-self-accept-loader.js +++ b/server/build/loaders/hot-self-accept-loader.js @@ -1,4 +1,5 @@ import { resolve, relative } from 'path' +import getConfig from '../../config' module.exports = function (content, sourceMap) { this.cacheable() @@ -34,7 +35,9 @@ module.exports = function (content, sourceMap) { const nextPagesDir = resolve(__dirname, '..', '..', '..', 'pages') function getRoute (loaderContext) { - const pagesDir = resolve(loaderContext.options.context, 'pages') + const config = getConfig(loaderContext.options.context) + const pagesDirectory = config.pagesDirectory + const pagesDir = resolve(loaderContext.options.context, pagesDirectory) const { resourcePath } = loaderContext const dir = [pagesDir, nextPagesDir] .find((d) => resourcePath.indexOf(d) === 0) diff --git a/server/build/plugins/json-pages-plugin.js b/server/build/plugins/json-pages-plugin.js index 06e34851b5f4da..b7da1ffea95014 100644 --- a/server/build/plugins/json-pages-plugin.js +++ b/server/build/plugins/json-pages-plugin.js @@ -1,9 +1,18 @@ +import getConfig from '../../config' + export default class JsonPagesPlugin { + constructor (dir) { + this.config = getConfig(dir) + } + apply (compiler) { compiler.plugin('after-compile', (compilation, callback) => { + const regex = new RegExp(`^bundles/${this.config.pagesDirectory}.*.js$`) const pages = Object .keys(compilation.assets) - .filter((filename) => /^bundles[/\\]pages.*\.js$/.test(filename)) + .filter((filename) => { + return filename.match(regex) + }) pages.forEach((pageName) => { const page = compilation.assets[pageName] diff --git a/server/build/plugins/watch-pages-plugin.js b/server/build/plugins/watch-pages-plugin.js index 7cf064d43c9591..e10cc5d4063f9a 100644 --- a/server/build/plugins/watch-pages-plugin.js +++ b/server/build/plugins/watch-pages-plugin.js @@ -1,8 +1,9 @@ -import { resolve, join } from 'path' +import { join } from 'path' +import getConfig from '../../config' export default class WatchPagesPlugin { constructor (dir) { - this.dir = resolve(dir, 'pages') + this.config = getConfig(dir) } apply (compiler) { @@ -10,7 +11,7 @@ export default class WatchPagesPlugin { compilation.plugin('optimize-assets', (assets, callback) => { // transpile pages/_document.js and descendants, // but don't need the bundle file - delete assets[join('bundles', 'pages', '_document.js')] + delete assets[join('bundles', this.config.pagesDirectory, '_document.js')] callback() }) }) @@ -19,10 +20,9 @@ export default class WatchPagesPlugin { // watch the pages directory compilation.contextDependencies = [ ...compilation.contextDependencies, - this.dir + this.config.pagesDirectory ] callback() }) } } - diff --git a/server/build/webpack.js b/server/build/webpack.js index 662238254db7db..700878ccd627ce 100644 --- a/server/build/webpack.js +++ b/server/build/webpack.js @@ -20,9 +20,6 @@ const defaultPages = [ ] const nextPagesDir = join(__dirname, '..', '..', 'pages') const nextNodeModulesDir = join(__dirname, '..', '..', '..', 'node_modules') -const interpolateNames = new Map(defaultPages.map((p) => { - return [join(nextPagesDir, p), `dist/pages/${p}`] -})) const relativeResolve = rootModuleRelativePath(require) @@ -33,19 +30,22 @@ export default async function createCompiler (dir, { dev = false, quiet = false, ? [join(__dirname, '..', '..', 'client/webpack-hot-middleware-client')] : [] const mainJS = dev ? require.resolve('../../client/next-dev') : require.resolve('../../client/next') + const interpolateNames = new Map(defaultPages.map((p) => { + return [join(nextPagesDir, p), `dist/${config.pagesDirectory}/${p}`] + })) let minChunks const entry = async () => { const entries = { 'main.js': mainJS } - const pages = await glob('pages/**/*.js', { cwd: dir }) + const pages = await glob(`${config.pagesDirectory}/**/*.js`, { cwd: dir }) for (const p of pages) { entries[join('bundles', p)] = [...defaultEntries, `./${p}?entry`] } for (const p of defaultPages) { - const entryName = join('bundles', 'pages', p) + const entryName = join('bundles', config.pagesDirectory, p) if (!entries[entryName]) { entries[entryName] = [...defaultEntries, join(nextPagesDir, p) + '?entry'] } @@ -81,7 +81,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false, return count >= minChunks } }), - new JsonPagesPlugin(), + new JsonPagesPlugin(dir), new CaseSensitivePathPlugin() ] @@ -139,7 +139,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false, test: /\.js(\?[^?]*)?$/, loader: 'hot-self-accept-loader', include: [ - join(dir, 'pages'), + join(dir, config.pagesDirectory), nextPagesDir ] }, { diff --git a/server/config.js b/server/config.js index 0c14009e40a186..c8d9acf0e6fbbb 100644 --- a/server/config.js +++ b/server/config.js @@ -5,7 +5,8 @@ const cache = new Map() const defaultConfig = { webpack: null, - poweredByHeader: true + poweredByHeader: true, + pagesDirectory: 'pages' } export default function getConfig (dir) { diff --git a/server/hot-reloader.js b/server/hot-reloader.js index 37eeecbd4cc06c..96d553d8411f02 100644 --- a/server/hot-reloader.js +++ b/server/hot-reloader.js @@ -5,6 +5,7 @@ import isWindowsBash from 'is-windows-bash' import webpack from './build/webpack' import clean from './build/clean' import readPage from './read-page' +import getConfig from './config' export default class HotReloader { constructor (dir, { quiet } = {}) { @@ -20,6 +21,7 @@ export default class HotReloader { this.prevChunkNames = null this.prevFailedChunkNames = null this.prevChunkHashes = null + this.config = getConfig(dir) } async run (req, res) { @@ -96,7 +98,7 @@ export default class HotReloader { // and to update error content const failed = failedChunkNames - const rootDir = join('bundles', 'pages') + const rootDir = join('bundles', this.config.pagesDirectory) for (const n of new Set([...added, ...removed, ...failed, ...succeeded])) { const route = toRoute(relative(rootDir, n)) diff --git a/server/index.js b/server/index.js index a11c5046091a1f..08b8775c2da1d8 100644 --- a/server/index.js +++ b/server/index.js @@ -98,7 +98,7 @@ export default class Server { await this.serveStatic(req, res, p) }, - '/_next/:buildId/pages/:path*': async (req, res, params) => { + [`/_next/:buildId/${this.config.pagesDirectory}/:path*`]: async (req, res, params) => { if (!this.handleBuildId(params.buildId, res)) { res.setHeader('Content-Type', 'application/json') res.end(JSON.stringify({ buildIdMismatch: true })) @@ -303,7 +303,7 @@ export default class Server { const errors = this.hotReloader.getCompilationErrors() if (!errors.size) return - const id = join(this.dir, '.next', 'bundles', 'pages', page) + const id = join(this.dir, '.next', 'bundles', this.config.pagesDirectory, page) const p = resolveFromList(id, errors.keys()) if (p) return errors.get(p)[0] } diff --git a/server/render.js b/server/render.js index 0be806fb2b1340..dfd5f67a78cdb9 100644 --- a/server/render.js +++ b/server/render.js @@ -2,6 +2,7 @@ import { join } from 'path' import { createElement } from 'react' import { renderToString, renderToStaticMarkup } from 'react-dom/server' import send from 'send' +import getConfig from './config' import requireModule from './require' import resolvePath from './resolve' import readPage from './read-page' @@ -36,10 +37,14 @@ async function doRender (req, res, pathname, query, { dev = false, staticMarkup = false } = {}) { + const config = getConfig(dir) + const pagesDirectory = config.pagesDirectory + page = page || pathname + let [Component, Document] = await Promise.all([ - requireModule(join(dir, '.next', 'dist', 'pages', page)), - requireModule(join(dir, '.next', 'dist', 'pages', '_document')) + requireModule(join(dir, '.next', 'dist', pagesDirectory, page)), + requireModule(join(dir, '.next', 'dist', pagesDirectory, '_document')) ]) Component = Component.default || Component Document = Document.default || Document @@ -51,8 +56,8 @@ async function doRender (req, res, pathname, query, { errorComponent ] = await Promise.all([ loadGetInitialProps(Component, ctx), - readPage(join(dir, '.next', 'bundles', 'pages', page)), - readPage(join(dir, '.next', 'bundles', 'pages', '_error')) + readPage(join(dir, '.next', 'bundles', pagesDirectory, page)), + readPage(join(dir, '.next', 'bundles', pagesDirectory, '_error')) ]) // the response might be finshed on the getinitialprops call @@ -90,6 +95,7 @@ async function doRender (req, res, pathname, query, { pathname, query, buildId, + pagesDirectory, err: (err && dev) ? errorToJSON(err) : null }, dev, @@ -101,12 +107,16 @@ async function doRender (req, res, pathname, query, { } export async function renderJSON (req, res, page, { dir = process.cwd() } = {}) { - const pagePath = await resolvePath(join(dir, '.next', 'bundles', 'pages', page)) + const config = getConfig(dir) + const pagesDirectory = config.pagesDirectory + const pagePath = await resolvePath(join(dir, '.next', 'bundles', pagesDirectory, page)) return serveStatic(req, res, pagePath) } export async function renderErrorJSON (err, req, res, { dir = process.cwd(), dev = false } = {}) { - const component = await readPage(join(dir, '.next', 'bundles', 'pages', '_error')) + const config = getConfig(dir) + const pagesDirectory = config.pagesDirectory + const component = await readPage(join(dir, '.next', 'bundles', pagesDirectory, '_error')) sendJSON(res, { component,