Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose JSX compilation to renderers #588

Merged
merged 17 commits into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dull-queens-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/renderer-solid': minor
---

Initial release
10 changes: 10 additions & 0 deletions .changeset/fair-cats-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
'@astrojs/renderer-preact': minor
'@astrojs/renderer-react': minor
---

Switches to [the new JSX Transform](https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) originally introduced for React v17. This also leverages the new `jsxTransformOptions` options for renderers.

This change also removes the need for importing your Framework's `jsxFactory` directly, which means you can wave goodbye to `import React from "react";` and `import { h } from "preact";`.

> **If you are using mutliple frameworks** and a file doesn't reference `react` or `preact`, Astro might not be able to locate the correct renderer! You can add a pragma comment like `/** @jsxImportSource preact */` to the top of your file. Alternatively, just import the JSX pragma as you traditionally would have.
5 changes: 5 additions & 0 deletions .changeset/five-bobcats-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'create-astro': patch
---

Add support for [Solid](https://www.solidjs.com/)
5 changes: 5 additions & 0 deletions .changeset/lemon-yaks-dream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/renderer-preact': patch
---

Update `check` logic to exclude false-positives from SolidJS
45 changes: 45 additions & 0 deletions docs/src/pages/reference/renderer-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,54 @@ export default {
external: ['dep'] // optional, dependencies that should not be built by snowpack
polyfills: ['./shadow-dom-polyfill.js'] // optional, module scripts that should be loaded before client hydration.
hydrationPolyfills: ['./hydrate-framework.js'] // optional, polyfills that need to run before hydration ever occurs.
jsxImportSource: 'preact', // optional, the name of the library from which JSX is imported
jsxTransformOptions: async () => { // optional, a function to transform JSX files
const { default: { default: jsx }} = await import('@babel/plugin-transform-react-jsx');
return {
plugins: [
jsx({}, { runtime: 'automatic', importSource: 'preact' })
]
}
}
};
```

### JSX Support

Astro is unique in that it allows you to mix multiple types of JSX/TSX files in a single project. It does this by reading the `jsxImportSource` and `jsxTransformOptions` from renderers and transforming a file with [Babel](https://babeljs.io/).

#### `jsxImportSource`
This is the name of your library (for example `preact` or `react` or `solid-js`) which, if encountered in a file, will signal to Astro that this renderer should be used.

Users may also manually define `/** @jsxImportSource preact */` in to ensure that the file is processed by this renderer (if, for example, the file has no imports).

#### `jsxTransformOptions`
This is an `async` function that returns information about how to transform matching JSX files with [Babel](https://babeljs.io/). It supports [`plugins`](https://babeljs.io/docs/en/plugins) or [`presets`](https://babeljs.io/docs/en/presets) to be passed directly to Babel.

> Keep in mind that this transform doesn't need to handle TSX separately from JSX, Astro handles that for you!

The arguments passed to `jsxTransformOptions` follow Snowpack's `load()` plugin hook. These allow you to pass separate Babel configurations for various conditions, like if your files should be compiled differently in SSR mode.

```ts
export interface JSXTransformOptions {
(context: {
/** True if builder is in dev mode (`astro dev`) */
isDev: boolean;
/** True if HMR is enabled (add any HMR code to the output here). */
isHmrEnabled: boolean;
/** True if builder is in SSR mode */
isSSR: boolean;
/** True if file being transformed is inside of a package. */
isPackage: boolean;
}) => {
plugins?: any[];
presets?: any[];
}
}
```

####

### Server Entrypoint (`server.js`)

The server entrypoint of a renderer is responsible for checking if a component should use this renderer, and if so, how that component should be rendered to a string of static HTML.
Expand Down
2 changes: 0 additions & 2 deletions examples/framework-multiple/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@ npm init astro -- --template framework-multiple
This example showcases Astro's built-in support for multiple frameworks ([React](https://reactjs.org), [Preact](https://preactjs.com), [Svelte](https://svelte.dev), and [Vue (`v3.x`)](https://v3.vuejs.org/)).

No configuration is needed to enable these frameworks—just start writing components in `src/components`.

> **Note**: If used, components _must_ include a JSX factory (ex. `import React from "react"`, `import { h } from "preact"`). Astro is unable to determine which framework is used without having the [JSX factory](https://mariusschulz.com/blog/per-file-jsx-factories-in-typescript#what-is-a-jsx-factory) in scope.
8 changes: 7 additions & 1 deletion examples/framework-multiple/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,11 @@ export default {
// port: 3000, // The port to run the dev server on.
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
},
renderers: ['@astrojs/renderer-preact', '@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'],
renderers: [
'@astrojs/renderer-preact',
'@astrojs/renderer-react',
'@astrojs/renderer-svelte',
'@astrojs/renderer-vue',
'@astrojs/renderer-solid',
]
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { h, Fragment } from 'preact';
import { useState } from 'preact/hooks';

/** a counter written in Preact */
Expand Down
12 changes: 12 additions & 0 deletions examples/framework-multiple/src/components/PreactSFC.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** @jsxImportSource preact */

/** a counter written in Preact */
export default function PreactSFC({ children }) {
return (
<>
<div className="counter">
Hello from Preact!
</div>
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import { useState } from 'react';

/** a counter written in React */
export function Counter({ children }) {
Expand Down
21 changes: 21 additions & 0 deletions examples/framework-multiple/src/components/SolidCounter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createSignal } from "solid-js";

/** a counter written with Solid */
export default function SolidCounter({ children }) {
const [count, setCount] = createSignal(0);
const add = () => setCount(count() + 1);
const subtract = () => setCount(count() - 1);

return (
<>
<div id="solid" class="counter">
<button onClick={subtract}>-</button>
<pre>{count()}</pre>
<button onClick={add}>+</button>
</div>
<div class="children">
{children}
</div>
</>
);
}
7 changes: 6 additions & 1 deletion examples/framework-multiple/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import { A, B as Renamed } from '../components';
import * as react from '../components/ReactCounter.jsx';
import { PreactCounter } from '../components/PreactCounter.tsx';
import PreactSFC from '../components/PreactSFC.tsx';
import SolidCounter from '../components/SolidCounter.tsx';
import VueCounter from '../components/VueCounter.vue';
import SvelteCounter from '../components/SvelteCounter.svelte';


// Full Astro Component Syntax:
// https://docs.astro.build/core-concepts/astro-components/
---
Expand Down Expand Up @@ -45,6 +46,10 @@ import SvelteCounter from '../components/SvelteCounter.svelte';
<h1>Hello Preact!</h1>
</PreactCounter>

<SolidCounter client:visible>
<h1>Hello Solid!</h1>
</SolidCounter>

<VueCounter client:visible>
<h1>Hello Vue!</h1>
</VueCounter>
Expand Down
35 changes: 31 additions & 4 deletions examples/framework-preact/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
# Using Preact with Astro

```
This example showcases Astro's built-in support for [Preact](https://www.preactjs.com/).

## Installation

### Automatic

Bootstrap your Astro project with this template!

```shell
npm init astro -- --template framework-preact
```

This example showcases Astro's built-in support for [Preact](https://preactjs.com/).
### Manual

To use Preact components in your Astro project:

1. Install `@astrojs/renderer-preact`

```shell
npm i @astrojs/renderer-preact
```

2. Add `"@astrojs/renderer-preact"` to your `renderers` in `astro.config.mjs`.

```js
export default {
renderers: [
"@astrojs/renderer-preact",
// optionally, others...
]
}
```

No configuration is needed to enable Preact support—just start writing Preact components in `src/components`.
## Usage

> **Note**: If used, components _must_ include the JSX factory (ex. `import { h } from "preact"`). Astro is unable to determine which framework is used without having the [JSX factory](https://mariusschulz.com/blog/per-file-jsx-factories-in-typescript#what-is-a-jsx-factory) in scope.
Write your Preact components as `.jsx` or `.tsx` files in your project.
35 changes: 31 additions & 4 deletions examples/framework-react/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,38 @@
# Using React with Astro

```
This example showcases Astro's built-in support for [React](https://reactjs.org/).

## Installation

### Automatic

Bootstrap your Astro project with this template!

```shell
npm init astro -- --template framework-react
```

This example showcases Astro's built-in support for [React](https://reactjs.org/).
### Manual

To use React components in your Astro project:

1. Install `@astrojs/renderer-react`

```shell
npm i @astrojs/renderer-react
```

2. Add `"@astrojs/renderer-react"` to your `renderers` in `astro.config.mjs`.

```js
export default {
renderers: [
"@astrojs/renderer-react",
// optionally, others...
]
}
```

No configuration is needed to enable React support—just start writing React components in `src/components`.
## Usage

> **Note**: If used, components _must_ include the JSX factory (ex. `import React from "react"`). Astro is unable to determine which framework is used without having the [JSX factory](https://mariusschulz.com/blog/per-file-jsx-factories-in-typescript#what-is-a-jsx-factory) in scope.
Write your React components as `.jsx` or `.tsx` files in your project.
18 changes: 18 additions & 0 deletions examples/framework-solid/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# build output
dist

# dependencies
node_modules/
.snowpack/

# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# environment variables
.env
.env.production

# macOS-specific files
.DS_Store
2 changes: 2 additions & 0 deletions examples/framework-solid/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
## force pnpm to hoist
shamefully-hoist = true
38 changes: 38 additions & 0 deletions examples/framework-solid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Using Solid with Astro

This example showcases Astro's built-in support for [Solid](https://www.solidjs.com/).

## Installation

### Automatic

Bootstrap your Astro project with this template!

```shell
npm init astro --template framework-solid
```

### Manual

To use Solid components in your Astro project:

1. Install `@astrojs/renderer-solid`

```shell
npm i @astrojs/renderer-solid
```

2. Add `"@astrojs/renderer-solid"` to your `renderers` in `astro.config.mjs`.

```js
export default {
renderers: [
"@astrojs/renderer-solid",
// optionally, others...
]
}
```

## Usage

Write your Solid components as `.jsx` or `.tsx` files in your project.
17 changes: 17 additions & 0 deletions examples/framework-solid/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
// projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project.
// pages: './src/pages', // Path to Astro components, pages, and data
// dist: './dist', // When running `astro build`, path to final static output
// public: './public', // A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that don’t need processing.
buildOptions: {
// site: 'http://example.com', // Your public domain, e.g.: https://my-site.dev/. Used to generate sitemaps and canonical URLs.
// sitemap: true, // Generate sitemap (set to "false" to disable)
},
devOptions: {
// port: 3000, // The port to run the dev server on.
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
},
renderers: [
'@astrojs/renderer-solid'
]
};
16 changes: 16 additions & 0 deletions examples/framework-solid/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "@example/framework-solid",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "astro dev",
"build": "astro build"
},
"devDependencies": {
"astro": "^0.18.0-next.1",
"@astrojs/renderer-solid": "0.0.1"
},
"snowpack": {
"workspaceRoot": "../.."
}
}
21 changes: 21 additions & 0 deletions examples/framework-solid/src/components/Counter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createSignal } from "solid-js";

/** */
export default function SolidCounter({ children }) {
const [count, setCount] = createSignal(0);
const add = () => setCount(count() + 1);
const subtract = () => setCount(count() - 1);

return (
<>
<div class="counter">
<button onClick={subtract}>-</button>
<pre>{count()}</pre>
<button onClick={add}>+</button>
</div>
<div class="children">
{children}
</div>
</>
);
}
Loading