[ci] format

This commit is contained in:
matthewp 2022-07-18 15:35:14 +00:00 committed by fredkbot
parent 3acb9ec264
commit b282cdb21f
6 changed files with 71 additions and 65 deletions

View file

@ -15,7 +15,7 @@ export async function getStylesForURL(
const importedCssUrls = new Set<string>(); const importedCssUrls = new Set<string>();
const importedStylesMap = new Map<string, string>(); const importedStylesMap = new Map<string, string>();
for await(const importedModule of crawlGraph(viteServer, viteID(filePath), true)) { for await (const importedModule of crawlGraph(viteServer, viteID(filePath), true)) {
const ext = path.extname(importedModule.url).toLowerCase(); const ext = path.extname(importedModule.url).toLowerCase();
if (STYLE_EXTENSIONS.has(ext)) { if (STYLE_EXTENSIONS.has(ext)) {
if ( if (

View file

@ -16,8 +16,8 @@ import { render as coreRender } from '../core.js';
import { RouteCache } from '../route-cache.js'; import { RouteCache } from '../route-cache.js';
import { collectMdMetadata } from '../util.js'; import { collectMdMetadata } from '../util.js';
import { getStylesForURL } from './css.js'; import { getStylesForURL } from './css.js';
import { getScriptsForURL } from './scripts.js';
import { resolveClientDevPath } from './resolve.js'; import { resolveClientDevPath } from './resolve.js';
import { getScriptsForURL } from './scripts.js';
export interface SSROptions { export interface SSROptions {
/** an instance of the AstroConfig */ /** an instance of the AstroConfig */

View file

@ -1,26 +1,26 @@
import type { AstroConfig, SSRElement } from '../../../@types/astro';
import type { ModuleInfo } from 'rollup'; import type { ModuleInfo } from 'rollup';
import type { PluginMetadata as AstroPluginMetadata } from '../../../vite-plugin-astro/types';
import vite from 'vite';
import slash from 'slash'; import slash from 'slash';
import { fileURLToPath } from 'url';
import vite from 'vite';
import type { AstroConfig, SSRElement } from '../../../@types/astro';
import type { PluginMetadata as AstroPluginMetadata } from '../../../vite-plugin-astro/types';
import { viteID } from '../../util.js'; import { viteID } from '../../util.js';
import { createModuleScriptElementWithSrc } from '../ssr-element.js'; import { createModuleScriptElementWithSrc } from '../ssr-element.js';
import { crawlGraph } from './vite.js'; import { crawlGraph } from './vite.js';
import { fileURLToPath } from 'url';
export async function getScriptsForURL( export async function getScriptsForURL(
filePath: URL, filePath: URL,
astroConfig: AstroConfig, astroConfig: AstroConfig,
viteServer: vite.ViteDevServer, viteServer: vite.ViteDevServer
): Promise<Set<SSRElement>> { ): Promise<Set<SSRElement>> {
const elements = new Set<SSRElement>(); const elements = new Set<SSRElement>();
const rootID = viteID(filePath); const rootID = viteID(filePath);
let rootProjectFolder = slash(fileURLToPath(astroConfig.root)); let rootProjectFolder = slash(fileURLToPath(astroConfig.root));
const modInfo = viteServer.pluginContainer.getModuleInfo(rootID); const modInfo = viteServer.pluginContainer.getModuleInfo(rootID);
addHoistedScripts(elements, modInfo, rootProjectFolder); addHoistedScripts(elements, modInfo, rootProjectFolder);
for await(const moduleNode of crawlGraph(viteServer, rootID, true)) { for await (const moduleNode of crawlGraph(viteServer, rootID, true)) {
const id = moduleNode.id; const id = moduleNode.id;
if(id) { if (id) {
const info = viteServer.pluginContainer.getModuleInfo(id); const info = viteServer.pluginContainer.getModuleInfo(id);
addHoistedScripts(elements, info, rootProjectFolder); addHoistedScripts(elements, info, rootProjectFolder);
} }
@ -29,14 +29,18 @@ export async function getScriptsForURL(
return elements; return elements;
} }
function addHoistedScripts(set: Set<SSRElement>, info: ModuleInfo | null, rootProjectFolder: string) { function addHoistedScripts(
if(!info?.meta?.astro) { set: Set<SSRElement>,
info: ModuleInfo | null,
rootProjectFolder: string
) {
if (!info?.meta?.astro) {
return; return;
} }
let id = info.id; let id = info.id;
const astro = info?.meta?.astro as AstroPluginMetadata['astro']; const astro = info?.meta?.astro as AstroPluginMetadata['astro'];
for(let i = 0; i < astro.scripts.length; i++) { for (let i = 0; i < astro.scripts.length; i++) {
const scriptId = `${id}?astro&type=script&index=${i}&lang.ts`; const scriptId = `${id}?astro&type=script&index=${i}&lang.ts`;
const element = createModuleScriptElementWithSrc(scriptId); const element = createModuleScriptElementWithSrc(scriptId);
set.add(element); set.add(element);

View file

@ -1,31 +1,31 @@
import vite from 'vite';
import npath from 'path'; import npath from 'path';
import vite from 'vite';
import { unwrapId } from '../../util.js'; import { unwrapId } from '../../util.js';
/** /**
* List of file extensions signalling we can (and should) SSR ahead-of-time * List of file extensions signalling we can (and should) SSR ahead-of-time
* See usage below * See usage below
*/ */
const fileExtensionsToSSR = new Set(['.astro', '.md']); const fileExtensionsToSSR = new Set(['.astro', '.md']);
/** recursively crawl the module graph to get all style files imported by parent id */ /** recursively crawl the module graph to get all style files imported by parent id */
export async function * crawlGraph( export async function* crawlGraph(
viteServer: vite.ViteDevServer, viteServer: vite.ViteDevServer,
_id: string, _id: string,
isFile: boolean, isFile: boolean,
scanned = new Set<string>() scanned = new Set<string>()
) : AsyncGenerator<vite.ModuleNode, void, unknown> { ): AsyncGenerator<vite.ModuleNode, void, unknown> {
const id = unwrapId(_id); const id = unwrapId(_id);
const importedModules = new Set<vite.ModuleNode>(); const importedModules = new Set<vite.ModuleNode>();
const moduleEntriesForId = isFile const moduleEntriesForId = isFile
? // If isFile = true, then you are at the root of your module import tree. ? // If isFile = true, then you are at the root of your module import tree.
// The `id` arg is a filepath, so use `getModulesByFile()` to collect all // The `id` arg is a filepath, so use `getModulesByFile()` to collect all
// nodes for that file. This is needed for advanced imports like Tailwind. // nodes for that file. This is needed for advanced imports like Tailwind.
viteServer.moduleGraph.getModulesByFile(id) ?? new Set() viteServer.moduleGraph.getModulesByFile(id) ?? new Set()
: // Otherwise, you are following an import in the module import tree. : // Otherwise, you are following an import in the module import tree.
// You are safe to use getModuleById() here because Vite has already // You are safe to use getModuleById() here because Vite has already
// resolved the correct `id` for you, by creating the import you followed here. // resolved the correct `id` for you, by creating the import you followed here.
new Set([viteServer.moduleGraph.getModuleById(id)]); new Set([viteServer.moduleGraph.getModuleById(id)]);
// Collect all imported modules for the module(s). // Collect all imported modules for the module(s).
for (const entry of moduleEntriesForId) { for (const entry of moduleEntriesForId) {
@ -45,7 +45,7 @@ export async function * crawlGraph(
const { pathname } = new URL(`file://${importedModule.id}`); const { pathname } = new URL(`file://${importedModule.id}`);
if (fileExtensionsToSSR.has(npath.extname(pathname))) { if (fileExtensionsToSSR.has(npath.extname(pathname))) {
const mod = viteServer.moduleGraph.getModuleById(importedModule.id); const mod = viteServer.moduleGraph.getModuleById(importedModule.id);
if(!mod?.ssrModule) { if (!mod?.ssrModule) {
await viteServer.ssrLoadModule(importedModule.id); await viteServer.ssrLoadModule(importedModule.id);
} }
} }
@ -63,6 +63,6 @@ export async function * crawlGraph(
} }
yield importedModule; yield importedModule;
yield * crawlGraph(viteServer, importedModule.id, false, scanned); yield* crawlGraph(viteServer, importedModule.id, false, scanned);
} }
} }

View file

@ -16,45 +16,45 @@ describe('Environment Variables', () => {
before(async () => { before(async () => {
await fixture.build(); await fixture.build();
}); });
it('builds without throwing', async () => { it('builds without throwing', async () => {
expect(true).to.equal(true); expect(true).to.equal(true);
}); });
it('does render public env and private env', async () => { it('does render public env and private env', async () => {
let indexHtml = await fixture.readFile('/index.html'); let indexHtml = await fixture.readFile('/index.html');
expect(indexHtml).to.include('CLUB_33'); expect(indexHtml).to.include('CLUB_33');
expect(indexHtml).to.include('BLUE_BAYOU'); expect(indexHtml).to.include('BLUE_BAYOU');
}); });
it('does render destructured public env and private env', async () => { it('does render destructured public env and private env', async () => {
let indexHtml = await fixture.readFile('/destructured/index.html'); let indexHtml = await fixture.readFile('/destructured/index.html');
expect(indexHtml).to.include('CLUB_33'); expect(indexHtml).to.include('CLUB_33');
expect(indexHtml).to.include('BLUE_BAYOU'); expect(indexHtml).to.include('BLUE_BAYOU');
}); });
it('does render builtin SITE env', async () => { it('does render builtin SITE env', async () => {
let indexHtml = await fixture.readFile('/index.html'); let indexHtml = await fixture.readFile('/index.html');
expect(indexHtml).to.include('http://example.com'); expect(indexHtml).to.include('http://example.com');
}); });
it('does render destructured builtin SITE env', async () => { it('does render destructured builtin SITE env', async () => {
let indexHtml = await fixture.readFile('/destructured/index.html'); let indexHtml = await fixture.readFile('/destructured/index.html');
expect(indexHtml).to.include('http://example.com'); expect(indexHtml).to.include('http://example.com');
}); });
it('does render builtin BASE_URL env', async () => { it('does render builtin BASE_URL env', async () => {
let indexHtml = await fixture.readFile('/index.html'); let indexHtml = await fixture.readFile('/index.html');
expect(indexHtml).to.include('/blog'); expect(indexHtml).to.include('/blog');
}); });
it('includes public env in client-side JS', async () => { it('includes public env in client-side JS', async () => {
let dirs = await fixture.readdir('/'); let dirs = await fixture.readdir('/');
let found = false; let found = false;
// Look in all of the .js files to see if the public env is inlined. // Look in all of the .js files to see if the public env is inlined.
// Testing this way prevents hardcoding expected js files. // Testing this way prevents hardcoding expected js files.
// If we find it in any of them that's good enough to know its working. // If we find it in any of them that's good enough to know its working.
@ -68,14 +68,14 @@ describe('Environment Variables', () => {
} }
}) })
); );
expect(found).to.equal(true, 'found the public env variable in the JS build'); expect(found).to.equal(true, 'found the public env variable in the JS build');
}); });
it('does not include private env in client-side JS', async () => { it('does not include private env in client-side JS', async () => {
let dirs = await fixture.readdir('/'); let dirs = await fixture.readdir('/');
let found = false; let found = false;
// Look in all of the .js files to see if the public env is inlined. // Look in all of the .js files to see if the public env is inlined.
// Testing this way prevents hardcoding expected js files. // Testing this way prevents hardcoding expected js files.
// If we find it in any of them that's good enough to know its NOT working. // If we find it in any of them that's good enough to know its NOT working.
@ -89,7 +89,7 @@ describe('Environment Variables', () => {
} }
}) })
); );
expect(found).to.equal(false, 'found the private env variable in the JS build'); expect(found).to.equal(false, 'found the private env variable in the JS build');
}); });
}); });

View file

@ -19,99 +19,99 @@ describe('Scripts (hoisted and not)', () => {
before(async () => { before(async () => {
await fixture.build(); await fixture.build();
}); });
it('Moves external scripts up', async () => { it('Moves external scripts up', async () => {
const html = await fixture.readFile('/external/index.html'); const html = await fixture.readFile('/external/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);
expect($('head script[type="module"]:not([src="/regular_script.js"])')).to.have.lengthOf(1); expect($('head script[type="module"]:not([src="/regular_script.js"])')).to.have.lengthOf(1);
expect($('body script')).to.have.lengthOf(0); expect($('body script')).to.have.lengthOf(0);
}); });
it('Moves inline scripts up', async () => { it('Moves inline scripts up', async () => {
const html = await fixture.readFile('/inline/index.html'); const html = await fixture.readFile('/inline/index.html');
const $ = cheerio.load(html); const $ = cheerio.load(html);
expect($('head script[type="module"]')).to.have.lengthOf(1); expect($('head script[type="module"]')).to.have.lengthOf(1);
expect($('body script')).to.have.lengthOf(0); expect($('body script')).to.have.lengthOf(0);
}); });
it('Inline page builds the scripts to a single bundle', async () => { it('Inline page builds the scripts to a single bundle', async () => {
// Inline page // Inline page
let inline = await fixture.readFile('/inline/index.html'); let inline = await fixture.readFile('/inline/index.html');
let $ = cheerio.load(inline); let $ = cheerio.load(inline);
let $el = $('script'); let $el = $('script');
// test 1: Just one entry module // test 1: Just one entry module
expect($el).to.have.lengthOf(1); expect($el).to.have.lengthOf(1);
// test 2: attr removed // test 2: attr removed
expect($el.attr('data-astro')).to.equal(undefined); expect($el.attr('data-astro')).to.equal(undefined);
expect($el.attr('src')).to.equal(undefined); expect($el.attr('src')).to.equal(undefined);
const inlineEntryJS = $el.text(); const inlineEntryJS = $el.text();
// test 3: the JS exists // test 3: the JS exists
expect(inlineEntryJS).to.be.ok; expect(inlineEntryJS).to.be.ok;
// test 4: Inline imported JS is included // test 4: Inline imported JS is included
expect(inlineEntryJS).to.contain( expect(inlineEntryJS).to.contain(
'I AM IMPORTED INLINE', 'I AM IMPORTED INLINE',
'The inline imported JS is included in the bundle' 'The inline imported JS is included in the bundle'
); );
}); });
it("Inline scripts that are shared by multiple pages create chunks, and aren't inlined into the HTML", async () => { it("Inline scripts that are shared by multiple pages create chunks, and aren't inlined into the HTML", async () => {
let html = await fixture.readFile('/inline-shared-one/index.html'); let html = await fixture.readFile('/inline-shared-one/index.html');
let $ = cheerio.load(html); let $ = cheerio.load(html);
expect($('script')).to.have.lengthOf(1); expect($('script')).to.have.lengthOf(1);
expect($('script').attr('src')).to.not.equal(undefined); expect($('script').attr('src')).to.not.equal(undefined);
}); });
it('External page builds the hoisted scripts to a single bundle', async () => { it('External page builds the hoisted scripts to a single bundle', async () => {
let external = await fixture.readFile('/external/index.html'); let external = await fixture.readFile('/external/index.html');
let $ = cheerio.load(external); let $ = cheerio.load(external);
// test 1: there are two scripts // test 1: there are two scripts
expect($('script')).to.have.lengthOf(2); expect($('script')).to.have.lengthOf(2);
let el = $('script').get(1); let el = $('script').get(1);
expect($(el).attr('src')).to.equal(undefined, 'This should have been inlined'); expect($(el).attr('src')).to.equal(undefined, 'This should have been inlined');
let externalEntryJS = $(el).text(); let externalEntryJS = $(el).text();
// test 2: the JS exists // test 2: the JS exists
expect(externalEntryJS).to.be.ok; expect(externalEntryJS).to.be.ok;
}); });
it('External page using non-hoist scripts that are modules are built standalone', async () => { it('External page using non-hoist scripts that are modules are built standalone', async () => {
let external = await fixture.readFile('/external-no-hoist/index.html'); let external = await fixture.readFile('/external-no-hoist/index.html');
let $ = cheerio.load(external); let $ = cheerio.load(external);
// test 1: there is 1 scripts // test 1: there is 1 scripts
expect($('script')).to.have.lengthOf(1); expect($('script')).to.have.lengthOf(1);
// test 2: inside assets // test 2: inside assets
let entryURL = $('script').attr('src'); let entryURL = $('script').attr('src');
expect(entryURL.includes('assets/')).to.equal(true); expect(entryURL.includes('assets/')).to.equal(true);
}); });
it('External page using non-hoist scripts that are not modules are built standalone', async () => { it('External page using non-hoist scripts that are not modules are built standalone', async () => {
let external = await fixture.readFile('/external-no-hoist-classic/index.html'); let external = await fixture.readFile('/external-no-hoist-classic/index.html');
let $ = cheerio.load(external); let $ = cheerio.load(external);
// test 1: there is 1 scripts // test 1: there is 1 scripts
expect($('script')).to.have.lengthOf(1); expect($('script')).to.have.lengthOf(1);
// test 2: inside assets // test 2: inside assets
let entryURL = $('script').attr('src'); let entryURL = $('script').attr('src');
expect(entryURL.includes('assets/')).to.equal(true); expect(entryURL.includes('assets/')).to.equal(true);
}); });
it('Scripts added via Astro.glob are hoisted', async () => { it('Scripts added via Astro.glob are hoisted', async () => {
let glob = await fixture.readFile('/glob/index.html'); let glob = await fixture.readFile('/glob/index.html');
let $ = cheerio.load(glob); let $ = cheerio.load(glob);
expect($('script[type="module"]').length).to.be.greaterThan(0); expect($('script[type="module"]').length).to.be.greaterThan(0);
}); });
}); });
@ -135,10 +135,12 @@ describe('Scripts (hoisted and not)', () => {
let found = 0; let found = 0;
let moduleScripts = $('[type=module]'); let moduleScripts = $('[type=module]');
moduleScripts.each((i, el) => { moduleScripts.each((i, el) => {
if($(el).attr('src').includes('Glob/GlobComponent.astro?astro&type=script&index=0&lang.ts')) { if (
$(el).attr('src').includes('Glob/GlobComponent.astro?astro&type=script&index=0&lang.ts')
) {
found++; found++;
} }
}) });
expect(found).to.equal(1); expect(found).to.equal(1);
}); });
}); });