Resolve .jsx -> .tsx in hydrated components (#3663)
This commit is contained in:
parent
e13ce4d751
commit
c20b93c484
11 changed files with 169 additions and 4 deletions
5
.changeset/warm-panthers-clap.md
Normal file
5
.changeset/warm-panthers-clap.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Resolve .jsx -> .tsx in hydrated components
|
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'astro/config';
|
||||
import react from '@astrojs/react';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [react()],
|
||||
});
|
11
packages/astro/e2e/fixtures/ts-resolution/package.json
Normal file
11
packages/astro/e2e/fixtures/ts-resolution/package.json
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"name": "@e2e/ts-resolution",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@astrojs/react": "workspace:*",
|
||||
"astro": "workspace:*",
|
||||
"react": "^18.1.0",
|
||||
"react-dom": "^18.1.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import React, { useState } from 'react';
|
||||
|
||||
export default function Counter({ children, count: initialCount, id }) {
|
||||
const [count, setCount] = useState(initialCount);
|
||||
const add = () => setCount((i) => i + 1);
|
||||
const subtract = () => setCount((i) => i - 1);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id={id} className="counter">
|
||||
<button className="decrement" onClick={subtract}>-</button>
|
||||
<pre>{count}</pre>
|
||||
<button className="increment" onClick={add}>+</button>
|
||||
</div>
|
||||
<div className="counter-message">{children}</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
import Counter from '../components/Counter.jsx';
|
||||
|
||||
const someProps = {
|
||||
count: 0,
|
||||
};
|
||||
---
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<!-- Head Stuff -->
|
||||
</head>
|
||||
<body>
|
||||
<Counter id="client-idle" {...someProps} client:idle>
|
||||
<h1>Hello, client:idle!</h1>
|
||||
</Counter>
|
||||
</body>
|
||||
</html>
|
64
packages/astro/e2e/ts-resolution.test.js
Normal file
64
packages/astro/e2e/ts-resolution.test.js
Normal file
|
@ -0,0 +1,64 @@
|
|||
import { test as base, expect } from '@playwright/test';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
const test = base.extend({
|
||||
astro: async ({}, use) => {
|
||||
const fixture = await loadFixture({ root: './fixtures/ts-resolution/' });
|
||||
await use(fixture);
|
||||
},
|
||||
});
|
||||
|
||||
function runTest(test) {
|
||||
test('client:idle', async ({ page, astro }) => {
|
||||
await page.goto(astro.resolveUrl('/'));
|
||||
|
||||
const counter = page.locator('#client-idle');
|
||||
await expect(counter, 'component is visible').toBeVisible();
|
||||
|
||||
const count = counter.locator('pre');
|
||||
await expect(count, 'initial count is 0').toHaveText('0');
|
||||
|
||||
const inc = counter.locator('.increment');
|
||||
await inc.click();
|
||||
|
||||
await expect(count, 'count incremented by 1').toHaveText('1');
|
||||
});
|
||||
}
|
||||
|
||||
test.describe('TypeScript resolution -', () => {
|
||||
test.describe('Development', () => {
|
||||
const t = test.extend({});
|
||||
|
||||
let devServer;
|
||||
|
||||
t.beforeEach(async ({ astro }) => {
|
||||
devServer = await astro.startDevServer();
|
||||
});
|
||||
|
||||
t.afterEach(async () => {
|
||||
await devServer.stop();
|
||||
});
|
||||
|
||||
runTest(t);
|
||||
});
|
||||
|
||||
test.describe('Production', () => {
|
||||
const t = test.extend({});
|
||||
|
||||
let previewServer;
|
||||
|
||||
t.beforeAll(async ({ astro }) => {
|
||||
await astro.build();
|
||||
})
|
||||
|
||||
t.beforeEach(async ({ astro }) => {
|
||||
previewServer = await astro.preview();
|
||||
});
|
||||
|
||||
t.afterEach(async () => {
|
||||
await previewServer.stop();
|
||||
});
|
||||
|
||||
runTest(t);
|
||||
})
|
||||
});
|
|
@ -5,6 +5,7 @@ import type { BuildInternals } from '../../core/build/internal.js';
|
|||
import type { PluginMetadata as AstroPluginMetadata } from '../../vite-plugin-astro/types';
|
||||
|
||||
import { prependForwardSlash } from '../../core/path.js';
|
||||
import { resolveClientDevPath } from '../../core/render/dev/resolve.js';
|
||||
import { getTopLevelPages } from './graph.js';
|
||||
import { getPageDataByViteID, trackClientOnlyPageDatas } from './internal.js';
|
||||
|
||||
|
@ -84,7 +85,8 @@ export function vitePluginAnalyzer(
|
|||
const astro = info.meta.astro as AstroPluginMetadata['astro'];
|
||||
|
||||
for (const c of astro.hydratedComponents) {
|
||||
internals.discoveredHydratedComponents.add(c.resolvedPath || c.specifier);
|
||||
const rid = c.resolvedPath ? resolveClientDevPath(c.resolvedPath) : c.specifier;
|
||||
internals.discoveredHydratedComponents.add(rid);
|
||||
}
|
||||
|
||||
// Scan hoisted scripts
|
||||
|
@ -94,7 +96,7 @@ export function vitePluginAnalyzer(
|
|||
const clientOnlys: string[] = [];
|
||||
|
||||
for (const c of astro.clientOnlyComponents) {
|
||||
const cid = c.resolvedPath || c.specifier;
|
||||
const cid = c.resolvedPath ? resolveClientDevPath(c.resolvedPath) : c.specifier;
|
||||
internals.discoveredClientOnlyComponents.add(cid);
|
||||
clientOnlys.push(cid);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { createModuleScriptElementWithSrcSet } from '../ssr-element.js';
|
|||
import { collectMdMetadata } from '../util.js';
|
||||
import { getStylesForURL } from './css.js';
|
||||
import { injectTags } from './html.js';
|
||||
import { resolveClientDevPath } from './resolve.js';
|
||||
|
||||
export interface SSROptions {
|
||||
/** an instance of the AstroConfig */
|
||||
|
@ -178,7 +179,7 @@ export async function render(
|
|||
// Resolves specifiers in the inline hydrated scripts, such as "@astrojs/preact/client.js"
|
||||
async resolve(s: string) {
|
||||
if (s.startsWith('/@fs')) {
|
||||
return s;
|
||||
return resolveClientDevPath(s);
|
||||
}
|
||||
return '/@id' + prependForwardSlash(s);
|
||||
},
|
||||
|
|
10
packages/astro/src/core/render/dev/resolve.ts
Normal file
10
packages/astro/src/core/render/dev/resolve.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
|
||||
export function resolveClientDevPath(id: string) {
|
||||
if(id.startsWith('/@fs')) {
|
||||
// Vite does not resolve .jsx -> .tsx when coming from the client, so clip the extension.
|
||||
if(id.endsWith('.jsx')) {
|
||||
return id.slice(0, id.length - 4);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
|
@ -37,7 +37,15 @@ export class Metadata {
|
|||
}
|
||||
|
||||
resolvePath(specifier: string): string {
|
||||
return specifier.startsWith('.') ? new URL(specifier, this.mockURL).pathname : specifier;
|
||||
if(specifier.startsWith('.')) {
|
||||
const resolved = new URL(specifier, this.mockURL).pathname;
|
||||
// Vite does not resolve .jsx -> .tsx when coming from the client, so clip the extension.
|
||||
if(resolved.startsWith('/@fs') && resolved.endsWith('.jsx')) {
|
||||
return resolved.slice(0, resolved.length - 4);
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
return specifier;
|
||||
}
|
||||
|
||||
getPath(Component: any): string | null {
|
||||
|
|
|
@ -956,6 +956,18 @@ importers:
|
|||
'@astrojs/tailwind': link:../../../../integrations/tailwind
|
||||
astro: link:../../..
|
||||
|
||||
packages/astro/e2e/fixtures/ts-resolution:
|
||||
specifiers:
|
||||
'@astrojs/react': workspace:*
|
||||
astro: workspace:*
|
||||
react: ^18.1.0
|
||||
react-dom: ^18.1.0
|
||||
dependencies:
|
||||
'@astrojs/react': link:../../../../integrations/react
|
||||
astro: link:../../..
|
||||
react: 18.1.0
|
||||
react-dom: 18.1.0_react@18.1.0
|
||||
|
||||
packages/astro/e2e/fixtures/vue-component:
|
||||
specifiers:
|
||||
'@astrojs/vue': workspace:*
|
||||
|
@ -8188,6 +8200,11 @@ packages:
|
|||
|
||||
/debug/3.2.7:
|
||||
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
dev: false
|
||||
|
@ -11104,6 +11121,8 @@ packages:
|
|||
debug: 3.2.7
|
||||
iconv-lite: 0.4.24
|
||||
sax: 1.2.4
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/netmask/2.0.2:
|
||||
|
@ -11187,6 +11206,8 @@ packages:
|
|||
rimraf: 2.7.1
|
||||
semver: 5.7.1
|
||||
tar: 4.4.19
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/node-releases/2.0.5:
|
||||
|
|
Loading…
Reference in a new issue