diff --git a/examples/snowpack/astro/components/Nav.astro b/examples/snowpack/astro/components/Nav.astro
index a5f14d656..d2c0e943c 100644
--- a/examples/snowpack/astro/components/Nav.astro
+++ b/examples/snowpack/astro/components/Nav.astro
@@ -345,8 +345,8 @@ export let version: string = '3.1.2';
};
diff --git a/examples/snowpack/astro/components/PluginSearchPage.jsx b/examples/snowpack/astro/components/PluginSearchPage.jsx
index 621cbe02b..51c7e6b0f 100644
--- a/examples/snowpack/astro/components/PluginSearchPage.jsx
+++ b/examples/snowpack/astro/components/PluginSearchPage.jsx
@@ -43,7 +43,7 @@ function Card({ result }) {
);
}
-export default function PluginSearchPage() {
+function PluginSearchPageLive() {
const searchParams = new URLSearchParams(window.location.search);
const [results, setResults] = useState(null);
const [searchQuery, setSearchQuery] = useState(searchParams.get('q'));
@@ -65,9 +65,6 @@ export default function PluginSearchPage() {
setResults(await searchPlugins(formula));
return false;
}
- // if (document.getElementById('loading-message')) {
- // document.getElementById('loading-message').style.display = 'none';
- // }
return (
<>
@@ -118,3 +115,7 @@ export default function PluginSearchPage() {
>
);
}
+
+export default function PluginSearchPage(props) {
+ return import.meta.env.astro ?
Loading...
:
+}
diff --git a/examples/snowpack/astro/pages/plugins.astro b/examples/snowpack/astro/pages/plugins.astro
index bffe9b4b9..ddd7632e8 100644
--- a/examples/snowpack/astro/pages/plugins.astro
+++ b/examples/snowpack/astro/pages/plugins.astro
@@ -66,7 +66,7 @@ let description = 'Snowpack plugins allow for configuration-minimal tooling inte
Creating your own plugin is easy!
-
+
diff --git a/package-lock.json b/package-lock.json
index 2e2f028b9..83d45dc04 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2956,15 +2956,15 @@
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ=="
},
"preact": {
- "version": "10.5.12",
- "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.12.tgz",
- "integrity": "sha512-r6siDkuD36oszwlCkcqDJCAKBQxGoeEGytw2DGMD5A/GGdu5Tymw+N2OBXwvOLxg6d1FeY8MgMV3cc5aVQo4Cg==",
+ "version": "10.5.13",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.5.13.tgz",
+ "integrity": "sha512-q/vlKIGNwzTLu+jCcvywgGrt+H/1P/oIRSD6mV4ln3hmlC+Aa34C7yfPI4+5bzW8pONyVXYS7SvXosy2dKKtWQ==",
"dev": true
},
"preact-render-to-string": {
- "version": "5.1.16",
- "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.1.16.tgz",
- "integrity": "sha512-HvO3W29Sziz9r5FZGwl2e34XJKzyRLvjhouv3cpkCGszNPdnvkO8p4B6CBpe0MT/tzR+QVbmsAKLrMK222UXew==",
+ "version": "5.1.18",
+ "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.1.18.tgz",
+ "integrity": "sha512-jTL6iTZeheYOhb54r7KuyrNCf33lc+Z52Wos5P1z2wGZ/dREfhBVwrK1qGOrl4fboBN1KxC1lxhBchDHNZr8Uw==",
"dev": true,
"requires": {
"pretty-format": "^3.8.0"
diff --git a/package.json b/package.json
index 5762c5d2e..0f4b70f6f 100644
--- a/package.json
+++ b/package.json
@@ -81,8 +81,8 @@
"eslint-plugin-prettier": "^3.3.1",
"estree-walker": "^3.0.0",
"nodemon": "^2.0.7",
- "preact": "^10.5.12",
- "preact-render-to-string": "^5.1.14",
+ "preact": "^10.5.13",
+ "preact-render-to-string": "^5.1.18",
"prettier": "^2.2.1",
"typescript": "^4.2.3",
"uvu": "^0.5.1"
diff --git a/src/build.ts b/src/build.ts
index 25d5e5ec6..ffae6fac0 100644
--- a/src/build.ts
+++ b/src/build.ts
@@ -61,7 +61,7 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
const runtime = await createRuntime(astroConfig, { logging: runtimeLogging });
const { runtimeConfig } = runtime;
- const { snowpack } = runtimeConfig;
+ const { backendSnowpack: snowpack } = runtimeConfig;
const resolve = (pkgName: string) => snowpack.getUrlForPackage(pkgName);
const imports = new Set();
diff --git a/src/frontend/render/renderer.ts b/src/frontend/render/renderer.ts
index d7afc0558..9589cef85 100644
--- a/src/frontend/render/renderer.ts
+++ b/src/frontend/render/renderer.ts
@@ -5,7 +5,7 @@ interface DynamicRenderContext {
}
export interface Renderer {
- renderStatic(Component: any): (props: Record, ...children: any[]) => string;
+ renderStatic(Component: any): (props: Record, ...children: any[]) => string;
render(context: { root: string; Component: string; props: string; [key: string]: string }): string;
imports?: Record;
}
diff --git a/src/runtime.ts b/src/runtime.ts
index f36ef1225..e0ac09de7 100644
--- a/src/runtime.ts
+++ b/src/runtime.ts
@@ -10,9 +10,12 @@ import { loadConfiguration, logger as snowpackLogger, startServer as startSnowpa
interface RuntimeConfig {
astroConfig: AstroConfig;
logging: LogOptions;
- snowpack: SnowpackDevServer;
- snowpackRuntime: SnowpackServerRuntime;
- snowpackConfig: SnowpackConfig;
+ backendSnowpack: SnowpackDevServer;
+ backendSnowpackRuntime: SnowpackServerRuntime;
+ backendSnowpackConfig: SnowpackConfig;
+ frontendSnowpack: SnowpackDevServer;
+ frontendSnowpackRuntime: SnowpackServerRuntime;
+ frontendSnowpackConfig: SnowpackConfig;
}
type LoadResultSuccess = {
@@ -29,7 +32,7 @@ export type LoadResult = LoadResultSuccess | LoadResultNotFound | LoadResultErro
snowpackLogger.level = 'silent';
async function load(config: RuntimeConfig, rawPathname: string | undefined): Promise {
- const { logging, snowpack, snowpackRuntime } = config;
+ const { logging, backendSnowpackRuntime, frontendSnowpack } = config;
const { astroRoot } = config.astroConfig;
const fullurl = new URL(rawPathname || '/', 'https://example.org/');
@@ -43,7 +46,8 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
// Non-Astro pages (file resources)
if (!existsSync(selectedPageLoc) && !existsSync(selectedPageMdLoc)) {
try {
- const result = await snowpack.loadUrl(reqPath);
+ console.log('loading', reqPath);
+ const result = await frontendSnowpack.loadUrl(reqPath);
// success
return {
@@ -63,7 +67,7 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
for (const url of [`/_astro/pages/${selectedPage}.astro.js`, `/_astro/pages/${selectedPage}.md.js`]) {
try {
- const mod = await snowpackRuntime.importModule(url);
+ const mod = await backendSnowpackRuntime.importModule(url);
debug(logging, 'resolve', `${reqPath} -> ${url}`);
let html = (await mod.exports.__renderPage({
request: {
@@ -128,7 +132,7 @@ interface RuntimeOptions {
logging: LogOptions;
}
-export async function createRuntime(astroConfig: AstroConfig, { logging }: RuntimeOptions): Promise {
+async function createSnowpack(astroConfig: AstroConfig, env: Record) {
const { projectRoot, astroRoot, extensions } = astroConfig;
const internalPath = new URL('./frontend/', import.meta.url);
@@ -170,23 +174,42 @@ export async function createRuntime(astroConfig: AstroConfig, { logging }: Runti
external: ['@vue/server-renderer', 'node-fetch'],
},
});
+
+ const envConfig = snowpackConfig.env || (snowpackConfig.env = {});
+ Object.assign(envConfig, env);
+
snowpack = await startSnowpackServer({
config: snowpackConfig,
lockfile: null,
});
const snowpackRuntime = snowpack.getServerRuntime();
+ return { snowpack, snowpackRuntime, snowpackConfig };
+}
+
+export async function createRuntime(astroConfig: AstroConfig, { logging }: RuntimeOptions): Promise {
+ const { snowpack: backendSnowpack, snowpackRuntime: backendSnowpackRuntime, snowpackConfig: backendSnowpackConfig } = await createSnowpack(astroConfig, {
+ astro: true,
+ });
+
+ const { snowpack: frontendSnowpack, snowpackRuntime: frontendSnowpackRuntime, snowpackConfig: frontendSnowpackConfig } = await createSnowpack(astroConfig, {
+ astro: false,
+ });
+
const runtimeConfig: RuntimeConfig = {
astroConfig,
logging,
- snowpack,
- snowpackRuntime,
- snowpackConfig,
+ backendSnowpack,
+ backendSnowpackRuntime,
+ backendSnowpackConfig,
+ frontendSnowpack,
+ frontendSnowpackRuntime,
+ frontendSnowpackConfig,
};
return {
runtimeConfig,
load: load.bind(null, runtimeConfig),
- shutdown: () => snowpack.shutdown(),
+ shutdown: () => Promise.all([backendSnowpack.shutdown(), frontendSnowpack.shutdown()]).then(() => void 0),
};
}
diff --git a/src/style-stuff.ts b/src/style-stuff.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/test/astro-fallback.test.js b/test/astro-fallback.test.js
new file mode 100644
index 000000000..2acf29f8e
--- /dev/null
+++ b/test/astro-fallback.test.js
@@ -0,0 +1,19 @@
+import { suite } from 'uvu';
+import * as assert from 'uvu/assert';
+import { doc } from './test-utils.js';
+import { setup } from './helpers.js';
+
+const Fallback = suite('Dynamic component fallback');
+
+setup(Fallback, './fixtures/astro-fallback');
+
+Fallback('Shows static content', async (context) => {
+ const result = await context.runtime.load('/');
+
+ assert.equal(result.statusCode, 200);
+
+ const $ = doc(result.contents);
+ assert.equal($('#fallback').text(), 'static');
+});
+
+Fallback.run();
diff --git a/test/fixtures/astro-fallback/astro.config.mjs b/test/fixtures/astro-fallback/astro.config.mjs
new file mode 100644
index 000000000..ac85e54d8
--- /dev/null
+++ b/test/fixtures/astro-fallback/astro.config.mjs
@@ -0,0 +1,8 @@
+export default {
+ projectRoot: '.',
+ astroRoot: './astro',
+ dist: './_site',
+ extensions: {
+ '.jsx': 'preact'
+ }
+};
diff --git a/test/fixtures/astro-fallback/astro/components/Client.jsx b/test/fixtures/astro-fallback/astro/components/Client.jsx
new file mode 100644
index 000000000..d79536e27
--- /dev/null
+++ b/test/fixtures/astro-fallback/astro/components/Client.jsx
@@ -0,0 +1,7 @@
+import { h } from 'preact';
+
+export default function(props) {
+ return (
+ {import.meta.env.astro ? 'static' : 'dynamic'}
+ );
+};
\ No newline at end of file
diff --git a/test/fixtures/astro-fallback/astro/pages/index.astro b/test/fixtures/astro-fallback/astro/pages/index.astro
new file mode 100644
index 000000000..f4f20c322
--- /dev/null
+++ b/test/fixtures/astro-fallback/astro/pages/index.astro
@@ -0,0 +1,16 @@
+---
+import Client from '../components/Client.jsx';
+
+let title = 'My Page'
+---
+
+
+
+ {title}
+
+
+ {title}
+
+
+
+
\ No newline at end of file
diff --git a/test/helpers.js b/test/helpers.js
new file mode 100644
index 000000000..c913ef912
--- /dev/null
+++ b/test/helpers.js
@@ -0,0 +1,33 @@
+import { createRuntime } from '../lib/runtime.js';
+import { loadConfig } from '../lib/config.js';
+import * as assert from 'uvu/assert';
+
+export function setup(Suite, fixturePath) {
+ let runtime, setupError;
+
+ Suite.before(async (context) => {
+ const astroConfig = await loadConfig(new URL(fixturePath, import.meta.url).pathname);
+
+ const logging = {
+ level: 'error',
+ dest: process.stderr,
+ };
+
+ try {
+ runtime = await createRuntime(astroConfig, { logging });
+ } catch (err) {
+ console.error(err);
+ setupError = err;
+ }
+
+ context.runtime = runtime;
+ });
+
+ Suite.after(async () => {
+ (await runtime) && runtime.shutdown();
+ });
+
+ Suite('No errors creating a runtime', () => {
+ assert.equal(setupError, undefined);
+ });
+}