Skip to content

Commit

Permalink
Exploration of different config + expose webpack config (#222)
Browse files Browse the repository at this point in the history
* Use next.config.js instead of package.json

* Remove irrelevant comment

* Integrate with custom webpack config

* Include hotReload option

* Remove async/await for getConfig

* Read package.json, show warning when webpack in config is defined

* Prepend warning message with WARNING

* Update log statements

* Documentation

* Restart server on change of config

* Fix process handling and cases where there is no config

* Also restart server when config file gets deleted

* Changed second parameter of webpack to config

* Support for returning Promise

* Update documentation, fix bug with webpack config

* Remove package.json, cdn and hotReload from config
  • Loading branch information
CompuIves authored and rauchg committed Dec 17, 2016
1 parent b62a0e8 commit 5ab7463
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 26 deletions.
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,66 @@ Then run `now` and enjoy!

Note: we recommend putting `.next` in `.npmignore` or `.gitignore`. Otherwise, use `files` or `now.files` to opt-into a whitelist of files you want to deploy (and obviously exclude `.next`)

## Configuration

While Next.js aims to work without any configuration, sometimes there is a need to add custom behaviour.
You can define custom configuration in a file called `next.config.js` in the project root directory.
An example of a configuration looks like this:

```javascript
// next.config.js
module.exports = {
cdn: true
}
```

### Customizing webpack config

Sometimes the user needs to have custom configuration for webpack to add a specific behaviour in the build process.
An example of this is using `eslint-loader` to lint the files before compiling. This can be done by defining
`webpack` in the config.

```javascript
module.exports = {
webpack: (webpackConfig, { dev }) => {
webpackConfig.module.preLoaders.push({ test: /\.js$/, loader: 'eslint-loader' })
return webpackConfig
}
}
```

As you can see you need to provide a function which has two parameters `webpackConfig`, which is the config used by Next.js, and `options`, which contains
`dev` (`true` if dev environment). The config you return is the config used by Next.js.
You can also return a `Promise` which will be resolved first.

_NOTE: Use this option with care, because you can potentially break the existing webpack build configuration by using this option._

These are some more examples:

```javascript
const I18nPlugin = require('i18n-webpack-plugin');

module.exports = {
webpack: (webpackConfig, { dev }) => {
// Read image files:
webpackConfig.module.loaders.push({
test: /\.png$/,
loader: 'file'
})

// Adding a plugin
webpackConfig.plugins.push(new I18nPlugin())

// Or adding an alias
// Create webpackConfig.resolve.alias if it doesn't exist yet:
webpackConfig.resolve.alias = webpackConfig.resolve.alias || {}
webpackConfig.resolve.alias.src = './src'

return webpackConfig
}
}
```

## FAQ

<details>
Expand Down Expand Up @@ -423,7 +483,7 @@ For this reason we want to promote a situation where users can share the cache f

We are committed to providing a great uptime and levels of security for our CDN. Even so, we also **automatically fall back** if the CDN script fails to load [with a simple trick](http://www.hanselman.com/blog/CDNsFailButYourScriptsDontHaveToFallbackFromCDNToLocalJQuery.aspx).

To turn the CDN off, just set `{ “next”: { cdn: false } }` in `package.json`.
To turn the CDN off, just set `module.exports = { cdn: false }` in `next.config.js`.
</details>

<details>
Expand Down
30 changes: 24 additions & 6 deletions bin/next
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { join } from 'path'
import { spawn } from 'cross-spawn'
import { watchFile } from 'fs'

const defaultCommand = 'dev'
const commands = new Set([
Expand All @@ -23,9 +24,26 @@ if (commands.has(cmd)) {

const bin = join(__dirname, 'next-' + cmd)

const proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] })
proc.on('close', (code) => process.exit(code))
proc.on('error', (err) => {
console.error(err)
process.exit(1)
})
const startProcess = () => {
const proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] })
proc.on('close', (code) => process.exit(code))
proc.on('error', (err) => {
console.error(err)
process.exit(1)
})
return proc
}

let proc = startProcess()

if (cmd === 'dev') {
watchFile(join(process.cwd(), 'next.config.js'), (cur, prev) => {
if (cur.size > 0 || prev.size > 0) {
console.log('\n> Found a change in next.config.js, restarting the server...')
// Don't listen to 'close' now since otherwise parent gets killed by listener
proc.removeAllListeners('close')
proc.kill()
proc = startProcess()
}
})
}
11 changes: 9 additions & 2 deletions server/build/webpack.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import WatchPagesPlugin from './plugins/watch-pages-plugin'
import WatchRemoveEventPlugin from './plugins/watch-remove-event-plugin'
import DynamicEntryPlugin from './plugins/dynamic-entry-plugin'
import DetachPlugin from './plugins/detach-plugin'
import getConfig from '../config'

export default async function createCompiler (dir, { dev = false } = {}) {
dir = resolve(dir)
Expand Down Expand Up @@ -166,7 +167,7 @@ export default async function createCompiler (dir, { dev = false } = {}) {
[errorDebugPath, 'dist/pages/_error-debug.js']
])

return webpack({
let webpackConfig = {
context: dir,
entry,
output: {
Expand Down Expand Up @@ -206,5 +207,11 @@ export default async function createCompiler (dir, { dev = false } = {}) {
customInterpolateName: function (url, name, opts) {
return interpolateNames.get(this.resourcePath) || url
}
})
}
const config = getConfig(dir)
if (config.webpack) {
console.log('> Using Webpack config function defined in next.config.js.')
webpackConfig = await config.webpack(webpackConfig, { dev })
}
return webpack(webpackConfig)
}
30 changes: 13 additions & 17 deletions server/config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { join } from 'path'
import { readFile } from 'mz/fs'
import { existsSync } from 'fs'

const cache = new Map()

const defaultConfig = {}
const defaultConfig = {
webpack: null
}

export default function getConfig (dir) {
if (!cache.has(dir)) {
Expand All @@ -12,22 +14,16 @@ export default function getConfig (dir) {
return cache.get(dir)
}

async function loadConfig (dir) {
const path = join(dir, 'package.json')
function loadConfig (dir) {
const path = join(dir, 'next.config.js')

let data
try {
data = await readFile(path, 'utf8')
} catch (err) {
if (err.code === 'ENOENT') {
data = '{}'
} else {
throw err
}
}
let userConfig = {}

// no try-cache, it must be a valid json
const config = JSON.parse(data).next || {}
const userHasConfig = existsSync(path)
if (userHasConfig) {
const userConfigModule = require(path)
userConfig = userConfigModule.default || userConfigModule
}

return Object.assign({}, defaultConfig, config)
return Object.assign({}, defaultConfig, userConfig)
}

0 comments on commit 5ab7463

Please sign in to comment.