Change astroRoot to pages (#277)

#271
This commit is contained in:
Drew Powers 2021-06-01 09:57:12 -06:00 committed by GitHub
parent fad2662486
commit addd67d244
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 76 additions and 62 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Rename `astroConfig` to `pages` in config. Docs updated.

View file

@ -6,8 +6,8 @@ To configure Astro, add an `astro.config.mjs` file in the root of your project.
export default {
/** Where to resolve all URLs relative to. Useful if you have a monorepo project. */
projectRoot: '.',
/** Path to Astro components, pages, and data */
astroRoot: './src',
/** Path to your sites pages (routes) */
pages: './src/pages',
/** When running `astro build`, path to final static output */
dist: './dist',
/** A folder of static files Astro will copy to the root. Useful for favicons, images, and other files that dont need processing. */

View file

@ -1,10 +1,10 @@
export default {
projectRoot: '.',
pages: './src/pages',
public: './public',
dist: './dist',
buildOptions: {
sitemap: true,
site: 'https://mysite.dev/', // change
},
astroRoot: './src',
};

View file

@ -1,6 +1,6 @@
export default {
projectRoot: '.',
astroRoot: './src',
pages: './src/pages',
dist: './dist',
public: './public',
extensions: {

View file

@ -3,7 +3,7 @@ import type { ImportSpecifier, ImportDefaultSpecifier, ImportNamespaceSpecifier
export interface AstroConfigRaw {
dist: string;
projectRoot: string;
astroRoot: string;
pages: string;
public: string;
jsx?: string;
}
@ -17,7 +17,7 @@ export interface AstroMarkdownOptions {
export interface AstroConfig {
dist: string;
projectRoot: URL;
astroRoot: URL;
pages: URL;
public: URL;
renderers?: string[];
/** Options for rendering markdown content */

View file

@ -41,9 +41,8 @@ function isRemote(url: string) {
/** The primary build action */
export async function build(astroConfig: AstroConfig, logging: LogOptions = defaultLogging): Promise<0 | 1> {
const { projectRoot, astroRoot } = astroConfig;
const { projectRoot, pages: pagesRoot } = astroConfig;
const dist = new URL(astroConfig.dist + '/', projectRoot);
const pageRoot = new URL('./pages/', astroRoot);
const buildState: BuildOutput = {};
const depTree: BundleMap = {};
const timer: Record<string, number> = {};
@ -70,7 +69,7 @@ export async function build(astroConfig: AstroConfig, logging: LogOptions = defa
* Source files are built in parallel and stored in memory. Most assets are also gathered here, too.
*/
timer.build = performance.now();
const pages = await allPages(pageRoot);
const pages = await allPages(pagesRoot);
info(logging, 'build', yellow('! building pages...'));
const release = trapWarn(); // Vue also console.warns, this silences it.
await Promise.all(

View file

@ -22,9 +22,9 @@ export function getPageType(filepath: URL): 'collection' | 'static' {
}
/** Build collection */
export async function buildCollectionPage({ astroConfig, filepath, logging, mode, runtime, site, resolvePackageUrl, buildState }: PageBuildOptions): Promise<void> {
const pagesPath = new URL('./pages/', astroConfig.astroRoot);
const srcURL = filepath.pathname.replace(pagesPath.pathname, '/');
export async function buildCollectionPage({ astroConfig, filepath, runtime, site, buildState }: PageBuildOptions): Promise<void> {
const { pages: pagesRoot } = astroConfig;
const srcURL = filepath.pathname.replace(pagesRoot.pathname, '/');
const outURL = srcURL.replace(/\$([^.]+)\.astro$/, '$1');
const builtURLs = new Set<string>(); // !important: internal cache that prevents building the same URLs
@ -89,8 +89,8 @@ export async function buildCollectionPage({ astroConfig, filepath, logging, mode
/** Build static page */
export async function buildStaticPage({ astroConfig, buildState, filepath, runtime }: PageBuildOptions): Promise<void> {
const pagesPath = new URL('./pages/', astroConfig.astroRoot);
const url = filepath.pathname.replace(pagesPath.pathname, '/').replace(/(index)?\.(astro|md)$/, '');
const { pages: pagesRoot } = astroConfig;
const url = filepath.pathname.replace(pagesRoot.pathname, '/').replace(/(index)?\.(astro|md)$/, '');
// build page in parallel
await Promise.all([

View file

@ -1,6 +1,7 @@
import type { AstroConfig } from '../@types/astro';
import { performance } from 'perf_hooks';
import fs from 'fs';
import path from 'path';
import { URL } from 'url';
@ -16,28 +17,43 @@ export function canonicalURL(url: string, base?: string): URL {
/** Resolve final output URL */
export function getDistPath(specifier: string, { astroConfig, srcPath }: { astroConfig: AstroConfig; srcPath: URL }): string {
if (specifier[0] === '/') return specifier; // assume absolute URLs are correct
const pagesDir = path.join(astroConfig.astroRoot.pathname, 'pages');
const { pages: pagesRoot, projectRoot } = astroConfig;
const fileLoc = path.posix.join(path.posix.dirname(srcPath.pathname), specifier);
const projectLoc = path.posix.relative(astroConfig.astroRoot.pathname, fileLoc);
const fileLoc = new URL(specifier, srcPath);
const projectLoc = fileLoc.pathname.replace(projectRoot.pathname, '');
const isPage = fileLoc.includes(pagesDir);
const isPage = fileLoc.pathname.includes(pagesRoot.pathname);
// if this lives above src/pages, return that URL
if (isPage) {
const [, publicURL] = projectLoc.split(pagesDir);
const [, publicURL] = projectLoc.split(pagesRoot.pathname);
return publicURL || '/index.html'; // if this is missing, this is the root
}
// otherwise, return /_astro/* url
return '/_astro/' + projectLoc;
}
/** Given a final output URL, guess at src path (may be inaccurate) */
export function getSrcPath(url: string, { astroConfig }: { astroConfig: AstroConfig }): URL {
if (url.startsWith('/_astro/')) {
return new URL(url.replace(/^\/_astro\//, ''), astroConfig.astroRoot);
/** Given a final output URL, guess at src path (may be inaccurate; only for non-pages) */
export function getSrcPath(distURL: string, { astroConfig }: { astroConfig: AstroConfig }): URL {
if (distURL.startsWith('/_astro/')) {
return new URL('.' + distURL.replace(/^\/_astro\//, ''), astroConfig.projectRoot);
} else if (distURL === '/index.html') {
return new URL('./index.astro', astroConfig.pages);
}
let srcFile = url.replace(/^\//, '').replace(/\/index.html$/, '.astro');
return new URL('./pages/' + srcFile, astroConfig.astroRoot);
const possibleURLs = [
new URL('.' + distURL, astroConfig.public), // public asset
new URL('.' + distURL.replace(/([^\/])+\/d+\/index.html/, '$$1.astro'), astroConfig.pages), // collection page
new URL('.' + distURL.replace(/\/index\.html$/, '.astro'), astroConfig.pages), // page
// TODO: Astro pages (this isnt currently used for that lookup)
];
// if this is in public/ or pages/, return that
for (const possibleURL of possibleURLs) {
if (fs.existsSync(possibleURL)) return possibleURL;
}
// otherwise resolve relative to project
return new URL('.' + distURL, astroConfig.projectRoot);
}
/** Stop timer & format time for profiling */

View file

@ -141,14 +141,13 @@ const PlainExtensions = new Set(['.js', '.jsx', '.ts', '.tsx']);
/** Generate Astro-friendly component import */
function getComponentWrapper(_name: string, { url, importSpecifier }: ComponentInfo, opts: GetComponentWrapperOptions) {
const { astroConfig, filename } = opts;
const { astroRoot } = astroConfig;
const currFileUrl = new URL(`file://${filename}`);
const [name, kind] = _name.split(':');
const getComponentUrl = () => {
const componentExt = path.extname(url);
const ext = PlainExtensions.has(componentExt) ? '.js' : `${componentExt}.js`;
const outUrl = new URL(url, currFileUrl);
return '/_astro/' + path.posix.relative(astroRoot.pathname, outUrl.pathname).replace(/\.[^.]+$/, ext);
return '/_astro/' + outUrl.href.replace(astroConfig.projectRoot.href, '').replace(/\.[^.]+$/, ext);
};
const getComponentExport = () => {
switch (importSpecifier.type) {

View file

@ -1,13 +1,11 @@
import type { Transformer } from '../../@types/transformer';
import type { CompileOptions } from '../../@types/compiler';
import path from 'path';
import { getAttrValue, setAttrValue } from '../../ast.js';
/** Transform <script type="module"> */
export default function ({ compileOptions, filename }: { compileOptions: CompileOptions; filename: string; fileID: string }): Transformer {
const { astroConfig } = compileOptions;
const { astroRoot } = astroConfig;
const fileUrl = new URL(`file://${filename}`);
return {
@ -31,8 +29,7 @@ export default function ({ compileOptions, filename }: { compileOptions: Compile
}
const srcUrl = new URL(src, fileUrl);
const fromAstroRoot = path.posix.relative(astroRoot.pathname, srcUrl.pathname);
const absoluteUrl = `/_astro/${fromAstroRoot}`;
const absoluteUrl = `/_astro/${srcUrl.href.replace(astroConfig.projectRoot.href, '')}`;
setAttrValue(node.attributes, 'src', absoluteUrl);
},
},

View file

@ -14,7 +14,7 @@ function validateConfig(config: any): void {
if (typeof config !== 'object') throw new Error(`[config] Expected object, received ${typeof config}`);
// strings
for (const key of ['projectRoot', 'astroRoot', 'dist', 'public']) {
for (const key of ['projectRoot', 'pages', 'dist', 'public']) {
if (config[key] !== undefined && config[key] !== null && typeof config[key] !== 'string') {
throw new Error(`[config] ${key}: ${JSON.stringify(config[key])}\n Expected string, received ${type(config[key])}.`);
}
@ -54,7 +54,7 @@ function configDefaults(userConfig?: any): any {
const config: any = { ...(userConfig || {}) };
if (!config.projectRoot) config.projectRoot = '.';
if (!config.astroRoot) config.astroRoot = './src';
if (!config.pages) config.pages = './src/pages';
if (!config.dist) config.dist = './dist';
if (!config.public) config.public = './public';
if (!config.devOptions) config.devOptions = {};
@ -72,7 +72,7 @@ function normalizeConfig(userConfig: any, root: string): AstroConfig {
const fileProtocolRoot = `file://${root}/`;
config.projectRoot = new URL(config.projectRoot + '/', fileProtocolRoot);
config.astroRoot = new URL(config.astroRoot + '/', fileProtocolRoot);
config.pages = new URL(config.pages + '/', fileProtocolRoot);
config.public = new URL(config.public + '/', fileProtocolRoot);
return config as AstroConfig;

View file

@ -50,7 +50,7 @@ snowpackLogger.level = 'silent';
/** Pass a URL to Astro to resolve and build */
async function load(config: RuntimeConfig, rawPathname: string | undefined): Promise<LoadResult> {
const { logging, backendSnowpackRuntime, frontendSnowpack } = config;
const { astroRoot, buildOptions, devOptions } = config.astroConfig;
const { pages: pagesRoot, buildOptions, devOptions } = config.astroConfig;
let origin = buildOptions.site ? new URL(buildOptions.site).origin : `http://localhost:${devOptions.port}`;
const fullurl = new URL(rawPathname || '/', origin);
@ -58,7 +58,7 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
const reqPath = decodeURI(fullurl.pathname);
info(logging, 'access', reqPath);
const searchResult = searchForPage(fullurl, astroRoot);
const searchResult = searchForPage(fullurl, pagesRoot);
if (searchResult.statusCode === 404) {
try {
const result = await frontendSnowpack.loadUrl(reqPath);
@ -274,7 +274,7 @@ const DEFAULT_RENDERERS = ['@astrojs/renderer-svelte', '@astrojs/renderer-react'
/** Create a new Snowpack instance to power Astro */
async function createSnowpack(astroConfig: AstroConfig, options: CreateSnowpackOptions) {
const { projectRoot, astroRoot, renderers = DEFAULT_RENDERERS } = astroConfig;
const { projectRoot, pages: pagesRoot, renderers = DEFAULT_RENDERERS } = astroConfig;
const { env, mode, resolvePackageUrl, target } = options;
const internalPath = new URL('./frontend/', import.meta.url);
@ -294,14 +294,12 @@ async function createSnowpack(astroConfig: AstroConfig, options: CreateSnowpackO
};
const mountOptions = {
[fileURLToPath(astroRoot)]: '/_astro',
[fileURLToPath(pagesRoot)]: '/_astro/pages',
...(existsSync(astroConfig.public) ? { [fileURLToPath(astroConfig.public)]: '/' } : {}),
[fileURLToPath(internalPath)]: '/_astro_internal',
[fileURLToPath(projectRoot)]: '/_astro', // must be last (greediest)
};
if (existsSync(astroConfig.public)) {
mountOptions[fileURLToPath(astroConfig.public)] = '/';
}
// Tailwind: IDK what this does but it makes JIT work 🤷‍♂️
if (astroConfig.devOptions.tailwindConfig) {
(process.env as any).TAILWIND_DISABLE_TOUCH = true;

View file

@ -9,9 +9,9 @@ interface PageLocation {
snowpackURL: string;
}
/** findAnyPage and return the _astro candidate for snowpack */
function findAnyPage(candidates: Array<string>, astroRoot: URL): PageLocation | false {
function findAnyPage(candidates: Array<string>, pagesRoot: URL): PageLocation | false {
for (let candidate of candidates) {
const url = new URL(`./pages/${candidate}`, astroRoot);
const url = new URL(`./${candidate}`, pagesRoot);
if (existsSync(url)) {
return {
fileURL: url,
@ -39,14 +39,14 @@ type SearchResult =
};
/** Given a URL, attempt to locate its source file (similar to Snowpacks load()) */
export function searchForPage(url: URL, astroRoot: URL): SearchResult {
export function searchForPage(url: URL, pagesRoot: URL): SearchResult {
const reqPath = decodeURI(url.pathname);
const base = reqPath.substr(1);
// Try to find index.astro/md paths
if (reqPath.endsWith('/')) {
const candidates = [`${base}index.astro`, `${base}index.md`];
const location = findAnyPage(candidates, astroRoot);
const location = findAnyPage(candidates, pagesRoot);
if (location) {
return {
statusCode: 200,
@ -57,7 +57,7 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult {
} else {
// Try to find the page by its name.
const candidates = [`${base}.astro`, `${base}.md`];
let location = findAnyPage(candidates, astroRoot);
let location = findAnyPage(candidates, pagesRoot);
if (location) {
return {
statusCode: 200,
@ -69,7 +69,7 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult {
// Try to find name/index.astro/md
const candidates = [`${base}/index.astro`, `${base}/index.md`];
const location = findAnyPage(candidates, astroRoot);
const location = findAnyPage(candidates, pagesRoot);
if (location) {
return {
statusCode: 301,
@ -81,7 +81,7 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult {
// Try and load collections (but only for non-extension files)
const hasExt = !!path.extname(reqPath);
if (!location && !hasExt) {
const collection = loadCollection(reqPath, astroRoot);
const collection = loadCollection(reqPath, pagesRoot);
if (collection) {
return {
statusCode: 200,
@ -109,8 +109,8 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult {
}
/** load a collection route */
function loadCollection(url: string, astroRoot: URL): { currentPage?: number; location: PageLocation } | undefined {
const pages = glob('**/$*.astro', { cwd: path.join(fileURLToPath(astroRoot), 'pages'), filesOnly: true });
function loadCollection(url: string, pagesRoot: URL): { currentPage?: number; location: PageLocation } | undefined {
const pages = glob('**/$*.astro', { cwd: fileURLToPath(pagesRoot), filesOnly: true });
for (const pageURL of pages) {
const reqURL = new RegExp('^/' + pageURL.replace(/\$([^/]+)\.astro/, '$1') + '/?(.*)');
const match = url.match(reqURL);
@ -127,7 +127,7 @@ function loadCollection(url: string, astroRoot: URL): { currentPage?: number; lo
}
return {
location: {
fileURL: new URL(`./pages/${pageURL}`, astroRoot),
fileURL: new URL(`./${pageURL}`, pagesRoot),
snowpackURL: `/_astro/pages/${pageURL}.js`,
},
currentPage,

View file

@ -39,9 +39,9 @@ Markdown('Bundles client-side JS for prod', async (context) => {
await context.build();
const complexHtml = await context.readFile('/complex/index.html');
assert.match(complexHtml, `import("/_astro/components/Counter.js"`);
assert.match(complexHtml, `import("/_astro/src/components/Counter.js"`);
const counterJs = await context.readFile('/_astro/components/Counter.js');
const counterJs = await context.readFile('/_astro/src/components/Counter.js');
assert.ok(counterJs, 'Counter.jsx is bundled for prod');
});

View file

@ -19,12 +19,12 @@ setup(StylesSSR, './fixtures/astro-styles-ssr');
StylesSSR('Has <link> tags', async ({ runtime }) => {
const MUST_HAVE_LINK_TAGS = [
'/_astro/components/ReactCSS.css',
'/_astro/components/ReactModules.module.css',
'/_astro/components/SvelteScoped.svelte.css',
'/_astro/components/VueCSS.vue.css',
'/_astro/components/VueModules.vue.css',
'/_astro/components/VueScoped.vue.css',
'/_astro/src/components/ReactCSS.css',
'/_astro/src/components/ReactModules.module.css',
'/_astro/src/components/SvelteScoped.svelte.css',
'/_astro/src/components/VueCSS.vue.css',
'/_astro/src/components/VueModules.vue.css',
'/_astro/src/components/VueScoped.vue.css',
];
const result = await runtime.load('/');

View file

@ -1,6 +1,6 @@
export default {
// projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project.
// astroRoot: './src', // Path to Astro components, pages, and data
// 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 dont need processing.
extensions: {

View file

@ -1,6 +1,6 @@
export default {
// projectRoot: '.', // Where to resolve all URLs relative to. Useful if you have a monorepo project.
// astroRoot: './src', // Path to Astro components, pages, and data
// 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 dont need processing.
extensions: {