Skip to content

Commit 1719738

Browse files
arunodarauchg
authored andcommittedDec 22, 2016
Allow to customize our babel configuration (#466)
* Add a way to customize babel configurations. * Add babel configuration docs to README.
1 parent 9ac79ed commit 1719738

File tree

7 files changed

+155
-15
lines changed

7 files changed

+155
-15
lines changed
 

‎README.md

+34-4
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ app.prepare().then(() => {
310310
```
311311

312312
The `next` API is as follows:
313-
- `next(path: string, opts: object)` - `path` is
313+
- `next(path: string, opts: object)` - `path` is
314314
- `next(opts: object)`
315315

316316
Supported options:
@@ -396,10 +396,40 @@ In order to extend our usage of `webpack`, you can define a function that extend
396396
The following example shows how you can use [`react-svg-loader`](https://github.com/boopathi/react-svg-loader) to easily import any `.svg` file as a React component, without modification.
397397

398398
```js
399+
// This file is not going through babel transformation.
400+
// So, we write it in vanilla JS
401+
// (But you could use ES2015 features supported by your Node.js version)
402+
403+
module.exports = {
404+
webpack: (config, { dev }) => {
405+
config.module.rules.push({ test: /\.svg$/, loader: 'babel!react-svg' })
406+
407+
// Important: return the modified config
408+
return config
409+
}
410+
}
411+
```
412+
413+
### Customizing babel config
414+
415+
In order to extend our usage of `babel`, you can define a function that extends its config via `next.config.js`.
416+
417+
The following example config shows you how to use `babel-preset-stage-0` with your app.
418+
419+
```js
420+
// This file is not going through babel transformation.
421+
// So, we write it in vanilla JS
422+
// (But you could use ES2015 features supported by your Node.js version)
423+
399424
module.exports = {
400-
webpack: (cfg, { dev }) => {
401-
cfg.module.rules.push({ test: /\.svg$/, loader: 'babel!react-svg' })
402-
return cfg
425+
// config is the set of options we pass to our babel-loaders's query option
426+
babel: function (config, { dev }) {
427+
// Add the stage-0 preset.
428+
// Make sure to use 'require.resolve' otherwise we won't be able to find it.
429+
config.presets.push(require.resolve('babel-preset-stage-0'))
430+
431+
// Important: return the modified config
432+
return config
403433
}
404434
}
405435
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Example app using custom babel config
2+
3+
This example features:
4+
5+
* An app using proposed [do expressions](https://babeljs.io/docs/plugins/transform-do-expressions/).
6+
* It uses babel-preset-stage-0, which allows us to use above JavaScript feature.
7+
8+
## How to run it
9+
10+
```sh
11+
npm install
12+
npm run dev
13+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This file is not going through babel transformation.
2+
// So, we write it in vanilla JS
3+
// (But you could use ES2015 features supported by your Node.js version)
4+
5+
module.exports = {
6+
// config is the set of options we pass to our babel-loaders's query option
7+
babel: function (config) {
8+
// Add the stage-0 preset.
9+
// Make sure to use 'require.resolve' otherwise we won't be able to find it.
10+
config.presets.push(require.resolve('babel-preset-stage-0'))
11+
12+
// Important: return the modified config
13+
return config
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "with-custom-babel-config",
3+
"version": "1.0.0",
4+
"description": "This example features:",
5+
"main": "index.js",
6+
"scripts": {
7+
"dev": "next",
8+
"build": "next build",
9+
"start": "next start"
10+
},
11+
"dependencies": {
12+
"next": "^2.0.0-beta"
13+
},
14+
"author": "",
15+
"license": "ISC",
16+
"devDependencies": {
17+
"babel-preset-stage-0": "^6.16.0"
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
3+
export default class MyLuckNo extends React.Component {
4+
constructor (...args) {
5+
super(...args)
6+
this.state = { randomNo: null }
7+
}
8+
9+
componentDidMount () {
10+
this.recalculate()
11+
}
12+
13+
recalculate () {
14+
this.setState({
15+
randomNo: Math.ceil(Math.random() * 100)
16+
})
17+
}
18+
19+
render () {
20+
const { randomNo } = this.state
21+
22+
if (randomNo === null) {
23+
return (<p>Please wait..</p>)
24+
}
25+
26+
// This is an experimental JavaScript feature where we can get with
27+
// using babel-preset-stage-0
28+
const message = do {
29+
if (randomNo < 30) {
30+
'Do not give up. Try again.'
31+
} else if (randomNo < 60) {
32+
'You are a lucky guy'
33+
} else {
34+
'You are soooo lucky!'
35+
}
36+
}
37+
38+
return (
39+
<div>
40+
<h3>Your Lucky number is: "{randomNo}"</h3>
41+
<p>{message}</p>
42+
<button onClick={() => this.recalculate()}>Try Again</button>
43+
</div>
44+
)
45+
}
46+
}

‎server/build/babel/index.js

+11-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { readFile, writeFile } from 'mz/fs'
33
import { transform } from 'babel-core'
44
import chokidar from 'chokidar'
55
import mkdirp from 'mkdirp-then'
6+
import getConfig from '../../config'
67

78
export default babel
89

910
async function babel (dir, { dev = false } = {}) {
1011
dir = resolve(dir)
12+
const config = getConfig('../')
1113

1214
let src
1315
try {
@@ -20,11 +22,18 @@ async function babel (dir, { dev = false } = {}) {
2022
}
2123
}
2224

23-
const { code } = transform(src, {
25+
let babelOptions = {
2426
babelrc: false,
2527
sourceMaps: dev ? 'inline' : false,
2628
presets: [require.resolve('./preset')]
27-
})
29+
}
30+
31+
if (config.babel) {
32+
console.log('> Using "babel" config function defined in next.config.js.')
33+
babelOptions = await config.babel(babelOptions, { dev })
34+
}
35+
36+
const { code } = transform(src, babelOptions)
2837

2938
const file = join(dir, '.next', 'dist', 'pages', '_document.js')
3039
await mkdirp(dirname(file))

‎server/build/webpack.js

+17-9
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import getConfig from '../config'
1313

1414
export default async function createCompiler (dir, { dev = false, quiet = false } = {}) {
1515
dir = resolve(dir)
16+
const config = getConfig(dir)
1617

1718
const pages = await glob('pages/**/*.js', {
1819
cwd: dir,
@@ -83,6 +84,19 @@ export default async function createCompiler (dir, { dev = false, quiet = false
8384
)
8485
}
8586

87+
let mainBabelOptions = {
88+
babelrc: false,
89+
sourceMaps: dev ? 'both' : false,
90+
presets: [
91+
require.resolve('./babel/preset')
92+
]
93+
}
94+
95+
if (config.babel) {
96+
console.log('> Using "babel" config function defined in next.config.js.')
97+
mainBabelOptions = await config.babel(mainBabelOptions, { dev })
98+
}
99+
86100
const loaders = (dev ? [{
87101
test: /\.js(\?[^?]*)?$/,
88102
loader: 'hot-self-accept-loader',
@@ -133,13 +147,7 @@ export default async function createCompiler (dir, { dev = false, quiet = false
133147
exclude (str) {
134148
return /node_modules/.test(str) && str.indexOf(nextPagesDir) !== 0
135149
},
136-
query: {
137-
babelrc: false,
138-
sourceMaps: dev ? 'both' : false,
139-
presets: [
140-
require.resolve('./babel/preset')
141-
]
142-
}
150+
query: mainBabelOptions
143151
}])
144152

145153
const interpolateNames = new Map([
@@ -188,9 +196,9 @@ export default async function createCompiler (dir, { dev = false, quiet = false
188196
return interpolateNames.get(this.resourcePath) || url
189197
}
190198
}
191-
const config = getConfig(dir)
199+
192200
if (config.webpack) {
193-
console.log('> Using Webpack config function defined in next.config.js.')
201+
console.log('> Using "webpack" config function defined in next.config.js.')
194202
webpackConfig = await config.webpack(webpackConfig, { dev })
195203
}
196204
return webpack(webpackConfig)

0 commit comments

Comments
 (0)