mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Exploration of different config + expose webpack config (#222)
* 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
This commit is contained in:
parent
b62a0e8f55
commit
5ab7463b93
62
README.md
62
README.md
|
@ -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>
|
||||
|
@ -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>
|
||||
|
|
30
bin/next
30
bin/next
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { join } from 'path'
|
||||
import { spawn } from 'cross-spawn'
|
||||
import { watchFile } from 'fs'
|
||||
|
||||
const defaultCommand = 'dev'
|
||||
const commands = new Set([
|
||||
|
@ -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()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -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: {
|
||||
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
|
@ -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 = {}
|
||||
|
||||
const userHasConfig = existsSync(path)
|
||||
if (userHasConfig) {
|
||||
const userConfigModule = require(path)
|
||||
userConfig = userConfigModule.default || userConfigModule
|
||||
}
|
||||
|
||||
// no try-cache, it must be a valid json
|
||||
const config = JSON.parse(data).next || {}
|
||||
|
||||
return Object.assign({}, defaultConfig, config)
|
||||
return Object.assign({}, defaultConfig, userConfig)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue