mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Allow next.config.js to export a function (#3867)
* Allow next.config.js to export a function * Expose phases to the configuration function * Use same value as variable name * Add next/constants * Add documentation for config function / phases * Add constants.js to npm bundle
This commit is contained in:
parent
50fcefdf97
commit
5017f91d23
1
constants.js
Normal file
1
constants.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
module.exports = require('./dist/lib/constants')
|
4
lib/constants.js
Normal file
4
lib/constants.js
Normal file
|
@ -0,0 +1,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'
|
|
@ -19,7 +19,8 @@
|
||||||
"prefetch.js",
|
"prefetch.js",
|
||||||
"router.js",
|
"router.js",
|
||||||
"asset.js",
|
"asset.js",
|
||||||
"error.js"
|
"error.js",
|
||||||
|
"constants.js"
|
||||||
],
|
],
|
||||||
"bin": {
|
"bin": {
|
||||||
"next": "./dist/bin/next"
|
"next": "./dist/bin/next"
|
||||||
|
|
30
readme.md
30
readme.md
|
@ -997,6 +997,36 @@ module.exports = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Or use a function:
|
||||||
|
|
||||||
|
```js
|
||||||
|
module.exports = (phase, {defaultConfig}){
|
||||||
|
//
|
||||||
|
// https://github.com/zeit/
|
||||||
|
return {
|
||||||
|
/* config options here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`phase` is the current context in which the configuration is loaded. You can see all phases here: [contants](./lib/constants.js)
|
||||||
|
Phases can be imported from `next/constants`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
const {PHASE_DEVELOPMENT_SERVER} = require('next/constants')
|
||||||
|
module.exports = (phase, {defaultConfig}){
|
||||||
|
if(phase === PHASE_DEVELOPMENT_SERVER) {
|
||||||
|
return {
|
||||||
|
/* development only config options here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
/* config options for all phases except development here */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### Setting a custom build directory
|
#### Setting a custom build directory
|
||||||
|
|
||||||
You can specify a name to use for a custom build directory. For example, the following config will create a `build` folder instead of a `.next` folder. If no configuration is specified then next will create a `.next` folder.
|
You can specify a name to use for a custom build directory. For example, the following config will create a `build` folder instead of a `.next` folder. If no configuration is specified then next will create a `.next` folder.
|
||||||
|
|
|
@ -3,11 +3,12 @@ import fs from 'mz/fs'
|
||||||
import uuid from 'uuid'
|
import uuid from 'uuid'
|
||||||
import webpack from 'webpack'
|
import webpack from 'webpack'
|
||||||
import getConfig from '../config'
|
import getConfig from '../config'
|
||||||
|
import {PHASE_PRODUCTION_BUILD} from '../../lib/constants'
|
||||||
import getBaseWebpackConfig from './webpack'
|
import getBaseWebpackConfig from './webpack'
|
||||||
import md5File from 'md5-file/promise'
|
import md5File from 'md5-file/promise'
|
||||||
|
|
||||||
export default async function build (dir, conf = null) {
|
export default async function build (dir, conf = null) {
|
||||||
const config = getConfig(dir, conf)
|
const config = getConfig(PHASE_PRODUCTION_BUILD, dir, conf)
|
||||||
const buildId = uuid.v4()
|
const buildId = uuid.v4()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -13,14 +13,14 @@ const defaultConfig = {
|
||||||
pageExtensions: ['jsx', 'js'] // jsx before js because otherwise regex matching will match js first
|
pageExtensions: ['jsx', 'js'] // jsx before js because otherwise regex matching will match js first
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getConfig (dir, customConfig) {
|
export default function getConfig (phase, dir, customConfig) {
|
||||||
if (!cache.has(dir)) {
|
if (!cache.has(dir)) {
|
||||||
cache.set(dir, loadConfig(dir, customConfig))
|
cache.set(dir, loadConfig(phase, dir, customConfig))
|
||||||
}
|
}
|
||||||
return cache.get(dir)
|
return cache.get(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadConfig (dir, customConfig) {
|
export function loadConfig (phase, dir, customConfig) {
|
||||||
if (customConfig && typeof customConfig === 'object') {
|
if (customConfig && typeof customConfig === 'object') {
|
||||||
customConfig.configOrigin = 'server'
|
customConfig.configOrigin = 'server'
|
||||||
return withDefaults(customConfig)
|
return withDefaults(customConfig)
|
||||||
|
@ -34,6 +34,9 @@ function loadConfig (dir, customConfig) {
|
||||||
if (path && path.length) {
|
if (path && path.length) {
|
||||||
const userConfigModule = require(path)
|
const userConfigModule = require(path)
|
||||||
userConfig = userConfigModule.default || userConfigModule
|
userConfig = userConfigModule.default || userConfigModule
|
||||||
|
if (typeof userConfigModule === 'function') {
|
||||||
|
userConfig = userConfigModule(phase, {defaultConfig})
|
||||||
|
}
|
||||||
userConfig.configOrigin = 'next.config.js'
|
userConfig.configOrigin = 'next.config.js'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import walk from 'walk'
|
||||||
import { extname, resolve, join, dirname, sep } from 'path'
|
import { extname, resolve, join, dirname, sep } from 'path'
|
||||||
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
import { existsSync, readFileSync, writeFileSync } from 'fs'
|
||||||
import getConfig from './config'
|
import getConfig from './config'
|
||||||
|
import {PHASE_EXPORT} from '../lib/constants'
|
||||||
import { renderToHTML } from './render'
|
import { renderToHTML } from './render'
|
||||||
import { getAvailableChunks } from './utils'
|
import { getAvailableChunks } from './utils'
|
||||||
import { printAndExit } from '../lib/utils'
|
import { printAndExit } from '../lib/utils'
|
||||||
|
@ -12,7 +13,7 @@ import { setAssetPrefix } from '../lib/asset'
|
||||||
|
|
||||||
export default async function (dir, options, configuration) {
|
export default async function (dir, options, configuration) {
|
||||||
dir = resolve(dir)
|
dir = resolve(dir)
|
||||||
const config = configuration || getConfig(dir)
|
const config = configuration || getConfig(PHASE_EXPORT, dir)
|
||||||
const nextDir = join(dir, config.distDir)
|
const nextDir = join(dir, config.distDir)
|
||||||
|
|
||||||
log(` using build directory: ${nextDir}`)
|
log(` using build directory: ${nextDir}`)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import Router from './router'
|
import Router from './router'
|
||||||
import { getAvailableChunks, isInternalUrl } from './utils'
|
import { getAvailableChunks, isInternalUrl } from './utils'
|
||||||
import getConfig from './config'
|
import getConfig from './config'
|
||||||
|
import {PHASE_PRODUCTION_SERVER, PHASE_DEVELOPMENT_SERVER} from '../lib/constants'
|
||||||
// We need to go up one more level since we are in the `dist` directory
|
// We need to go up one more level since we are in the `dist` directory
|
||||||
import pkg from '../../package'
|
import pkg from '../../package'
|
||||||
import * as asset from '../lib/asset'
|
import * as asset from '../lib/asset'
|
||||||
|
@ -33,7 +34,8 @@ export default class Server {
|
||||||
this.quiet = quiet
|
this.quiet = quiet
|
||||||
this.router = new Router()
|
this.router = new Router()
|
||||||
this.http = null
|
this.http = null
|
||||||
this.config = getConfig(this.dir, conf)
|
const phase = dev ? PHASE_DEVELOPMENT_SERVER : PHASE_PRODUCTION_SERVER
|
||||||
|
this.config = getConfig(phase, this.dir, conf)
|
||||||
this.dist = this.config.distDir
|
this.dist = this.config.distDir
|
||||||
|
|
||||||
this.hotReloader = dev ? this.getHotReloader(this.dir, { quiet, config: this.config }) : null
|
this.hotReloader = dev ? this.getHotReloader(this.dir, { quiet, config: this.config }) : null
|
||||||
|
|
7
test/isolated/_resolvedata/with-function/next.config.js
Normal file
7
test/isolated/_resolvedata/with-function/next.config.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module.exports = (phase, {defaultConfig}) => {
|
||||||
|
return {
|
||||||
|
phase,
|
||||||
|
defaultConfig,
|
||||||
|
customConfig: true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
customConfig: true
|
||||||
|
}
|
41
test/isolated/config.test.js
Normal file
41
test/isolated/config.test.js
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* global describe, it, expect */
|
||||||
|
|
||||||
|
import {join} from 'path'
|
||||||
|
import getConfig, {loadConfig} from '../../dist/server/config'
|
||||||
|
import {PHASE_DEVELOPMENT_SERVER} from '../../dist/lib/constants'
|
||||||
|
|
||||||
|
const pathToConfig = join(__dirname, '_resolvedata', 'without-function')
|
||||||
|
const pathToConfigFn = join(__dirname, '_resolvedata', 'with-function')
|
||||||
|
|
||||||
|
describe('config', () => {
|
||||||
|
it('Should get the configuration', () => {
|
||||||
|
const config = loadConfig(PHASE_DEVELOPMENT_SERVER, pathToConfig)
|
||||||
|
expect(config.customConfig).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should pass the phase correctly', () => {
|
||||||
|
const config = loadConfig(PHASE_DEVELOPMENT_SERVER, pathToConfigFn)
|
||||||
|
expect(config.phase).toBe(PHASE_DEVELOPMENT_SERVER)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should pass the defaultConfig correctly', () => {
|
||||||
|
const config = loadConfig(PHASE_DEVELOPMENT_SERVER, pathToConfigFn)
|
||||||
|
expect(config.defaultConfig).toBeDefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should pass the customConfig correctly', () => {
|
||||||
|
const config = loadConfig(PHASE_DEVELOPMENT_SERVER, null, {customConfig: true})
|
||||||
|
expect(config.customConfig).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should not pass the customConfig when it is null', () => {
|
||||||
|
const config = loadConfig(PHASE_DEVELOPMENT_SERVER, null, null)
|
||||||
|
expect(config.webpack).toBe(null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should cache on getConfig', () => {
|
||||||
|
const config = getConfig(PHASE_DEVELOPMENT_SERVER, pathToConfig)
|
||||||
|
const config2 = getConfig(PHASE_DEVELOPMENT_SERVER, pathToConfig, {extraConfig: true}) // won't add extraConfig because it's cached.
|
||||||
|
expect(config === config2).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue