summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Drew Powers <1369770+drwpow@users.noreply.github.com> 2021-11-30 11:54:37 -0700
committerGravatar GitHub <noreply@github.com> 2021-11-30 11:54:37 -0700
commit03cabc51714a8963eeacbe896da22f47159d9d59 (patch)
treeed0dde863fac0183f16931e7494515a2ea7451e8
parent606fa81b94bf5045c37d8d8ee6caf2a49ef1998a (diff)
downloadastro-03cabc51714a8963eeacbe896da22f47159d9d59.tar.gz
astro-03cabc51714a8963eeacbe896da22f47159d9d59.tar.zst
astro-03cabc51714a8963eeacbe896da22f47159d9d59.zip
Fix Windows dev script proxying (#2052)
* Add tests for script proxying * Fix Windows script proxying #2053
-rw-r--r--packages/astro/src/core/dev/index.ts10
-rw-r--r--packages/astro/src/core/ssr/css.ts20
-rw-r--r--packages/astro/src/core/ssr/index.ts3
-rw-r--r--packages/astro/src/core/util.ts6
-rw-r--r--packages/astro/test/fixtures/solid-component/src/pages/index.astro6
-rw-r--r--packages/astro/test/fixtures/svelte-component/src/pages/typescript.astro2
-rw-r--r--packages/astro/test/react-component.test.js171
-rw-r--r--packages/astro/test/solid-component.test.js54
-rw-r--r--packages/astro/test/svelte-component.test.js39
-rw-r--r--packages/astro/test/vue-component.test.js60
10 files changed, 237 insertions, 134 deletions
diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts
index f1326d30f..c2f2bca94 100644
--- a/packages/astro/src/core/dev/index.ts
+++ b/packages/astro/src/core/dev/index.ts
@@ -21,7 +21,6 @@ import { createVite } from '../create-vite.js';
import * as msg from './messages.js';
import notFoundTemplate, { subpathNotUsedTemplate } from './template/4xx.js';
import serverErrorTemplate from './template/5xx.js';
-import { viteifyURL } from '../util.js';
export interface DevOptions {
logging: LogOptions;
@@ -329,14 +328,7 @@ export class AstroDevServer {
res.end();
} catch (err: any) {
const statusCode = 500;
- const mod = filePath && this.viteServer.moduleGraph.getModuleById(viteifyURL(filePath));
- if (mod) {
- for (const m of [mod, ...mod.importedModules]) {
- this.viteServer.moduleGraph.invalidateModule(m);
- }
- } else {
- this.viteServer.moduleGraph.invalidateAll();
- }
+ await this.viteServer.moduleGraph.invalidateAll();
this.viteServer.ws.send({ type: 'error', err });
let html = serverErrorTemplate({
statusCode,
diff --git a/packages/astro/src/core/ssr/css.ts b/packages/astro/src/core/ssr/css.ts
index afbd53461..0f2ffb00a 100644
--- a/packages/astro/src/core/ssr/css.ts
+++ b/packages/astro/src/core/ssr/css.ts
@@ -9,27 +9,23 @@ export const STYLE_EXTENSIONS = new Set(['.css', '.pcss', '.postcss', '.scss', '
/** find unloaded styles */
export function getStylesForURL(filePath: URL, viteServer: vite.ViteDevServer): Set<string> {
const css = new Set<string>();
- const { idToModuleMap } = viteServer.moduleGraph;
const rootID = viteifyURL(filePath);
- const moduleGraph = idToModuleMap.get(rootID);
- if (!moduleGraph) return css;
// recursively crawl module graph to get all style files imported by parent id
function crawlCSS(entryModule: string, scanned = new Set<string>()) {
- const moduleName = idToModuleMap.get(entryModule);
- if (!moduleName) return;
- if (!moduleName.id) return;
+ const moduleName = viteServer.moduleGraph.urlToModuleMap.get(entryModule);
+ if (!moduleName || !moduleName.id) return;
// mark the entrypoint as scanned to avoid an infinite loop
- scanned.add(moduleName.id);
+ scanned.add(moduleName.url);
for (const importedModule of moduleName.importedModules) {
- if (!importedModule.id || scanned.has(importedModule.id)) continue;
- const ext = path.extname(importedModule.id.toLowerCase());
+ if (!importedModule.url || scanned.has(importedModule.url)) continue;
+ const ext = path.extname(importedModule.url.toLowerCase());
if (STYLE_EXTENSIONS.has(ext)) {
- css.add(importedModule.url || importedModule.id); // if style file, add to list
+ css.add(importedModule.url); // if style file, add to list
} else {
- crawlCSS(importedModule.id, scanned); // otherwise, crawl file to see if it imports any CSS
+ crawlCSS(importedModule.url, scanned); // otherwise, crawl file to see if it imports any CSS
}
- scanned.add(importedModule.id);
+ scanned.add(importedModule.url);
}
}
crawlCSS(rootID);
diff --git a/packages/astro/src/core/ssr/index.ts b/packages/astro/src/core/ssr/index.ts
index 5aad47b4b..af9702c9b 100644
--- a/packages/astro/src/core/ssr/index.ts
+++ b/packages/astro/src/core/ssr/index.ts
@@ -266,7 +266,8 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO
// run transformIndexHtml() in dev to run Vite dev transformations
if (mode === 'development') {
- html = await viteServer.transformIndexHtml(viteifyURL(filePath), html, pathname);
+ const relativeURL = filePath.href.replace(astroConfig.projectRoot.href, '/');
+ html = await viteServer.transformIndexHtml(relativeURL, html, pathname);
}
// inject <!doctype html> if missing (TODO: is a more robust check needed for comments, etc.?)
diff --git a/packages/astro/src/core/util.ts b/packages/astro/src/core/util.ts
index 45ada43e2..e05a76801 100644
--- a/packages/astro/src/core/util.ts
+++ b/packages/astro/src/core/util.ts
@@ -77,9 +77,9 @@ export function resolveDependency(dep: string, astroConfig: AstroConfig) {
* Vite-ify URL
* Given a file URL, return an ID that matches Vite’s module graph. Needed for resolution and stack trace fixing.
* Must match the following format:
- * Linux/Mac: /Users/astro/code/my-project/src/pages/index.astro
- * Windows: C:/Users/astro/code/my-project/src/pages/index.astro
+ * Linux/Mac: /@fs/Users/astro/code/my-project/src/pages/index.astro
+ * Windows: /@fs/C:/Users/astro/code/my-project/src/pages/index.astro
*/
export function viteifyURL(filePath: URL): string {
- return slash(fileURLToPath(filePath));
+ return `/@fs${filePath.pathname}`;
}
diff --git a/packages/astro/test/fixtures/solid-component/src/pages/index.astro b/packages/astro/test/fixtures/solid-component/src/pages/index.astro
index b489bda08..73a9e2d3a 100644
--- a/packages/astro/test/fixtures/solid-component/src/pages/index.astro
+++ b/packages/astro/test/fixtures/solid-component/src/pages/index.astro
@@ -4,6 +4,8 @@ import Hello from '../components/Hello.jsx';
<html>
<head><title>Solid</title></head>
<body>
- <div><Hello /></div>
+ <div>
+ <Hello client:load />
+ </div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/packages/astro/test/fixtures/svelte-component/src/pages/typescript.astro b/packages/astro/test/fixtures/svelte-component/src/pages/typescript.astro
index 229ec763b..d6b416756 100644
--- a/packages/astro/test/fixtures/svelte-component/src/pages/typescript.astro
+++ b/packages/astro/test/fixtures/svelte-component/src/pages/typescript.astro
@@ -19,7 +19,7 @@ import TypeScript from '../components/TypeScript.svelte'
</head>
<body>
<main>
- <TypeScript message="Hello, TypeScript" />
+ <TypeScript message="Hello, TypeScript" client:load />
</main>
</body>
</html>
diff --git a/packages/astro/test/react-component.test.js b/packages/astro/test/react-component.test.js
index 6eba570b5..c6485460f 100644
--- a/packages/astro/test/react-component.test.js
+++ b/packages/astro/test/react-component.test.js
@@ -4,98 +4,125 @@ import { loadFixture } from './test-utils.js';
let fixture;
-before(async () => {
- fixture = await loadFixture({
- projectRoot: './fixtures/react-component/',
- renderers: ['@astrojs/renderer-react', '@astrojs/renderer-vue'],
+describe('React Components', () => {
+ before(async () => {
+ fixture = await loadFixture({
+ projectRoot: './fixtures/react-component/',
+ renderers: ['@astrojs/renderer-react', '@astrojs/renderer-vue'],
+ });
});
- await fixture.build();
-});
-describe('React Components', () => {
- it('Can load React', async () => {
- const html = await fixture.readFile('/index.html');
- const $ = cheerio.load(html);
+ describe('build', () => {
+ before(async () => {
+ await fixture.build();
+ });
- // test 1: basic component renders
- expect($('#react-h2').text()).to.equal('Hello world!');
+ it('Can load React', async () => {
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
- // test 2: no reactroot
- expect($('#react-h2').attr('data-reactroot')).to.equal(undefined);
+ // test 1: basic component renders
+ expect($('#react-h2').text()).to.equal('Hello world!');
- // test 3: Can use function components
- expect($('#arrow-fn-component')).to.have.lengthOf(1);
+ // test 2: no reactroot
+ expect($('#react-h2').attr('data-reactroot')).to.equal(undefined);
- // test 4: Can use spread for components
- expect($('#component-spread-props')).to.have.lengthOf(1);
+ // test 3: Can use function components
+ expect($('#arrow-fn-component')).to.have.lengthOf(1);
- // test 5: spread props renders
- expect($('#component-spread-props').text(), 'Hello world!');
+ // test 4: Can use spread for components
+ expect($('#component-spread-props')).to.have.lengthOf(1);
- // test 6: Can use TS components
- expect($('.ts-component')).to.have.lengthOf(1);
+ // test 5: spread props renders
+ expect($('#component-spread-props').text(), 'Hello world!');
- // test 7: Can use Pure components
- expect($('#pure')).to.have.lengthOf(1);
- });
+ // test 6: Can use TS components
+ expect($('.ts-component')).to.have.lengthOf(1);
- // TODO: fix compiler bug
- it.skip('Includes reactroot on hydrating components', async () => {
- const html = await fixture.readFile('/index.html');
- const $ = cheerio.load(html);
+ // test 7: Can use Pure components
+ expect($('#pure')).to.have.lengthOf(1);
+ });
- const div = $('#research');
+ it('Can load Vue', async () => {
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
+ expect($('#vue-h2').text()).to.equal('Hasta la vista, baby');
+ });
- // test 1: has the hydration attr
- expect(div.attr('data-reactroot')).to.be.ok;
+ it('Can use a pragma comment', async () => {
+ const html = await fixture.readFile('/pragma-comment/index.html');
+ const $ = cheerio.load(html);
- // test 2: renders correctly
- expect(div.html()).to.equal('foo bar <!-- -->1');
- });
+ // test 1: rendered the PragmaComment component
+ expect($('.pragma-comment')).to.have.lengthOf(2);
+ });
- // TODO: Vite does not throw a helpful error message on window SSR
- it.skip('Throws helpful error message on window SSR', async () => {
- const html = await fixture.readFile('/window/index.html');
- expect(html).to.include(
- `[/window]
- The window object is not available during server-side rendering (SSR).
- Try using \`import.meta.env.SSR\` to write SSR-friendly code.
- https://docs.astro.build/reference/api-reference/#importmeta`
- );
- });
+ // TODO: is this still a relevant test?
+ it.skip('Includes reactroot on hydrating components', async () => {
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
- it('Can load Vue', async () => {
- const html = await fixture.readFile('/index.html');
- const $ = cheerio.load(html);
- expect($('#vue-h2').text()).to.equal('Hasta la vista, baby');
- });
+ const div = $('#research');
- // TODO: fix
- it('Can use a pragma comment', async () => {
- const html = await fixture.readFile('/pragma-comment/index.html');
- const $ = cheerio.load(html);
+ // test 1: has the hydration attr
+ expect(div.attr('data-reactroot')).to.be.ok;
- // test 1: rendered the PragmaComment component
- expect($('.pragma-comment')).to.have.lengthOf(2);
+ // test 2: renders correctly
+ expect(div.html()).to.equal('foo bar <!-- -->1');
+ });
});
- // In moving over to Vite, the jsx-runtime import is now obscured. TODO: update the method of finding this.
- it.skip('uses the new JSX transform', async () => {
- const html = await fixture.fetch('/index.html');
-
- // Grab the imports
- const exp = /import\("(.+?)"\)/g;
- let match, componentUrl;
- while ((match = exp.exec(html))) {
- if (match[1].includes('Research.js')) {
- componentUrl = match[1];
- break;
+ describe('dev', () => {
+ let devServer;
+
+ before(async () => {
+ devServer = await fixture.startDevServer();
+ });
+
+ after(async () => {
+ devServer && (await devServer.stop());
+ });
+
+ it('scripts proxy correctly', async () => {
+ const html = await fixture.fetch('/').then((res) => res.text());
+ const $ = cheerio.load(html);
+
+ for (const script of $('script').toArray()) {
+ const { src } = script.attribs;
+ if (!src) continue;
+ expect((await fixture.fetch(src)).status, `404: ${src}`).to.equal(200);
+ }
+ });
+
+ // TODO: move this to separate dev test?
+ it.skip('Throws helpful error message on window SSR', async () => {
+ const html = await fixture.fetch('/window/index.html');
+ expect(html).to.include(
+ `[/window]
+ The window object is not available during server-side rendering (SSR).
+ Try using \`import.meta.env.SSR\` to write SSR-friendly code.
+ https://docs.astro.build/reference/api-reference/#importmeta`
+ );
+ });
+
+ // In moving over to Vite, the jsx-runtime import is now obscured. TODO: update the method of finding this.
+ it.skip('uses the new JSX transform', async () => {
+ const html = await fixture.fetch('/index.html');
+
+ // Grab the imports
+ const exp = /import\("(.+?)"\)/g;
+ let match, componentUrl;
+ while ((match = exp.exec(html))) {
+ if (match[1].includes('Research.js')) {
+ componentUrl = match[1];
+ break;
+ }
}
- }
- const component = await fixture.readFile(componentUrl);
- const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime'));
+ const component = await fixture.readFile(componentUrl);
+ const jsxRuntime = component.imports.filter((i) => i.specifier.includes('jsx-runtime'));
- // test 1: react/jsx-runtime is used for the component
- expect(jsxRuntime).to.be.ok;
+ // test 1: react/jsx-runtime is used for the component
+ expect(jsxRuntime).to.be.ok;
+ });
});
});
diff --git a/packages/astro/test/solid-component.test.js b/packages/astro/test/solid-component.test.js
index da1022208..426f687bc 100644
--- a/packages/astro/test/solid-component.test.js
+++ b/packages/astro/test/solid-component.test.js
@@ -2,22 +2,50 @@ import { expect } from 'chai';
import cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
-let fixture;
+describe('Solid component', () => {
+ let fixture;
-before(async () => {
- fixture = await loadFixture({
- projectRoot: './fixtures/solid-component/',
- renderers: ['@astrojs/renderer-solid'],
+ before(async () => {
+ fixture = await loadFixture({
+ projectRoot: './fixtures/solid-component/',
+ renderers: ['@astrojs/renderer-solid'],
+ });
});
- await fixture.build();
-});
-describe('Solid component', () => {
- it('Can load a component', async () => {
- const html = await fixture.readFile('/index.html');
- const $ = cheerio.load(html);
+ describe('build', () => {
+ before(async () => {
+ await fixture.build();
+ });
+
+ it('Can load a component', async () => {
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
+
+ // test 1: Works
+ expect($('.hello')).to.have.lengthOf(1);
+ });
+ });
+
+ describe('dev', () => {
+ let devServer;
+
+ before(async () => {
+ devServer = await fixture.startDevServer();
+ });
+
+ after(async () => {
+ devServer & devServer.stop();
+ });
+
+ it('scripts proxy correctly', async () => {
+ const html = await fixture.fetch('/').then((res) => res.text());
+ const $ = cheerio.load(html);
- // test 1: Works
- expect($('.hello')).to.have.lengthOf(1);
+ for (const script of $('script').toArray()) {
+ const { src } = script.attribs;
+ if (!src) continue;
+ expect((await fixture.fetch(src)).status, `404: ${src}`).to.equal(200);
+ }
+ });
});
});
diff --git a/packages/astro/test/svelte-component.test.js b/packages/astro/test/svelte-component.test.js
index 0d79be3de..f50f24e0c 100644
--- a/packages/astro/test/svelte-component.test.js
+++ b/packages/astro/test/svelte-component.test.js
@@ -10,13 +10,42 @@ describe('Svelte component', () => {
projectRoot: './fixtures/svelte-component/',
renderers: ['@astrojs/renderer-svelte'],
});
- await fixture.build();
});
- it('Works with TypeScript', async () => {
- const html = await fixture.readFile('/typescript/index.html');
- const $ = cheerio.load(html);
+ describe('build', () => {
+ before(async () => {
+ await fixture.build();
+ });
+
+ it('Works with TypeScript', async () => {
+ const html = await fixture.readFile('/typescript/index.html');
+ const $ = cheerio.load(html);
+
+ expect($('#svelte-ts').text()).to.equal('Hello, TypeScript');
+ });
+ });
+
+ describe('dev', () => {
+ let devServer;
- expect($('#svelte-ts').text()).to.equal('Hello, TypeScript');
+ before(async () => {
+ devServer = await fixture.startDevServer();
+ });
+
+ after(async () => {
+ devServer && (await devServer.stop());
+ });
+
+ it('scripts proxy correctly', async () => {
+ const html = await fixture.fetch('/').then((res) => res.text());
+ const $ = cheerio.load(html);
+
+ for (const script of $('script').toArray()) {
+ const { src } = script.attribs;
+ if (!src) continue;
+ console.log({ src });
+ expect((await fixture.fetch(src)).status, `404: ${src}`).to.equal(200);
+ }
+ });
});
});
diff --git a/packages/astro/test/vue-component.test.js b/packages/astro/test/vue-component.test.js
index 8899782af..f375174bb 100644
--- a/packages/astro/test/vue-component.test.js
+++ b/packages/astro/test/vue-component.test.js
@@ -10,28 +10,56 @@ describe('Vue component', () => {
projectRoot: './fixtures/vue-component/',
renderers: ['@astrojs/renderer-vue'],
});
- await fixture.build();
});
- it('Can load Vue', async () => {
- const html = await fixture.readFile('/index.html');
- const $ = cheerio.load(html);
+ describe('build', () => {
+ before(async () => {
+ await fixture.build();
+ });
+
+ it('Can load Vue', async () => {
+ const html = await fixture.readFile('/index.html');
+ const $ = cheerio.load(html);
+
+ const allPreValues = $('pre')
+ .toArray()
+ .map((el) => $(el).text());
+
+ // test 1: renders all components correctly
+ expect(allPreValues).to.deep.equal(['0', '1', '10', '100', '1000']);
+
+ // test 2: renders 3 <astro-root>s
+ expect($('astro-root')).to.have.lengthOf(4);
+
+ // test 3: all <astro-root>s have uid attributes
+ expect($('astro-root[uid]')).to.have.lengthOf(4);
- const allPreValues = $('pre')
- .toArray()
- .map((el) => $(el).text());
+ // test 5: all <astro-root>s have unique uid attributes
+ const uniqueRootUIDs = $('astro-root').map((i, el) => $(el).attr('uid'));
+ expect(new Set(uniqueRootUIDs).size).to.equal(4);
+ });
+ });
+
+ describe('dev', () => {
+ let devServer;
- // test 1: renders all components correctly
- expect(allPreValues).to.deep.equal(['0', '1', '10', '100', '1000']);
+ before(async () => {
+ devServer = await fixture.startDevServer();
+ });
- // test 2: renders 3 <astro-root>s
- expect($('astro-root')).to.have.lengthOf(4);
+ after(async () => {
+ devServer && (await devServer.stop());
+ });
- // test 3: all <astro-root>s have uid attributes
- expect($('astro-root[uid]')).to.have.lengthOf(4);
+ it('scripts proxy correctly', async () => {
+ const html = await fixture.fetch('/').then((res) => res.text());
+ const $ = cheerio.load(html);
- // test 5: all <astro-root>s have unique uid attributes
- const uniqueRootUIDs = $('astro-root').map((i, el) => $(el).attr('uid'));
- expect(new Set(uniqueRootUIDs).size).to.equal(4);
+ for (const script of $('script').toArray()) {
+ const { src } = script.attribs;
+ if (!src) continue;
+ expect((await fixture.fetch(src)).status, `404: ${src}`).to.equal(200);
+ }
+ });
});
});