Public commit
This commit is contained in:
106
scripts/plugins/babel-why-did-you-render.ts
Normal file
106
scripts/plugins/babel-why-did-you-render.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import type { NodePath, types } from "@babel/core"
|
||||
import type { Node } from "@babel/core"
|
||||
import type { BabelPlugin } from "./esbuild-babel"
|
||||
|
||||
// useWhyDidYouUpdate
|
||||
export const whyDidYouRender =
|
||||
({
|
||||
hookName,
|
||||
hookPath,
|
||||
ignoredHooks,
|
||||
}: {
|
||||
hookName: string
|
||||
hookPath: string
|
||||
ignoredHooks: string[]
|
||||
}): BabelPlugin =>
|
||||
({ types: t }) => {
|
||||
const ignored = new WeakSet<Node>()
|
||||
|
||||
function ignore(node: Node) {
|
||||
ignored.add(node)
|
||||
return node
|
||||
}
|
||||
|
||||
return {
|
||||
name: "why-did-you-render",
|
||||
visitor: {
|
||||
Program(path, state) {
|
||||
const id = path.scope.generateUidIdentifier(hookName)
|
||||
path.node.body.unshift(
|
||||
t.importDeclaration(
|
||||
[t.importSpecifier(id, t.identifier(hookName))], //
|
||||
t.stringLiteral(hookPath),
|
||||
),
|
||||
)
|
||||
state.whyDidYouRenderId = id
|
||||
},
|
||||
|
||||
VariableDeclaration(path, state) {
|
||||
if (ignored.has(path.node)) return
|
||||
|
||||
const decls = path.node.declarations
|
||||
if (decls.length !== 1) return
|
||||
|
||||
const [{ init, id }] = decls
|
||||
if (
|
||||
!t.isCallExpression(init) ||
|
||||
!t.isIdentifier(init.callee) ||
|
||||
!init.callee.name.startsWith("use") ||
|
||||
init.callee.name.length <= 3
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ignoredHooks.includes(init.callee.name)) {
|
||||
return
|
||||
}
|
||||
|
||||
const findParent = <T extends types.Node>(
|
||||
predicate: (node: types.Node) => node is T,
|
||||
) => path.findParent(path => predicate(path.node)) as NodePath<T> | undefined
|
||||
|
||||
const parentId =
|
||||
findParent(t.isFunctionDeclaration)?.node.id!.name ??
|
||||
(<types.Identifier>(
|
||||
(<types.VariableDeclarator>findParent(t.isArrowFunctionExpression)?.parent)
|
||||
?.id
|
||||
))?.name
|
||||
|
||||
if (!parentId || parentId.startsWith("use")) {
|
||||
return
|
||||
}
|
||||
|
||||
const callee = t.cloneNode(state.whyDidYouRenderId as types.Identifier)
|
||||
|
||||
if (t.isIdentifier(id)) {
|
||||
path.insertAfter(
|
||||
t.callExpression(callee, [
|
||||
t.stringLiteral(parentId),
|
||||
t.stringLiteral(init.callee.name),
|
||||
id,
|
||||
]),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const temporaryId = path.scope.generateUidIdentifier(init.callee.name)
|
||||
|
||||
path.replaceWithMultiple([
|
||||
ignore(
|
||||
t.variableDeclaration(path.node.kind, [
|
||||
t.variableDeclarator(temporaryId, init),
|
||||
t.variableDeclarator(id, temporaryId),
|
||||
]),
|
||||
),
|
||||
t.expressionStatement(
|
||||
t.callExpression(callee, [
|
||||
t.stringLiteral(parentId),
|
||||
t.stringLiteral(init.callee.name),
|
||||
temporaryId,
|
||||
]),
|
||||
),
|
||||
])
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user