rsnext/packages/next/build/webpack/loaders/next-babel-loader.js
JJ Kasper 0ca8087565
Add prerender PageConfig option (#7699)
* Add prerender PageConfig option

* Update PageConfig type

* Add inlining of data when pre-render is set and add tests

* Update types import

* Add check for props

* Rename prerender to experimentalPrerender for now
2019-07-01 14:13:52 -07:00

158 lines
4.7 KiB
JavaScript

import hash from 'string-hash'
import { join, basename } from 'path'
import babelLoader from 'babel-loader'
// increment 'c' to invalidate cache
const cacheKey = 'babel-cache-' + 'c' + '-'
module.exports = babelLoader.custom(babel => {
const presetItem = babel.createConfigItem(require('../../babel/preset'), {
type: 'preset'
})
const applyCommonJs = babel.createConfigItem(
require('../../babel/plugins/commonjs'),
{ type: 'plugin' }
)
const commonJsItem = babel.createConfigItem(
require('@babel/plugin-transform-modules-commonjs'),
{ type: 'plugin' }
)
const configs = new Set()
return {
customOptions (opts) {
const custom = {
isServer: opts.isServer,
asyncToPromises: opts.asyncToPromises
}
const filename = join(opts.cwd, 'noop.js')
const loader = Object.assign(
opts.cache
? {
cacheCompression: false,
cacheDirectory: join(opts.distDir, 'cache', 'next-babel-loader'),
cacheIdentifier:
cacheKey +
JSON.stringify(
babel.loadPartialConfig({
filename,
cwd: opts.cwd,
sourceFileName: filename
}).options
)
}
: {
cacheDirectory: false
},
opts
)
delete loader.isServer
delete loader.asyncToPromises
delete loader.cache
delete loader.distDir
return { loader, custom }
},
config (
cfg,
{
source,
customOptions: { isServer, asyncToPromises }
}
) {
const filename = this.resourcePath
const options = Object.assign({}, cfg.options)
if (cfg.hasFilesystemConfig()) {
for (const file of [cfg.babelrc, cfg.config]) {
// We only log for client compilation otherwise there will be double output
if (file && !isServer && !configs.has(file)) {
configs.add(file)
console.log(`> Using external babel configuration`)
console.log(`> Location: "${file}"`)
}
}
} else {
// Add our default preset if the no "babelrc" found.
options.presets = [...options.presets, presetItem]
}
if (!isServer) {
const pageConfigPlugin = babel.createConfigItem(
[require('../../babel/plugins/next-page-config')],
{ type: 'plugin' }
)
options.plugins = options.plugins || []
options.plugins.push(pageConfigPlugin)
}
if (isServer && source.indexOf('next/data') !== -1) {
const nextDataPlugin = babel.createConfigItem(
[
require('../../babel/plugins/next-data'),
{ key: basename(filename) + '-' + hash(filename) }
],
{ type: 'plugin' }
)
options.plugins = options.plugins || []
options.plugins.push(nextDataPlugin)
}
if (asyncToPromises) {
const asyncToPromisesPlugin = babel.createConfigItem(
[
'babel-plugin-transform-async-to-promises',
{
inlineHelpers: true
}
],
{ type: 'plugin' }
)
options.plugins = options.plugins || []
options.plugins.push(asyncToPromisesPlugin)
const regeneratorPlugin = options.plugins.find(plugin => {
return plugin[0] === require('@babel/plugin-transform-runtime')
})
if (regeneratorPlugin) {
regeneratorPlugin[1].regenerator = false
}
const babelPresetEnv = (options.presets || []).find((preset = []) => {
return preset[0] === require('@babel/preset-env').default
})
if (babelPresetEnv) {
babelPresetEnv[1].exclude = (options.presets[0][1].exclude || [])
.concat([
'transform-typeof-symbol',
'transform-regenerator',
'transform-async-to-generator'
])
.filter('transform-typeof-symbol')
}
}
// If the file has `module.exports` we have to transpile commonjs because Babel adds `import` statements
// That break webpack, since webpack doesn't support combining commonjs and esmodules
if (source.indexOf('module.exports') !== -1) {
options.plugins = options.plugins || []
options.plugins.push(applyCommonJs)
}
// As next-server/lib has stateful modules we have to transpile commonjs
options.overrides = [
...(options.overrides || []),
{
test: [
/next-server[\\/]dist[\\/]lib/,
/next[\\/]dist[\\/]client/,
/next[\\/]dist[\\/]pages/
],
plugins: [commonJsItem]
}
]
return options
}
}
})