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",
|
||||
"router.js",
|
||||
"asset.js",
|
||||
"error.js"
|
||||
"error.js",
|
||||
"constants.js"
|
||||
],
|
||||
"bin": {
|
||||
"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
|
||||
|
||||
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 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 {
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
||||
|
|
|
@ -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}`)
|
||||
|
|
|
@ -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
|
||||
|
|
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