1
0
Fork 0
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:
Tim Neutkens 2018-02-23 14:42:06 +01:00 committed by Arunoda Susiripala
parent 50fcefdf97
commit 5017f91d23
11 changed files with 101 additions and 7 deletions

1
constants.js Normal file
View file

@ -0,0 +1 @@
module.exports = require('./dist/lib/constants')

4
lib/constants.js Normal file
View 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'

View file

@ -19,7 +19,8 @@
"prefetch.js",
"router.js",
"asset.js",
"error.js"
"error.js",
"constants.js"
],
"bin": {
"next": "./dist/bin/next"

View file

@ -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
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.

View file

@ -3,11 +3,12 @@ import fs from 'mz/fs'
import uuid from 'uuid'
import webpack from 'webpack'
import getConfig from '../config'
import {PHASE_PRODUCTION_BUILD} from '../../lib/constants'
import getBaseWebpackConfig from './webpack'
import md5File from 'md5-file/promise'
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()
try {

View file

@ -13,14 +13,14 @@ const defaultConfig = {
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)) {
cache.set(dir, loadConfig(dir, customConfig))
cache.set(dir, loadConfig(phase, dir, customConfig))
}
return cache.get(dir)
}
function loadConfig (dir, customConfig) {
export function loadConfig (phase, dir, customConfig) {
if (customConfig && typeof customConfig === 'object') {
customConfig.configOrigin = 'server'
return withDefaults(customConfig)
@ -34,6 +34,9 @@ function loadConfig (dir, customConfig) {
if (path && path.length) {
const userConfigModule = require(path)
userConfig = userConfigModule.default || userConfigModule
if (typeof userConfigModule === 'function') {
userConfig = userConfigModule(phase, {defaultConfig})
}
userConfig.configOrigin = 'next.config.js'
}

View file

@ -5,6 +5,7 @@ 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 { renderToHTML } from './render'
import { getAvailableChunks } from './utils'
import { printAndExit } from '../lib/utils'
@ -12,7 +13,7 @@ import { setAssetPrefix } from '../lib/asset'
export default async function (dir, options, configuration) {
dir = resolve(dir)
const config = configuration || getConfig(dir)
const config = configuration || getConfig(PHASE_EXPORT, dir)
const nextDir = join(dir, config.distDir)
log(` using build directory: ${nextDir}`)

View file

@ -16,6 +16,7 @@ import {
import Router from './router'
import { getAvailableChunks, isInternalUrl } from './utils'
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
import pkg from '../../package'
import * as asset from '../lib/asset'
@ -33,7 +34,8 @@ export default class Server {
this.quiet = quiet
this.router = new Router()
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.hotReloader = dev ? this.getHotReloader(this.dir, { quiet, config: this.config }) : null

View file

@ -0,0 +1,7 @@
module.exports = (phase, {defaultConfig}) => {
return {
phase,
defaultConfig,
customConfig: true
}
}

View file

@ -0,0 +1,3 @@
module.exports = {
customConfig: true
}

View 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)
})
})