On this page
JSX
Deno has built-in support for JSX in both .jsx
files and .tsx
files. JSX in
Deno can be handy for server-side rendering or generating code for browser
consumption.
Default configuration Jump to heading
The Deno CLI has a default configuration for JSX that is different than the
defaults for tsc
. Effectively Deno uses the following
TypeScript compiler
options by default:
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment"
}
}
Using the "react"
option will convert JSX into the following JavaScript code:
// input
const jsx = (
<div className="foo">
<MyComponent value={2} />
</div>
);
// output:
const jsx = React.createElement(
"div",
{ className: "foo" },
React.createElement(MyComponent, { value: 2 }),
);
JSX automatic runtime (recommended) Jump to heading
In React 17, the React team added what they called the new JSX transforms. This enhanced and modernized the API for JSX transforms as well as provided a mechanism to automatically add relevant JSX imports so that you don't have to do this yourself. This is the recommended way to use JSX.
To use the newer JSX runtime transform change the compiler options in your
deno.json
.
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "react"
},
"imports": {
"react": "npm:react"
}
}
Behind the scenes the jsxImportSource
setting will always append a
/jsx-runtime
to the import specifier.
// This import will be inserted automatically
import { jsx as _jsx } from "react/jsx-runtime";
Using the "react-jsx"
option will convert JSX into the following JavaScript
code:
// input
const jsx = (
<div className="foo">
<MyComponent value={2} />
</div>
);
// output
import { jsx as _jsx } from "react/jsx-runtime";
const jsx = _jsx(
"div",
{
className: "foo",
children: _jsx(MyComponent, { value: 2 }),
},
);
If you want to use Preact instead of React you can
update the jsxImportSource
value accordingly.
{
"compilerOptions": {
"jsx": "react-jsx",
- "jsxImportSource": "react"
+ "jsxImportSource": "preact"
},
"imports": {
- "react": "npm:react"
+ "preact": "npm:preact"
}
}
Development transform Jump to heading
Setting the "jsx"
option to "react-jsxdev"
instead of "react-jsx"
will
pass additional debugging information to each JSX node. The additional
information is the file path, line number and column number of the callsite of
each JSX node.
This information is typically used in frameworks to enhance the debugging experience during development. In React this information is used to enhance stack traces and show where a component was instantiated in the React developer tools browser extension.
Using the "react-jsxdev"
option will convert JSX into the following JavaScript
code:
// input
const jsx = (
<div className="foo">
<MyComponent value={2} />
</div>
);
// output
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
const _jsxFileName = "file:///input.tsx";
const jsx = _jsxDEV(
"div",
{
className: "foo",
children: _jsxDEV(
MyComponent,
{
value: 2,
},
void 0,
false,
{
fileName: _jsxFileName,
lineNumber: 3,
columnNumber: 5,
},
this,
),
},
void 0,
false,
{
fileName: _jsxFileName,
lineNumber: 1,
columnNumber: 14,
},
this,
);
Only use the "react-jsxdev"
information during development and not in
production.
Using the JSX import source pragma Jump to heading
Whether you have a JSX import source configured for your project, or if you are
using the default "legacy" configuration, you can add the JSX import source
pragma to a .jsx
or .tsx
module, and Deno will respect it.
The @jsxImportSource
pragma needs to be in the leading comments of the module.
For example to use Preact from esm.sh, you would do something like this:
/** @jsxImportSource https://esm.sh/preact */
export function App() {
return (
<div>
<h1>Hello, world!</h1>
</div>
);
}
jsxImportSourceTypes
Jump to heading
In certain cases, a library may not provide types. To specify the types, you can
use the @jsxImportSourceTypes
pragma:
/** @jsxImportSource npm:react@^18.3 */
/** @jsxImportSourceTypes npm:@types/react@^18.3 */
export function Hello() {
return <div>Hello!</div>;
}
Or specify via the jsxImportSourceTypes
compiler option in a deno.json:
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "npm:react@^18.3",
"jsxImportSourceTypes": "npm:@types/react@^18.3"
}
}
JSX precompile transform Jump to heading
Deno ships with a new JSX transform that is optimized for server-side rendering. It can be up to 7-20x faster than the other JSX transform options. The difference is that the precompile transform analyses your JSX statically and stores precompiled HTML strings if possible. That way a lot of time creating JSX objects can be avoided.
To use the precompile transform, set the jsx
option to "precompile"
.
{
"compilerOptions": {
+ "jsx": "precompile",
"jsxImportSource": "preact"
},
"imports": {
"preact": "npm:preact"
}
}
To prevent JSX nodes representing HTML elements from being precompiled, you can
add them to the jsxPrecompileSkipElements
setting.
{
"compilerOptions": {
"jsx": "precompile",
"jsxImportSource": "preact",
+ "jsxPrecompileSkipElements": ["a", "link"]
},
"imports": {
"preact": "npm:preact"
}
}
Using the "precompile"
option will convert JSX into the following JavaScript
code:
// input
const jsx = (
<div className="foo">
<MyComponent value={2} />
</div>
);
// output:
import {
jsx as _jsx,
jsxTemplate as _jsxTemplate,
} from "npm:preact/jsx-runtime";
const $$_tpl_1 = [
'<div class="foo">',
"</div>",
];
function MyComponent() {
return null;
}
const jsx = _jsxTemplate(
$$_tpl_1,
_jsx(MyComponent, {
value: 2,
}),
);