UNPKG

@tanstack/router-plugin

Version:

Modern and scalable routing for React applications

67 lines (58 loc) 2.17 kB
import * as template from '@babel/template' import * as t from '@babel/types' import { createHmrHotExpressionAst } from '../../hmr-hot-expression' import { getUniqueProgramIdentifier } from '../../utils' import type { ReferenceRouteCompilerPlugin } from '../plugins' function capitalizeIdentifier(str: string) { return str[0]!.toUpperCase() + str.slice(1) } function createHotDataKey(exportName: string) { return `tsr-split-component:${exportName}` } const buildStableSplitComponentStatements = template.statements( ` const %%stableComponentIdent%% = (() => { const hot = %%hotExpression%% const hotData = hot ? (hot.data ??= {}) : undefined return hotData?.[%%hotDataKey%%] ?? %%lazyRouteComponentIdent%%(%%localImporterIdent%%, %%exporterIdent%%) })() if (%%hotExpression%%) { ((%%hotExpression%%).data ??= {})[%%hotDataKey%%] = %%stableComponentIdent%% } `, { syntacticPlaceholders: true, }, ) export function createReactStableHmrSplitRouteComponentsPlugin(opts?: { hotExpression?: string }): ReferenceRouteCompilerPlugin { return { name: 'react-stable-hmr-split-route-components', onSplitRouteProperty(ctx) { if (ctx.splitNodeMeta.splitStrategy !== 'lazyRouteComponent') { return } const stableComponentIdent = getUniqueProgramIdentifier( ctx.programPath, `TSRSplit${capitalizeIdentifier(ctx.splitNodeMeta.exporterIdent)}`, ) const hotDataKey = createHotDataKey(ctx.splitNodeMeta.exporterIdent) ctx.insertionPath.insertBefore( buildStableSplitComponentStatements({ stableComponentIdent, hotDataKey: t.stringLiteral(hotDataKey), hotExpression: createHmrHotExpressionAst( opts?.hotExpression ?? ctx.opts.hmrHotExpression, ), lazyRouteComponentIdent: t.identifier(ctx.lazyRouteComponentIdent), localImporterIdent: t.identifier( ctx.splitNodeMeta.localImporterIdent, ), exporterIdent: t.stringLiteral(ctx.splitNodeMeta.exporterIdent), }), ) return t.identifier(stableComponentIdent.name) }, } }