rsnext/packages/next/build/babel/plugins/no-anonymous-default-export.ts
Guy Bedford 64850a8348
ncc Babel inlining (#18768)
This adds inlining for Babel and the Babel plugins used in next.

This is based to the PR at https://github.com/vercel/next.js/pull/18823.

The approach is to make one large bundle and then separate out the individual packages from that in order to avoid duplications.

In the first attempt the Babel bundle size was 10MB... using "resolutions" in the Yarn workspace to reduce the duplicated packages this was brought down to a 2.8MB bundle for Babel and all the used plugins which is exactly the expected file size here.

This will thus add a 2.8MB download size to the next package, but save downloading any babel dependencies separately, removing a large number of package dependencies from the overall install.
2020-11-05 14:23:01 +00:00

91 lines
2.8 KiB
TypeScript

import { PluginObj, types as BabelTypes } from 'next/dist/compiled/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
}
}
},
},
}
}