From 829d5baafe45273c150c32c9287fadaf9676d404 Mon Sep 17 00:00:00 2001 From: "Fred K. Schott" Date: Wed, 28 Jul 2021 11:31:50 -0700 Subject: [PATCH] fix tsx+jsx error (#916) * fix tsx+jsx error * throw error if no build can be returned --- .changeset/heavy-ears-hope.md | 5 ++++ packages/astro/snowpack-plugin-jsx.cjs | 26 +++++++------------ .../src/components/PragmaComment.jsx | 2 +- .../components/PragmaCommentTypeScript.tsx | 5 ++++ .../src/components/TypeScriptComponent.tsx | 5 ++++ .../src/pages/pragma-comment.astro | 6 ++++- .../src/pages/ts-components.astro | 12 +++++++++ .../src/components/PragmaComment.jsx | 5 ++++ .../components/PragmaCommentTypeScript.tsx | 5 ++++ .../src/components/TypeScriptComponent.tsx | 5 ++++ .../react-component/src/pages/index.astro | 2 ++ .../src/pages/pragma-comment.astro | 14 ++++++++++ packages/astro/test/preact-component.test.js | 10 ++++++- packages/astro/test/react-component.test.js | 8 ++++++ 14 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 .changeset/heavy-ears-hope.md create mode 100644 packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx create mode 100644 packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx create mode 100644 packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro create mode 100644 packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx create mode 100644 packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx create mode 100644 packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx create mode 100644 packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro diff --git a/.changeset/heavy-ears-hope.md b/.changeset/heavy-ears-hope.md new file mode 100644 index 000000000..a63bdaf30 --- /dev/null +++ b/.changeset/heavy-ears-hope.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fix TSX issue with JSX multi-rendering diff --git a/packages/astro/snowpack-plugin-jsx.cjs b/packages/astro/snowpack-plugin-jsx.cjs index 419c55195..9c3e51079 100644 --- a/packages/astro/snowpack-plugin-jsx.cjs +++ b/packages/astro/snowpack-plugin-jsx.cjs @@ -23,6 +23,10 @@ function getLoader(fileExt) { return fileExt.substr(1); } +// The `tsx` loader in esbuild will remove unused imports, so we need to +// be careful about esbuild not treating h, React, Fragment, etc. as unused. +const PREVENT_UNUSED_IMPORTS = ';;(React,Fragment,h);'; + /** * @type {import('snowpack').SnowpackPluginFactory} */ @@ -74,18 +78,8 @@ module.exports = function jsxPlugin(config, options = {}) { }; if (importSources.size === 0) { - error( - logging, - 'renderer', - `${colors.yellow(filePath)} -Unable to resolve a renderer that handles JSX transforms! Please include a \`renderer\` plugin which supports JSX in your \`astro.config.mjs\` file.` - ); - - return { - '.js': { - code: '', - }, - }; + throw new Error(`${colors.yellow(filePath)} +Unable to resolve a renderer that handles JSX transforms! Please include a \`renderer\` plugin which supports JSX in your \`astro.config.mjs\` file.`); } // If we only have a single renderer, we can skip a bunch of work! @@ -99,10 +93,10 @@ Unable to resolve a renderer that handles JSX transforms! Please include a \`ren }; } - // we need valid JS to scan for imports - // so let's just use `h` and `Fragment` as placeholders - const { code: codeToScan } = await esbuild.transform(code, { - loader: 'jsx', + // we need valid JS here, so we can use `h` and `Fragment` as placeholders + // NOTE(fks, matthewp): Make sure that you're transforming the original contents here. + const { code: codeToScan } = await esbuild.transform(contents + PREVENT_UNUSED_IMPORTS, { + loader, jsx: 'transform', jsxFactory: 'h', jsxFragment: 'Fragment', diff --git a/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx b/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx index 3340e3f8e..498738113 100644 --- a/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx +++ b/packages/astro/test/fixtures/preact-component/src/components/PragmaComment.jsx @@ -1,5 +1,5 @@ /** @jsxImportSource preact */ export default function() { - return
Hello world
; + return
Hello world
; } diff --git a/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx b/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx new file mode 100644 index 000000000..7bfe65ada --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/components/PragmaCommentTypeScript.tsx @@ -0,0 +1,5 @@ +/** @jsxImportSource preact */ + +export default function({}: object) { + return
Hello world
; +} diff --git a/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx b/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx new file mode 100644 index 000000000..c341e13eb --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/components/TypeScriptComponent.tsx @@ -0,0 +1,5 @@ +import {h} from 'preact'; + +export default function({}: object) { + return
Hello world
; +} diff --git a/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro b/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro index 91db69830..720a0e0a5 100644 --- a/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro +++ b/packages/astro/test/fixtures/preact-component/src/pages/pragma-comment.astro @@ -1,10 +1,14 @@ --- import PragmaComponent from '../components/PragmaComment.jsx'; +import PragmaComponentTypeScript from '../components/PragmaCommentTypeScript.tsx'; --- Preact component works with Pragma comment - + + + + diff --git a/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro b/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro new file mode 100644 index 000000000..2e2597f10 --- /dev/null +++ b/packages/astro/test/fixtures/preact-component/src/pages/ts-components.astro @@ -0,0 +1,12 @@ +--- +import TypeScriptComponent from '../components/TypeScriptComponent.tsx'; +--- + + + + Preact TS component + + + + + \ No newline at end of file diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx b/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx new file mode 100644 index 000000000..d8ea77810 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/PragmaComment.jsx @@ -0,0 +1,5 @@ +/** @jsxImportSource react */ + +export default function() { + return
Hello world
; +} diff --git a/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx b/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx new file mode 100644 index 000000000..9f2256fbf --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/PragmaCommentTypeScript.tsx @@ -0,0 +1,5 @@ +/** @jsxImportSource react */ + +export default function({}: object) { + return
Hello world
; +} diff --git a/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx b/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx new file mode 100644 index 000000000..bde96da84 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/components/TypeScriptComponent.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function({}) { + return
Hello world
; +} diff --git a/packages/astro/test/fixtures/react-component/src/pages/index.astro b/packages/astro/test/fixtures/react-component/src/pages/index.astro index a64e076ce..3c0240296 100644 --- a/packages/astro/test/fixtures/react-component/src/pages/index.astro +++ b/packages/astro/test/fixtures/react-component/src/pages/index.astro @@ -4,6 +4,7 @@ import Later from '../components/Goodbye.vue'; // use different specifier import ArrowFunction from '../components/ArrowFunction.jsx'; import PropsSpread from '../components/PropsSpread.jsx'; import {Research2} from '../components/Research.jsx'; +import TypeScriptComponent from '../components/TypeScriptComponent'; const someProps = { text: 'Hello world!', @@ -20,5 +21,6 @@ const someProps = { + diff --git a/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro b/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro new file mode 100644 index 000000000..b3ddba639 --- /dev/null +++ b/packages/astro/test/fixtures/react-component/src/pages/pragma-comment.astro @@ -0,0 +1,14 @@ +--- +import PragmaComponent from '../components/PragmaComment.jsx'; +import PragmaComponentTypeScript from '../components/PragmaCommentTypeScript.tsx'; +--- + + + + React component works with Pragma comment + + + + + + diff --git a/packages/astro/test/preact-component.test.js b/packages/astro/test/preact-component.test.js index 67d071718..9ef02cad0 100644 --- a/packages/astro/test/preact-component.test.js +++ b/packages/astro/test/preact-component.test.js @@ -25,6 +25,14 @@ PreactComponent('Can load function component', async ({ runtime }) => { assert.equal($('#arrow-fn-component').length, 1, 'Can use function components'); }); +PreactComponent('Can load TS component', async ({ runtime }) => { + const result = await runtime.load('/ts-components'); + assert.ok(!result.error, `build error: ${result.error}`); + const $ = doc(result.contents); + assert.equal($('.ts-component').length, 1, 'Can use TS components'); +}); + + PreactComponent('Can use hooks', async ({ runtime }) => { const result = await runtime.load('/hooks'); assert.ok(!result.error, `build error: ${result.error}`); @@ -46,7 +54,7 @@ PreactComponent('Can use a pragma comment', async ({ runtime }) => { assert.ok(!result.error, `build error: ${result.error}`); const $ = doc(result.contents); - assert.equal($('#pragma-comment').length, 1, 'rendered the PragmaComment component.'); + assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.'); }); PreactComponent('Uses the new JSX transform', async ({ runtime }) => { diff --git a/packages/astro/test/react-component.test.js b/packages/astro/test/react-component.test.js index 6f10b2914..6bfde0d25 100644 --- a/packages/astro/test/react-component.test.js +++ b/packages/astro/test/react-component.test.js @@ -43,6 +43,7 @@ React('Can load React', async () => { assert.equal($('#arrow-fn-component').length, 1, 'Can use function components'); assert.equal($('#component-spread-props').length, 1, 'Can use spread for components'); assert.equal($('#component-spread-props').text(), 'Hello world!'); + assert.equal($('.ts-component').length, 1, 'Can use TS components'); }); React('Includes reactroot on hydrating components', async () => { @@ -74,6 +75,13 @@ React('Can load Vue', async () => { assert.equal($('#vue-h2').text(), 'Hasta la vista, baby'); }); +React('Can use a pragma comment', async () => { + const result = await runtime.load('/pragma-comment'); + assert.ok(!result.error, `build error: ${result.error}`); + const $ = doc(result.contents); + assert.equal($('.pragma-comment').length, 2, 'rendered the PragmaComment component.'); +}); + React('uses the new JSX transform', async () => { const result = await runtime.load('/'); assert.ok(!result.error, `build error: ${result.error}`);