Skip to content

Commit

Permalink
feat(vite): islands support async component
Browse files Browse the repository at this point in the history
  • Loading branch information
yusukebe committed Jan 13, 2024
1 parent b14bc7d commit c69f607
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 9 deletions.
27 changes: 18 additions & 9 deletions src/vite/island-components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
import type { Plugin } from 'vite'
import { COMPONENT_NAME, DATA_SERIALIZED_PROPS } from '../constants.js'

function addSSRCheck(funcName: string, componentName: string) {
function addSSRCheck(funcName: string, componentName: string, isAsync = false) {
const isSSR = memberExpression(
memberExpression(identifier('import'), identifier('meta')),
identifier('env.SSR')
Expand Down Expand Up @@ -70,7 +70,11 @@ function addSSRCheck(funcName: string, componentName: string) {
)

const returnStmt = returnStatement(conditionalExpression(isSSR, ssrElement, clientElement))
return functionExpression(null, [identifier('props')], blockStatement([returnStmt]))
const functionExpr = functionExpression(null, [identifier('props')], blockStatement([returnStmt]))
if (isAsync) {
functionExpr.async = true
}
return functionExpr
}

export const transformJsxTags = (contents: string, componentName: string) => {
Expand All @@ -85,18 +89,23 @@ export const transformJsxTags = (contents: string, componentName: string) => {
if (path.node.declaration.type === 'FunctionDeclaration') {
const functionId = path.node.declaration.id
if (!functionId) return
const isAsync = path.node.declaration.async
const originalFunctionId = identifier(functionId.name + 'Original')

const originalFunction = functionExpression(
null,
path.node.declaration.params,
path.node.declaration.body
)
if (isAsync) {
originalFunction.async = true
}

path.insertBefore(
variableDeclaration('const', [
variableDeclarator(
originalFunctionId,
functionExpression(null, path.node.declaration.params, path.node.declaration.body)
),
])
variableDeclaration('const', [variableDeclarator(originalFunctionId, originalFunction)])
)

const wrappedFunction = addSSRCheck(originalFunctionId.name, componentName)
const wrappedFunction = addSSRCheck(originalFunctionId.name, componentName, isAsync)
const wrappedFunctionId = identifier('Wrapped' + functionId.name)
path.replaceWith(
variableDeclaration('const', [variableDeclarator(wrappedFunctionId, wrappedFunction)])
Expand Down
16 changes: 16 additions & 0 deletions test/unit/vite/island-components.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,20 @@ export default WrappedBadge;`
const code = transformJsxTags('', 'Badge.tsx')
expect(code).toBe('')
})

it('async', () => {
const code = `export default async function AsyncComponent() {
return <h1>Hello</h1>
}`
const result = transformJsxTags(code, 'AsyncComponent.tsx')
expect(result).toBe(
`const AsyncComponentOriginal = async function () {
return <h1>Hello</h1>;
};
const WrappedAsyncComponent = async function (props) {
return import.meta.env.SSR ? <honox-island component-name="AsyncComponent.tsx" data-serialized-props={JSON.stringify(props)}><AsyncComponentOriginal {...props}></AsyncComponentOriginal></honox-island> : <AsyncComponentOriginal {...props}></AsyncComponentOriginal>;
};
export default WrappedAsyncComponent;`
)
})
})

0 comments on commit c69f607

Please sign in to comment.