0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

Add runtime mode (#48)

This commit is contained in:
Drew Powers 2021-04-01 10:20:57 -06:00 committed by GitHub
parent 7c10d563f2
commit f6a7ac67be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 48 additions and 32 deletions

View file

@ -33,3 +33,5 @@ export interface CompileResult {
contents: string; contents: string;
css?: string; css?: string;
} }
export type RuntimeMode = 'development' | 'production';

View file

@ -1,9 +1,10 @@
import type { LogOptions } from '../logger'; import type { LogOptions } from '../logger';
import type { AstroConfig, ValidExtensionPlugins } from './astro'; import type { AstroConfig, RuntimeMode, ValidExtensionPlugins } from './astro';
export interface CompileOptions { export interface CompileOptions {
logging: LogOptions; logging: LogOptions;
resolve: (p: string) => Promise<string>; resolve: (p: string) => Promise<string>;
astroConfig: AstroConfig; astroConfig: AstroConfig;
extensions?: Record<string, ValidExtensionPlugins>; extensions?: Record<string, ValidExtensionPlugins>;
mode: RuntimeMode;
} }

View file

@ -1,4 +1,5 @@
import type { TemplateNode } from '../parser/interfaces'; import type { TemplateNode } from '../parser/interfaces';
import type { CompileOptions } from './compiler';
export type VisitorFn = (node: TemplateNode, parent: TemplateNode, type: string, index: number) => void; export type VisitorFn = (node: TemplateNode, parent: TemplateNode, type: string, index: number) => void;
@ -14,3 +15,9 @@ export interface Optimizer {
}; };
finalize: () => Promise<void>; finalize: () => Promise<void>;
} }
export interface OptimizeOptions {
compileOptions: CompileOptions;
filename: string;
fileID: string;
}

View file

@ -1,4 +1,4 @@
import type { AstroConfig } from './@types/astro'; import type { AstroConfig, RuntimeMode } from './@types/astro';
import type { LogOptions } from './logger'; import type { LogOptions } from './logger';
import type { LoadResult } from './runtime'; import type { LoadResult } from './runtime';
@ -60,14 +60,15 @@ export async function build(astroConfig: AstroConfig): Promise<0 | 1> {
dest: defaultLogDestination, dest: defaultLogDestination,
}; };
const runtime = await createRuntime(astroConfig, { logging: runtimeLogging }); const mode: RuntimeMode = 'production';
const runtime = await createRuntime(astroConfig, { mode, logging: runtimeLogging });
const { runtimeConfig } = runtime; const { runtimeConfig } = runtime;
const { backendSnowpack: snowpack } = runtimeConfig; const { backendSnowpack: snowpack } = runtimeConfig;
const resolve = (pkgName: string) => snowpack.getUrlForPackage(pkgName); const resolve = (pkgName: string) => snowpack.getUrlForPackage(pkgName);
const imports = new Set<string>(); const imports = new Set<string>();
const statics = new Set<string>(); const statics = new Set<string>();
const collectImportsOptions = { astroConfig, logging, resolve }; const collectImportsOptions = { astroConfig, logging, resolve, mode };
for (const pathname of await allPages(pageRoot)) { for (const pathname of await allPages(pageRoot)) {
const filepath = new URL(`file://${pathname}`); const filepath = new URL(`file://${pathname}`);

View file

@ -1,4 +1,4 @@
import type { AstroConfig, ValidExtensionPlugins } from '../@types/astro'; import type { AstroConfig, RuntimeMode, ValidExtensionPlugins } from '../@types/astro';
import type { ImportDeclaration } from '@babel/types'; import type { ImportDeclaration } from '@babel/types';
import type { InputOptions, OutputOptions } from 'rollup'; import type { InputOptions, OutputOptions } from 'rollup';
import type { AstroRuntime } from '../runtime'; import type { AstroRuntime } from '../runtime';
@ -62,9 +62,10 @@ interface CollectDynamic {
astroConfig: AstroConfig; astroConfig: AstroConfig;
resolve: (s: string) => Promise<string>; resolve: (s: string) => Promise<string>;
logging: LogOptions; logging: LogOptions;
mode: RuntimeMode;
} }
export async function collectDynamicImports(filename: URL, { astroConfig, logging, resolve }: CollectDynamic) { export async function collectDynamicImports(filename: URL, { astroConfig, logging, resolve, mode }: CollectDynamic) {
const imports = new Set<string>(); const imports = new Set<string>();
// Only astro files // Only astro files
@ -89,6 +90,7 @@ export async function collectDynamicImports(filename: URL, { astroConfig, loggin
astroConfig, astroConfig,
resolve, resolve,
logging, logging,
mode,
}, },
}); });

View file

@ -1,5 +1,5 @@
import type { LogOptions } from '../logger.js'; import type { CompileResult, TransformResult } from '../@types/astro';
import type { AstroConfig, CompileResult, TransformResult } from '../@types/astro'; import type { CompileOptions } from '../@types/compiler.js';
import path from 'path'; import path from 'path';
import micromark from 'micromark'; import micromark from 'micromark';
@ -13,12 +13,6 @@ import { encodeMarkdown } from '../micromark-encode.js';
import { optimize } from './optimize/index.js'; import { optimize } from './optimize/index.js';
import { codegen } from './codegen.js'; import { codegen } from './codegen.js';
interface CompileOptions {
astroConfig: AstroConfig;
logging: LogOptions;
resolve: (p: string) => Promise<string>;
}
function internalImport(internalPath: string) { function internalImport(internalPath: string) {
return `/_astro_internal/${internalPath}`; return `/_astro_internal/${internalPath}`;
} }

View file

@ -1,6 +1,5 @@
import type { Ast, TemplateNode } from '../../parser/interfaces'; import type { Ast, TemplateNode } from '../../parser/interfaces';
import type { CompileOptions } from '../../@types/compiler'; import type { NodeVisitor, OptimizeOptions, Optimizer, VisitorFn } from '../../@types/optimizer';
import type { NodeVisitor, Optimizer, VisitorFn } from '../../@types/optimizer';
import { walk } from 'estree-walker'; import { walk } from 'estree-walker';
@ -69,12 +68,6 @@ function walkAstWithVisitors(tmpl: TemplateNode, collection: VisitorCollection)
}); });
} }
interface OptimizeOptions {
compileOptions: CompileOptions;
filename: string;
fileID: string;
}
export async function optimize(ast: Ast, opts: OptimizeOptions) { export async function optimize(ast: Ast, opts: OptimizeOptions) {
const htmlVisitors = createVisitorCollection(); const htmlVisitors = createVisitorCollection();
const cssVisitors = createVisitorCollection(); const cssVisitors = createVisitorCollection();

View file

@ -4,7 +4,8 @@ import autoprefixer from 'autoprefixer';
import postcss from 'postcss'; import postcss from 'postcss';
import findUp from 'find-up'; import findUp from 'find-up';
import sass from 'sass'; import sass from 'sass';
import { Optimizer } from '../../@types/optimizer'; import { RuntimeMode } from '../../@types/astro';
import { OptimizeOptions, Optimizer } from '../../@types/optimizer';
import type { TemplateNode } from '../../parser/interfaces'; import type { TemplateNode } from '../../parser/interfaces';
import astroScopedStyles from './postcss-scoped-styles/index.js'; import astroScopedStyles from './postcss-scoped-styles/index.js';
@ -25,9 +26,6 @@ const getStyleType: Map<string, StyleType> = new Map([
['text/scss', 'scss'], ['text/scss', 'scss'],
]); ]);
const SASS_OPTIONS: Partial<sass.Options> = {
outputStyle: process.env.NODE_ENV === 'production' ? 'compressed' : undefined,
};
/** HTML tags that should never get scoped classes */ /** HTML tags that should never get scoped classes */
const NEVER_SCOPED_TAGS = new Set<string>(['html', 'head', 'body', 'script', 'style', 'link', 'meta']); const NEVER_SCOPED_TAGS = new Set<string>(['html', 'head', 'body', 'script', 'style', 'link', 'meta']);
@ -50,8 +48,15 @@ export interface StyleTransformResult {
// cache node_modules resolutions for each run. saves looking up the same directory over and over again. blown away on exit. // cache node_modules resolutions for each run. saves looking up the same directory over and over again. blown away on exit.
const nodeModulesMiniCache = new Map<string, string>(); const nodeModulesMiniCache = new Map<string, string>();
export interface TransformStyleOptions {
type?: string;
filename: string;
scopedClass: string;
mode: RuntimeMode;
}
/** Convert styles to scoped CSS */ /** Convert styles to scoped CSS */
async function transformStyle(code: string, { type, filename, scopedClass }: { type?: string; filename: string; scopedClass: string }): Promise<StyleTransformResult> { async function transformStyle(code: string, { type, filename, scopedClass, mode }: TransformStyleOptions): Promise<StyleTransformResult> {
let styleType: StyleType = 'css'; // important: assume CSS as default let styleType: StyleType = 'css'; // important: assume CSS as default
if (type) { if (type) {
styleType = getStyleType.get(type) || styleType; styleType = getStyleType.get(type) || styleType;
@ -80,7 +85,13 @@ async function transformStyle(code: string, { type, filename, scopedClass }: { t
} }
case 'sass': case 'sass':
case 'scss': { case 'scss': {
css = sass.renderSync({ ...SASS_OPTIONS, data: code, includePaths }).css.toString('utf8'); css = sass
.renderSync({
outputStyle: mode === 'production' ? 'compressed' : undefined,
data: code,
includePaths,
})
.css.toString('utf8');
break; break;
} }
default: { default: {
@ -96,7 +107,7 @@ async function transformStyle(code: string, { type, filename, scopedClass }: { t
} }
/** Style optimizer */ /** Style optimizer */
export default function ({ filename, fileID }: { filename: string; fileID: string }): Optimizer { export default function optimizeStyles({ compileOptions, filename, fileID }: OptimizeOptions): Optimizer {
const styleNodes: TemplateNode[] = []; // <style> tags to be updated const styleNodes: TemplateNode[] = []; // <style> tags to be updated
const styleTransformPromises: Promise<StyleTransformResult>[] = []; // async style transform results to be finished in finalize(); const styleTransformPromises: Promise<StyleTransformResult>[] = []; // async style transform results to be finished in finalize();
const scopedClass = `astro-${hashFromFilename(fileID)}`; // this *should* generate same hash from fileID every time const scopedClass = `astro-${hashFromFilename(fileID)}`; // this *should* generate same hash from fileID every time
@ -118,6 +129,7 @@ export default function ({ filename, fileID }: { filename: string; fileID: strin
type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined, type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined,
filename, filename,
scopedClass, scopedClass,
mode: compileOptions.mode,
}) })
); );
return; return;
@ -164,6 +176,7 @@ export default function ({ filename, fileID }: { filename: string; fileID: strin
type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined, type: (langAttr && langAttr.value[0] && langAttr.value[0].data) || undefined,
filename, filename,
scopedClass, scopedClass,
mode: compileOptions.mode,
}) })
); );
}, },

View file

@ -21,7 +21,7 @@ const logging: LogOptions = {
export default async function (astroConfig: AstroConfig) { export default async function (astroConfig: AstroConfig) {
const { projectRoot } = astroConfig; const { projectRoot } = astroConfig;
const runtime = await createRuntime(astroConfig, { logging }); const runtime = await createRuntime(astroConfig, { mode: 'development', logging });
const server = http.createServer(async (req, res) => { const server = http.createServer(async (req, res) => {
const result = await runtime.load(req.url); const result = await runtime.load(req.url);

View file

@ -1,5 +1,5 @@
import type { SnowpackDevServer, ServerRuntime as SnowpackServerRuntime, SnowpackConfig } from 'snowpack'; import type { SnowpackDevServer, ServerRuntime as SnowpackServerRuntime, SnowpackConfig } from 'snowpack';
import type { AstroConfig } from './@types/astro'; import type { AstroConfig, RuntimeMode } from './@types/astro';
import type { LogOptions } from './logger'; import type { LogOptions } from './logger';
import type { CompileError } from './parser/utils/error.js'; import type { CompileError } from './parser/utils/error.js';
import { debug, info } from './logger.js'; import { debug, info } from './logger.js';
@ -10,6 +10,7 @@ import { loadConfiguration, logger as snowpackLogger, startServer as startSnowpa
interface RuntimeConfig { interface RuntimeConfig {
astroConfig: AstroConfig; astroConfig: AstroConfig;
logging: LogOptions; logging: LogOptions;
mode: RuntimeMode;
backendSnowpack: SnowpackDevServer; backendSnowpack: SnowpackDevServer;
backendSnowpackRuntime: SnowpackServerRuntime; backendSnowpackRuntime: SnowpackServerRuntime;
backendSnowpackConfig: SnowpackConfig; backendSnowpackConfig: SnowpackConfig;
@ -129,6 +130,7 @@ export interface AstroRuntime {
} }
interface RuntimeOptions { interface RuntimeOptions {
mode: RuntimeMode;
logging: LogOptions; logging: LogOptions;
} }
@ -187,7 +189,7 @@ async function createSnowpack(astroConfig: AstroConfig, env: Record<string, any>
return { snowpack, snowpackRuntime, snowpackConfig }; return { snowpack, snowpackRuntime, snowpackConfig };
} }
export async function createRuntime(astroConfig: AstroConfig, { logging }: RuntimeOptions): Promise<AstroRuntime> { export async function createRuntime(astroConfig: AstroConfig, { mode, logging }: RuntimeOptions): Promise<AstroRuntime> {
const { snowpack: backendSnowpack, snowpackRuntime: backendSnowpackRuntime, snowpackConfig: backendSnowpackConfig } = await createSnowpack(astroConfig, { const { snowpack: backendSnowpack, snowpackRuntime: backendSnowpackRuntime, snowpackConfig: backendSnowpackConfig } = await createSnowpack(astroConfig, {
astro: true, astro: true,
}); });
@ -199,6 +201,7 @@ export async function createRuntime(astroConfig: AstroConfig, { logging }: Runti
const runtimeConfig: RuntimeConfig = { const runtimeConfig: RuntimeConfig = {
astroConfig, astroConfig,
logging, logging,
mode,
backendSnowpack, backendSnowpack,
backendSnowpackRuntime, backendSnowpackRuntime,
backendSnowpackConfig, backendSnowpackConfig,