Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test fixes for Babel mode #24312

Merged
merged 15 commits into from
Apr 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 82 additions & 17 deletions packages/next/build/babel/loader/get-config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { readFileSync } from 'fs'

import { createConfigItem, loadOptions } from 'next/dist/compiled/babel/core'
import loadConfig from 'next/dist/compiled/babel/core-lib-config'

import nextBabelPreset from '../preset'
import { NextBabelLoaderOptions, NextJsLoaderContext } from './types'
import { consumeIterator } from './util'

Expand Down Expand Up @@ -31,8 +32,10 @@ interface CharacteristicsGermaneToCaching {
isPageFile: boolean
isNextDist: boolean
hasModuleExports: boolean
fileExt: string
}

const fileExtensionRegex = /\.([a-z]+)$/
function getCacheCharacteristics(
loaderOptions: NextBabelLoaderOptions,
source: string,
Expand All @@ -42,12 +45,14 @@ function getCacheCharacteristics(
const isPageFile = filename.startsWith(pagesDir)
const isNextDist = nextDistPath.test(filename)
const hasModuleExports = source.indexOf('module.exports') !== -1
const fileExt = fileExtensionRegex.exec(filename)?.[1] || 'unknown'

return {
isServer,
isPageFile,
isNextDist,
hasModuleExports,
fileExt,
}
}

Expand Down Expand Up @@ -134,6 +139,46 @@ function getPlugins(
].filter(Boolean)
}

const isJsonFile = /\.(json|babelrc)$/
const isJsFile = /\.js$/

/**
* While this function does block execution while reading from disk, it
* should not introduce any issues. The function is only invoked when
* generating a fresh config, and only a small handful of configs should
* be generated during compilation.
*/
function getCustomBabelConfig(configFilePath: string) {
if (isJsonFile.exec(configFilePath)) {
const babelConfigRaw = readFileSync(configFilePath, 'utf8')
return JSON.parse(babelConfigRaw)
} else if (isJsFile.exec(configFilePath)) {
return require(configFilePath)
}
throw new Error(
'The Next Babel loader does not support MJS or CJS config files.'
)
}

function getCustomPresets(presets: any[], customConfig: any) {
presets = [...presets, ...customConfig?.presets]

const hasNextBabelPreset = (customConfig?.presets || [])
.filter((preset: any) => {
return (
preset === 'next/babel' ||
(Array.isArray(preset) && preset[0] === 'next/babel')
)
})
.reduce((memo: boolean, presetFound: boolean) => memo || presetFound, false)

if (!hasNextBabelPreset) {
presets.push('next/babel')
}

return presets
}

/**
* Generate a new, flat Babel config, ready to be handed to Babel-traverse.
* This config should have no unresolved overrides, presets, etc.
Expand All @@ -146,19 +191,28 @@ function getFreshConfig(
filename: string,
inputSourceMap?: object | null
) {
const {
let {
presets = [],
isServer,
pagesDir,
development,
hasReactRefresh,
hasJsxRuntime,
babelrc,
configFile,
} = loaderOptions
const nextPresetItem = createConfigItem(nextBabelPreset, { type: 'preset' })

let customPlugins = []
if (configFile) {
const customConfig = getCustomBabelConfig(configFile)
presets = getCustomPresets(presets, customConfig)
if (customConfig.plugins) {
customPlugins = customConfig.plugins
}
} else {
presets = [...presets, 'next/babel']
}

let options = {
babelrc,
babelrc: false,
cloneInputAst: false,
filename,
inputSourceMap: inputSourceMap || undefined,
Expand All @@ -167,17 +221,20 @@ function getFreshConfig(
// but allow users to override if they want.
sourceMaps:
loaderOptions.sourceMaps === undefined
? inputSourceMap
? this.sourceMap
: loaderOptions.sourceMaps,

// Ensure that Webpack will get a full absolute path in the sourcemap
// so that it can properly map the module back to its internal cached
// modules.
sourceFileName: filename,

plugins: getPlugins(loaderOptions, cacheCharacteristics),
plugins: [
...getPlugins(loaderOptions, cacheCharacteristics),
...customPlugins,
],

presets: [...presets, nextPresetItem],
presets,

overrides: loaderOptions.overrides,

Expand All @@ -197,8 +254,7 @@ function getFreshConfig(

isServer,
pagesDir,
development,
hasReactRefresh,
isDev: development,
hasJsxRuntime,

...loaderOptions.caller,
Expand Down Expand Up @@ -233,19 +289,21 @@ function getCacheKey(cacheCharacteristics: CharacteristicsGermaneToCaching) {
isPageFile,
isNextDist,
hasModuleExports,
fileExt,
} = cacheCharacteristics

return (
const flags =
0 |
(isServer ? 0b0001 : 0) |
(isPageFile ? 0b0010 : 0) |
(isNextDist ? 0b0100 : 0) |
(hasModuleExports ? 0b1000 : 0)
)

return fileExt + flags
}

type BabelConfig = any
const configCache: Map<number, BabelConfig> = new Map()
const configCache: Map<any, BabelConfig> = new Map()

export default function getConfig(
this: NextJsLoaderContext,
Expand All @@ -271,10 +329,17 @@ export default function getConfig(

const cacheKey = getCacheKey(cacheCharacteristics)
if (configCache.has(cacheKey)) {
const cachedConfig = configCache.get(cacheKey)

return {
...configCache.get(cacheKey),
filename,
sourceFileName: filename,
...cachedConfig,
options: {
...cachedConfig.options,
cwd: loaderOptions.cwd,
root: loaderOptions.cwd,
filename,
sourceFileName: filename,
},
}
}

Expand Down
4 changes: 0 additions & 4 deletions packages/next/build/babel/loader/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { inspect } from 'util'
import { getOptions } from 'next/dist/compiled/loader-utils'
import { trace } from '../../../telemetry/trace'
import { Span } from '../../../telemetry/trace'
Expand Down Expand Up @@ -52,9 +51,6 @@ const nextBabelLoaderOuter = function nextBabelLoaderOuter(
([transformedSource, outputSourceMap]) =>
callback?.(null, transformedSource, outputSourceMap || inputSourceMap),
(err) => {
console.error(
`Problem encountered in next-babel-turbo-loader. \n${inspect(err)}`
)
callback?.(err)
}
)
Expand Down
3 changes: 2 additions & 1 deletion packages/next/build/babel/loader/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ export interface NextBabelLoaderOptions {
sourceMaps?: any[]
overrides: any
caller: any
babelrc: boolean
configFile: string | undefined
cwd: string
}
14 changes: 9 additions & 5 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export default async function getBaseWebpackConfig(
// fixed in rc.1.
semver.gte(reactVersion!, '17.0.0-rc.1')

const babelrc = await [
const babelConfigFile = await [
'.babelrc',
'.babelrc.json',
'.babelrc.js',
Expand All @@ -219,9 +219,13 @@ export default async function getBaseWebpackConfig(
'babel.config.json',
'babel.config.mjs',
'babel.config.cjs',
].reduce(async (memo: boolean | Promise<boolean>, filename) => {
return (await memo) || (await fileExists(path.join(dir, filename)))
}, false)
].reduce(async (memo: Promise<string | undefined>, filename) => {
const configFilePath = path.join(dir, filename)
return (
(await memo) ||
((await fileExists(configFilePath)) ? configFilePath : undefined)
)
}, Promise.resolve(undefined))

const distDir = path.join(dir, config.distDir)

Expand All @@ -232,7 +236,7 @@ export default async function getBaseWebpackConfig(
babel: {
loader: babelLoader,
options: {
babelrc,
configFile: babelConfigFile,
isServer,
distDir,
pagesDir,
Expand Down
2 changes: 1 addition & 1 deletion test/integration/config-devtool-dev/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jest.setTimeout(1000 * 30)

const appDir = join(__dirname, '../')

describe('devtool set in developmemt mode in next config', () => {
describe('devtool set in development mode in next config', () => {
it('should warn and revert when a devtool is set in development mode', async () => {
let stderr = ''

Expand Down