735aab6f03
Fixes https://github.com/vercel/next.js/issues/16495 Terminal: ![image](https://user-images.githubusercontent.com/4278345/90984442-96421b00-e53a-11ea-9939-44b00cba87cf.png) Browser: ![image](https://user-images.githubusercontent.com/4278345/90984456-a9ed8180-e53a-11ea-86da-d9f28e9c2fdd.png) The link https://nextjs.link/codemod-ndc used for the warning links to a currently 404 docs page, that will be available in the next stable release. Tests not added as the warning has tests already.
91 lines
2.8 KiB
TypeScript
91 lines
2.8 KiB
TypeScript
import { PluginObj, types as BabelTypes } from '@babel/core'
|
|
import chalk from 'next/dist/compiled/chalk'
|
|
|
|
export default function NoAnonymousDefaultExport({
|
|
types: t,
|
|
...babel
|
|
}: {
|
|
types: typeof BabelTypes
|
|
caller: (callerCallback: (caller: any) => any) => any
|
|
}): PluginObj<any> {
|
|
let onWarning: ((reason: string | Error) => void) | null = null
|
|
babel.caller((caller) => {
|
|
onWarning = caller.onWarning
|
|
return '' // Intentionally empty to not invalidate cache
|
|
})
|
|
|
|
if (typeof onWarning !== 'function') {
|
|
return { visitor: {} }
|
|
}
|
|
|
|
const warn = onWarning!
|
|
return {
|
|
visitor: {
|
|
ExportDefaultDeclaration(path) {
|
|
const def = path.node.declaration
|
|
|
|
if (
|
|
!(
|
|
def.type === 'ArrowFunctionExpression' ||
|
|
def.type === 'FunctionDeclaration'
|
|
)
|
|
) {
|
|
return
|
|
}
|
|
|
|
switch (def.type) {
|
|
case 'ArrowFunctionExpression': {
|
|
warn(
|
|
[
|
|
chalk.yellow.bold(
|
|
'Anonymous arrow functions cause Fast Refresh to not preserve local component state.'
|
|
),
|
|
'Please add a name to your function, for example:',
|
|
'',
|
|
chalk.bold('Before'),
|
|
chalk.cyan('export default () => <div />;'),
|
|
'',
|
|
chalk.bold('After'),
|
|
chalk.cyan('const Named = () => <div />;'),
|
|
chalk.cyan('export default Named;'),
|
|
'',
|
|
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
|
'https://nextjs.link/codemod-ndc'
|
|
)}`,
|
|
].join('\n')
|
|
)
|
|
break
|
|
}
|
|
case 'FunctionDeclaration': {
|
|
const isAnonymous = !Boolean(def.id)
|
|
if (isAnonymous) {
|
|
warn(
|
|
[
|
|
chalk.yellow.bold(
|
|
'Anonymous function declarations cause Fast Refresh to not preserve local component state.'
|
|
),
|
|
'Please add a name to your function, for example:',
|
|
'',
|
|
chalk.bold('Before'),
|
|
chalk.cyan('export default function () { /* ... */ }'),
|
|
'',
|
|
chalk.bold('After'),
|
|
chalk.cyan('export default function Named() { /* ... */ }'),
|
|
'',
|
|
`A codemod is available to fix the most common cases: ${chalk.cyan(
|
|
'https://nextjs.link/codemod-ndc'
|
|
)}`,
|
|
].join('\n')
|
|
)
|
|
}
|
|
break
|
|
}
|
|
default: {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const _: never = def
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}
|
|
}
|