[next] fix .tsx
handling (#1620)
* fix: support tsx in JSX plugin * fix: preserve JSX via esbuild, only use Babel for JSX compilation * fix: handle upcoming Vite API for `ssr` flag
This commit is contained in:
parent
2c36d0a427
commit
51e5a45ec5
1 changed files with 34 additions and 9 deletions
|
@ -27,12 +27,28 @@ interface AstroPluginJSXOptions {
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/vitejs/vite/discussions/5109#discussioncomment-1450726
|
||||||
|
function isSSR(options: undefined | boolean | { ssr: boolean }): boolean {
|
||||||
|
if (options === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof options === 'boolean') {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
if (typeof options == 'object') {
|
||||||
|
return !!options.ssr;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Use Astro config to allow for alternate or multiple JSX renderers (by default Vite will assume React) */
|
/** Use Astro config to allow for alternate or multiple JSX renderers (by default Vite will assume React) */
|
||||||
export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin {
|
export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin {
|
||||||
return {
|
return {
|
||||||
name: '@astrojs/vite-plugin-jsx',
|
name: '@astrojs/vite-plugin-jsx',
|
||||||
enforce: 'pre', // run transforms before other plugins
|
enforce: 'pre', // run transforms before other plugins
|
||||||
async transform(code, id, ssr) {
|
async transform(code, id, ssrOrOptions) {
|
||||||
|
const ssr = isSSR(ssrOrOptions);
|
||||||
if (!JSX_EXTENSIONS.has(path.extname(id))) {
|
if (!JSX_EXTENSIONS.has(path.extname(id))) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -56,22 +72,26 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
|
||||||
// Attempt: Single JSX renderer
|
// Attempt: Single JSX renderer
|
||||||
// If we only have one renderer, we can skip a bunch of work!
|
// If we only have one renderer, we can skip a bunch of work!
|
||||||
if (JSX_RENDERERS.size === 1) {
|
if (JSX_RENDERERS.size === 1) {
|
||||||
return transformJSX({ code, id, renderer: [...JSX_RENDERERS.values()][0], ssr: ssr || false });
|
// downlevel any non-standard syntax, but preserve JSX
|
||||||
|
const { code: jsxCode } = await esbuild.transform(code, {
|
||||||
|
loader: getLoader(path.extname(id)),
|
||||||
|
jsx: 'preserve'
|
||||||
|
});
|
||||||
|
return transformJSX({ code: jsxCode, id, renderer: [...JSX_RENDERERS.values()][0], ssr });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt: Multiple JSX renderers
|
// Attempt: Multiple JSX renderers
|
||||||
// Determine for each .jsx or .tsx file what it wants to use to Render
|
// we need valid JS to scan, so we can use `h` and `Fragment` as placeholders
|
||||||
// we need valid JS here, so we can use `h` and `Fragment` as placeholders
|
const { code: jsCode } = await esbuild.transform(code + PREVENT_UNUSED_IMPORTS, {
|
||||||
// NOTE(fks, matthewp): Make sure that you're transforming the original contents here.
|
|
||||||
const { code: codeToScan } = await esbuild.transform(code + PREVENT_UNUSED_IMPORTS, {
|
|
||||||
loader: getLoader(path.extname(id)),
|
loader: getLoader(path.extname(id)),
|
||||||
jsx: 'transform',
|
jsx: 'transform',
|
||||||
jsxFactory: 'h',
|
jsxFactory: 'h',
|
||||||
jsxFragment: 'Fragment',
|
jsxFragment: 'Fragment',
|
||||||
});
|
});
|
||||||
|
|
||||||
let imports: eslexer.ImportSpecifier[] = [];
|
let imports: eslexer.ImportSpecifier[] = [];
|
||||||
if (/import/.test(codeToScan)) {
|
if (/import/.test(jsCode)) {
|
||||||
let [i] = eslexer.parse(codeToScan);
|
let [i] = eslexer.parse(jsCode);
|
||||||
imports = i as any;
|
imports = i as any;
|
||||||
}
|
}
|
||||||
let importSource: string | undefined;
|
let importSource: string | undefined;
|
||||||
|
@ -106,7 +126,12 @@ export default function jsx({ config, logging }: AstroPluginJSXOptions): Plugin
|
||||||
error(logging, 'renderer', `${colors.yellow(id)} No renderer installed for ${importSource}. Try adding \`@astrojs/renderer-${importSource}\` to your dependencies.`);
|
error(logging, 'renderer', `${colors.yellow(id)} No renderer installed for ${importSource}. Try adding \`@astrojs/renderer-${importSource}\` to your dependencies.`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return transformJSX({ code, id, renderer: JSX_RENDERERS.get(importSource) as Renderer, ssr: ssr || false });
|
// downlevel any non-standard syntax, but preserve JSX
|
||||||
|
const { code: jsxCode } = await esbuild.transform(code, {
|
||||||
|
loader: getLoader(path.extname(id)),
|
||||||
|
jsx: 'preserve'
|
||||||
|
});
|
||||||
|
return transformJSX({ code: jsxCode, id, renderer: JSX_RENDERERS.get(importSource) as Renderer, ssr });
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we still can’t tell, throw error
|
// if we still can’t tell, throw error
|
||||||
|
|
Loading…
Add table
Reference in a new issue