Support solidjs libraries (#5059)
This commit is contained in:
parent
5cab04521a
commit
f7fcdfe621
10 changed files with 104 additions and 8 deletions
5
.changeset/ten-phones-drop.md
Normal file
5
.changeset/ten-phones-drop.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@astrojs/solid-js': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Auto ssr.noExternal solidjs dependencies
|
5
.changeset/thin-parents-breathe.md
Normal file
5
.changeset/thin-parents-breathe.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Support strict dependency install for libraries with JSX
|
|
@ -126,6 +126,7 @@
|
||||||
"gray-matter": "^4.0.3",
|
"gray-matter": "^4.0.3",
|
||||||
"html-entities": "^2.3.3",
|
"html-entities": "^2.3.3",
|
||||||
"html-escaper": "^3.0.3",
|
"html-escaper": "^3.0.3",
|
||||||
|
"import-meta-resolve": "^2.1.0",
|
||||||
"kleur": "^4.1.4",
|
"kleur": "^4.1.4",
|
||||||
"magic-string": "^0.25.9",
|
"magic-string": "^0.25.9",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
|
|
|
@ -98,6 +98,7 @@ interface TransformJSXOptions {
|
||||||
mode: string;
|
mode: string;
|
||||||
renderer: AstroRenderer;
|
renderer: AstroRenderer;
|
||||||
ssr: boolean;
|
ssr: boolean;
|
||||||
|
root: URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function transformJSX({
|
async function transformJSX({
|
||||||
|
@ -106,12 +107,13 @@ async function transformJSX({
|
||||||
id,
|
id,
|
||||||
ssr,
|
ssr,
|
||||||
renderer,
|
renderer,
|
||||||
|
root,
|
||||||
}: TransformJSXOptions): Promise<TransformResult> {
|
}: TransformJSXOptions): Promise<TransformResult> {
|
||||||
const { jsxTransformOptions } = renderer;
|
const { jsxTransformOptions } = renderer;
|
||||||
const options = await jsxTransformOptions!({ mode, ssr });
|
const options = await jsxTransformOptions!({ mode, ssr });
|
||||||
const plugins = [...(options.plugins || [])];
|
const plugins = [...(options.plugins || [])];
|
||||||
if (ssr) {
|
if (ssr) {
|
||||||
plugins.push(tagExportsPlugin({ rendererName: renderer.name }));
|
plugins.push(await tagExportsPlugin({ rendererName: renderer.name, root }));
|
||||||
}
|
}
|
||||||
const result = await babel.transformAsync(code, {
|
const result = await babel.transformAsync(code, {
|
||||||
presets: options.presets,
|
presets: options.presets,
|
||||||
|
@ -204,6 +206,7 @@ export default function jsx({ settings, logging }: AstroPluginJSXOptions): Plugi
|
||||||
renderer: astroJSXRenderer,
|
renderer: astroJSXRenderer,
|
||||||
mode,
|
mode,
|
||||||
ssr,
|
ssr,
|
||||||
|
root: settings.config.root,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (defaultJSXRendererEntry && jsxRenderersIntegrationOnly.size === 1) {
|
if (defaultJSXRendererEntry && jsxRenderersIntegrationOnly.size === 1) {
|
||||||
|
@ -220,6 +223,7 @@ export default function jsx({ settings, logging }: AstroPluginJSXOptions): Plugi
|
||||||
renderer: defaultJSXRendererEntry[1],
|
renderer: defaultJSXRendererEntry[1],
|
||||||
mode,
|
mode,
|
||||||
ssr,
|
ssr,
|
||||||
|
root: settings.config.root,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,6 +290,7 @@ https://docs.astro.build/en/core-concepts/framework-components/#installing-integ
|
||||||
renderer: selectedJsxRenderer,
|
renderer: selectedJsxRenderer,
|
||||||
mode,
|
mode,
|
||||||
ssr,
|
ssr,
|
||||||
|
root: settings.config.root,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { resolve as importMetaResolve } from 'import-meta-resolve';
|
||||||
import type { PluginObj } from '@babel/core';
|
import type { PluginObj } from '@babel/core';
|
||||||
import * as t from '@babel/types';
|
import * as t from '@babel/types';
|
||||||
|
|
||||||
|
@ -9,11 +11,16 @@ import * as t from '@babel/types';
|
||||||
* This plugin crawls each export in the file and "tags" each export with a given `rendererName`.
|
* This plugin crawls each export in the file and "tags" each export with a given `rendererName`.
|
||||||
* This allows us to automatically match a component to a renderer and skip the usual `check()` calls.
|
* This allows us to automatically match a component to a renderer and skip the usual `check()` calls.
|
||||||
*/
|
*/
|
||||||
export default function tagExportsWithRenderer({
|
export default async function tagExportsWithRenderer({
|
||||||
rendererName,
|
rendererName,
|
||||||
|
root,
|
||||||
}: {
|
}: {
|
||||||
rendererName: string;
|
rendererName: string;
|
||||||
}): PluginObj {
|
root: URL;
|
||||||
|
}): Promise<PluginObj> {
|
||||||
|
const astroServerPath = fileURLToPath(
|
||||||
|
await importMetaResolve('astro/server/index.js', root.toString())
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
visitor: {
|
visitor: {
|
||||||
Program: {
|
Program: {
|
||||||
|
@ -29,7 +36,7 @@ export default function tagExportsWithRenderer({
|
||||||
t.identifier('__astro_tag_component__')
|
t.identifier('__astro_tag_component__')
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
t.stringLiteral('astro/server/index.js')
|
t.stringLiteral(astroServerPath)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/solid-js": "workspace:*",
|
"@astrojs/solid-js": "workspace:*",
|
||||||
|
"@solidjs/router": "^0.5.0",
|
||||||
"astro": "workspace:*",
|
"astro": "workspace:*",
|
||||||
"solid-js": "^1.5.6"
|
"solid-js": "^1.5.6"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
import Hello from '../components/Hello.jsx';
|
import Hello from '../components/Hello.jsx';
|
||||||
import WithNewlines from '../components/WithNewlines.jsx';
|
import WithNewlines from '../components/WithNewlines.jsx';
|
||||||
|
import { Router } from "@solidjs/router";
|
||||||
---
|
---
|
||||||
<html>
|
<html>
|
||||||
<head><title>Solid</title></head>
|
<head><title>Solid</title></head>
|
||||||
|
@ -8,6 +9,7 @@ import WithNewlines from '../components/WithNewlines.jsx';
|
||||||
<div>
|
<div>
|
||||||
<Hello client:load />
|
<Hello client:load />
|
||||||
<WithNewlines client:load />
|
<WithNewlines client:load />
|
||||||
|
<Router />
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
57
packages/integrations/solid/src/dependencies.ts
Normal file
57
packages/integrations/solid/src/dependencies.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
// This file is a fork of vite-plugin-solid.
|
||||||
|
// Original: https://github.com/solidjs/vite-plugin-solid/blob/03130c8a0a2ceaab9a07e16f1e1df832b996e1b8/src/index.ts#L251-L297
|
||||||
|
// License: MIT (https://github.com/solidjs/vite-plugin-solid/blob/03130c8a0a2ceaab9a07e16f1e1df832b996e1b8/package.json#L38)
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { createRequire } from 'module';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
function containsSolidField(fields: Record<string, any>) {
|
||||||
|
const keys = Object.keys(fields);
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
const key = keys[i];
|
||||||
|
if (key === 'solid') return true;
|
||||||
|
if (typeof fields[key] === 'object' && containsSolidField(fields[key])) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSolidDeps(root: URL) {
|
||||||
|
const pkgPath = path.join(fileURLToPath(root), 'package.json');
|
||||||
|
if (!fs.existsSync(pkgPath)) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('No package.json found at project root');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const require = createRequire(pkgPath);
|
||||||
|
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
||||||
|
const deps = [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.devDependencies || {})];
|
||||||
|
const pkgs = deps.map((dep) => {
|
||||||
|
try {
|
||||||
|
return require(`${dep}/package.json`);
|
||||||
|
} catch {
|
||||||
|
try {
|
||||||
|
let dir = path.dirname(require.resolve(dep));
|
||||||
|
while (dir) {
|
||||||
|
const subPkgPath = path.join(dir, 'package.json');
|
||||||
|
if (fs.existsSync(subPkgPath)) {
|
||||||
|
const subPkg = JSON.parse(fs.readFileSync(subPkgPath, 'utf-8'));
|
||||||
|
if (subPkg && subPkg.name === dep) return subPkg;
|
||||||
|
}
|
||||||
|
const parent = path.dirname(dir);
|
||||||
|
if (parent === dir) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dir = parent;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Couldn't find package.json for", dep, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deps.reduce<string[]>((acc, dep, i) => {
|
||||||
|
if (pkgs[i] && pkgs[i].exports && containsSolidField(pkgs[i].exports)) acc.push(dep);
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import type { AstroIntegration, AstroRenderer } from 'astro';
|
import type { AstroIntegration, AstroRenderer } from 'astro';
|
||||||
|
import { getSolidDeps } from './dependencies.js';
|
||||||
|
|
||||||
function getRenderer(): AstroRenderer {
|
function getRenderer(): AstroRenderer {
|
||||||
return {
|
return {
|
||||||
|
@ -23,7 +24,7 @@ function getRenderer(): AstroRenderer {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getViteConfiguration(isDev: boolean) {
|
function getViteConfiguration(isDev: boolean, root: URL) {
|
||||||
// https://github.com/solidjs/vite-plugin-solid
|
// https://github.com/solidjs/vite-plugin-solid
|
||||||
// We inject the dev mode only if the user explicitely wants it or if we are in dev (serve) mode
|
// We inject the dev mode only if the user explicitely wants it or if we are in dev (serve) mode
|
||||||
const nestedDeps = ['solid-js', 'solid-js/web', 'solid-js/store', 'solid-js/html', 'solid-js/h'];
|
const nestedDeps = ['solid-js', 'solid-js/web', 'solid-js/store', 'solid-js/html', 'solid-js/h'];
|
||||||
|
@ -45,7 +46,7 @@ function getViteConfiguration(isDev: boolean) {
|
||||||
ssr: {
|
ssr: {
|
||||||
external: ['babel-preset-solid'],
|
external: ['babel-preset-solid'],
|
||||||
target: 'node',
|
target: 'node',
|
||||||
noExternal: ['solid-js'],
|
noExternal: ['solid-js', ...getSolidDeps(root)],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -54,9 +55,9 @@ export default function (): AstroIntegration {
|
||||||
return {
|
return {
|
||||||
name: '@astrojs/solid-js',
|
name: '@astrojs/solid-js',
|
||||||
hooks: {
|
hooks: {
|
||||||
'astro:config:setup': ({ command, addRenderer, updateConfig }) => {
|
'astro:config:setup': ({ command, addRenderer, updateConfig, config }) => {
|
||||||
addRenderer(getRenderer());
|
addRenderer(getRenderer());
|
||||||
updateConfig({ vite: getViteConfiguration(command === 'dev') });
|
updateConfig({ vite: getViteConfiguration(command === 'dev', config.root) });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -415,6 +415,7 @@ importers:
|
||||||
gray-matter: ^4.0.3
|
gray-matter: ^4.0.3
|
||||||
html-entities: ^2.3.3
|
html-entities: ^2.3.3
|
||||||
html-escaper: ^3.0.3
|
html-escaper: ^3.0.3
|
||||||
|
import-meta-resolve: ^2.1.0
|
||||||
kleur: ^4.1.4
|
kleur: ^4.1.4
|
||||||
magic-string: ^0.25.9
|
magic-string: ^0.25.9
|
||||||
mime: ^3.0.0
|
mime: ^3.0.0
|
||||||
|
@ -484,6 +485,7 @@ importers:
|
||||||
gray-matter: 4.0.3
|
gray-matter: 4.0.3
|
||||||
html-entities: 2.3.3
|
html-entities: 2.3.3
|
||||||
html-escaper: 3.0.3
|
html-escaper: 3.0.3
|
||||||
|
import-meta-resolve: 2.1.0
|
||||||
kleur: 4.1.5
|
kleur: 4.1.5
|
||||||
magic-string: 0.25.9
|
magic-string: 0.25.9
|
||||||
mime: 3.0.0
|
mime: 3.0.0
|
||||||
|
@ -2117,10 +2119,12 @@ importers:
|
||||||
packages/astro/test/fixtures/solid-component:
|
packages/astro/test/fixtures/solid-component:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@astrojs/solid-js': workspace:*
|
'@astrojs/solid-js': workspace:*
|
||||||
|
'@solidjs/router': ^0.5.0
|
||||||
astro: workspace:*
|
astro: workspace:*
|
||||||
solid-js: ^1.5.6
|
solid-js: ^1.5.6
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/solid-js': link:../../../../integrations/solid
|
'@astrojs/solid-js': link:../../../../integrations/solid
|
||||||
|
'@solidjs/router': 0.5.0_solid-js@1.5.7
|
||||||
astro: link:../../..
|
astro: link:../../..
|
||||||
solid-js: 1.5.7
|
solid-js: 1.5.7
|
||||||
|
|
||||||
|
@ -9282,6 +9286,14 @@ packages:
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@solidjs/router/0.5.0_solid-js@1.5.7:
|
||||||
|
resolution: {integrity: sha512-rNR07l21tWWDVmCbaapggB89rEX7jlM2XChpTLqEGEnj46LzVZ8zgvjcF6NNKScByAlLpoQUkVIjB2KHpcMi+w==}
|
||||||
|
peerDependencies:
|
||||||
|
solid-js: ^1.5.3
|
||||||
|
dependencies:
|
||||||
|
solid-js: 1.5.7
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@spectrum-icons/ui/3.3.3_jshkqybnlidashxgfmbz45rdaq:
|
/@spectrum-icons/ui/3.3.3_jshkqybnlidashxgfmbz45rdaq:
|
||||||
resolution: {integrity: sha512-KGPRQidTviIZWI1VHQCqNZ1dgPuOjXVTjr0ELih4y7+fV2r39qeukiKCs0AzePs7VUj04sZGRL+ZezKcvk/98Q==}
|
resolution: {integrity: sha512-KGPRQidTviIZWI1VHQCqNZ1dgPuOjXVTjr0ELih4y7+fV2r39qeukiKCs0AzePs7VUj04sZGRL+ZezKcvk/98Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
Loading…
Reference in a new issue