Skip to content

Commit

Permalink
Support custom mode (#12150)
Browse files Browse the repository at this point in the history
Co-authored-by: Sarah Rainsberger <[email protected]>
  • Loading branch information
bluwy and sarah11918 authored Oct 17, 2024
1 parent 2649a73 commit 93351bc
Show file tree
Hide file tree
Showing 33 changed files with 297 additions and 83 deletions.
31 changes: 31 additions & 0 deletions .changeset/sixty-coins-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
'astro': minor
---

Adds support for passing values other than `"production"` or `"development"` to the `--mode` flag (e.g. `"staging"`, `"testing"`, or any custom value) to change the value of `import.meta.env.MODE` or the loaded `.env` file. This allows you take advantage of Vite's [mode](https://vite.dev/guide/env-and-mode#modes) feature.

Also adds a new `--devOutput` flag for `astro build` that will output a development-based build.

Note that changing the `mode` does not change the kind of code transform handled by Vite and Astro:

- In `astro dev`, Astro will transform code with debug information.
- In `astro build`, Astro will transform code with the most optimized output and removes debug information.
- In `astro build --devOutput` (new flag), Astro will transform code with debug information like in `astro dev`.

This enables various usecases like:

```bash
# Run the dev server connected to a "staging" API
astro dev --mode staging

# Build a site that connects to a "staging" API
astro build --mode staging

# Build a site that connects to a "production" API with additional debug information
astro build --devOutput

# Build a site that connects to a "testing" API
astro build --mode testing
```

The different modes can be used to load different `.env` files, e.g. `.env.staging` or `.env.production`, which can be customized for each environment, for example with different `API_URL` environment variable values.
3 changes: 0 additions & 3 deletions packages/astro/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# astro


## 5.0.0-beta.5

### Minor Changes
Expand Down Expand Up @@ -988,7 +987,6 @@

If you are using this service, and cannot migrate to the base Sharp image service, a third-party extraction of the previous service is available here: https://github.com/Princesseuh/astro-image-service-squoosh


## 5.0.0-alpha.0

### Major Changes
Expand Down Expand Up @@ -1064,7 +1062,6 @@
- Updated dependencies [[`83a2a64`](https://github.com/withastro/astro/commit/83a2a648418ad30f4eb781d1c1b5f2d8a8ac846e)]:
- @astrojs/[email protected]


## 4.16.6

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/assets/internal.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isRemotePath } from '@astrojs/internal-helpers/path';
import { AstroError, AstroErrorData } from '../core/errors/index.js';
import type { AstroConfig } from '../types/public/config.js';
import { DEFAULT_HASH_PROPS } from './consts.js';
Expand All @@ -11,7 +12,6 @@ import {
} from './types.js';
import { isESMImportedImage, isRemoteImage, resolveSrc } from './utils/imageKind.js';
import { inferRemoteSize } from './utils/remoteProbe.js';
import {isRemotePath} from "@astrojs/internal-helpers/path";

export async function getConfiguredImageService(): Promise<ImageService> {
if (!globalThis?.astroAsset?.imageService) {
Expand Down
16 changes: 7 additions & 9 deletions packages/astro/src/assets/vite-plugin-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
removeBase,
removeQueryString,
} from '../core/path.js';
import type { AstroPluginOptions, AstroSettings } from '../types/astro.js';
import type { AstroSettings } from '../types/astro.js';
import { VALID_INPUT_FORMATS, VIRTUAL_MODULE_ID, VIRTUAL_SERVICE_ID } from './consts.js';
import type { ImageTransform } from './types.js';
import { getAssetsPrefix } from './utils/getAssetsPrefix.js';
Expand Down Expand Up @@ -89,12 +89,10 @@ const addStaticImageFactory = (
};
};

export default function assets({
settings,
mode,
}: AstroPluginOptions & { mode: string }): vite.Plugin[] {
export default function assets({ settings }: { settings: AstroSettings }): vite.Plugin[] {
let resolvedConfig: vite.ResolvedConfig;
let shouldEmitFile = false;
let isBuild = false;

globalThis.astroAsset = {
referencedImages: new Set(),
Expand All @@ -104,6 +102,9 @@ export default function assets({
// Expose the components and different utilities from `astro:assets`
{
name: 'astro:assets',
config(_, env) {
isBuild = env.command === 'build';
},
async resolveId(id) {
if (id === VIRTUAL_SERVICE_ID) {
return await this.resolve(settings.config.image.service.entrypoint);
Expand Down Expand Up @@ -143,10 +144,7 @@ export default function assets({
}
},
buildStart() {
if (mode != 'build') {
return;
}

if (!isBuild) return;
globalThis.astroAsset.addStaticImage = addStaticImageFactory(settings);
},
// In build, rewrite paths to ESM imported images in code to their final location
Expand Down
7 changes: 6 additions & 1 deletion packages/astro/src/cli/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export async function build({ flags }: BuildOptions) {
tables: {
Flags: [
['--outDir <directory>', `Specify the output directory for the build.`],
['--mode', `Specify the mode of the project. Defaults to "production".`],
[
'--devOutput',
'Output a development-based build similar to code transformed in `astro dev`.',
],
[
'--force',
'Clear the content layer and content collection cache, forcing a full rebuild.',
Expand All @@ -28,5 +33,5 @@ export async function build({ flags }: BuildOptions) {

const inlineConfig = flagsToAstroInlineConfig(flags);

await _build(inlineConfig);
await _build(inlineConfig, { devOutput: !!flags.devOutput });
}
1 change: 1 addition & 0 deletions packages/astro/src/cli/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export async function dev({ flags }: DevOptions) {
usage: '[...flags]',
tables: {
Flags: [
['--mode', `Specify the mode of the project. Defaults to "development".`],
['--port', `Specify which port to run on. Defaults to 4321.`],
['--host', `Listen on all addresses, including LAN and public addresses.`],
['--host <custom-address>', `Expose on a network IP address at <custom-address>`],
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/cli/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig {
return {
// Inline-only configs
configFile: typeof flags.config === 'string' ? flags.config : undefined,
mode: typeof flags.mode === 'string' ? (flags.mode as AstroInlineConfig['mode']) : undefined,
mode: typeof flags.mode === 'string' ? flags.mode : undefined,
logLevel: flags.verbose ? 'debug' : flags.silent ? 'silent' : undefined,
force: flags.force ? true : undefined,

Expand Down
11 changes: 5 additions & 6 deletions packages/astro/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { UserConfig as ViteUserConfig } from 'vite';
import type { UserConfig as ViteUserConfig, UserConfigFn as ViteUserConfigFn } from 'vite';
import { Logger } from '../core/logger/core.js';
import { createRouteManifest } from '../core/routing/index.js';
import type { AstroInlineConfig, AstroUserConfig } from '../types/public/config.js';
Expand All @@ -11,11 +11,11 @@ export function defineConfig(config: AstroUserConfig) {
export function getViteConfig(
userViteConfig: ViteUserConfig,
inlineAstroConfig: AstroInlineConfig = {},
) {
): ViteUserConfigFn {
// Return an async Vite config getter which exposes a resolved `mode` and `command`
return async ({ mode, command }: { mode: 'dev'; command: 'serve' | 'build' }) => {
return async ({ mode, command }) => {
// Vite `command` is `serve | build`, but Astro uses `dev | build`
const cmd = command === 'serve' ? 'dev' : command;
const cmd = command === 'serve' ? 'dev' : 'build';

// Use dynamic import to avoid pulling in deps unless used
const [
Expand Down Expand Up @@ -46,13 +46,12 @@ export function getViteConfig(
const devSSRManifest = createDevelopmentManifest(settings);
const viteConfig = await createVite(
{
mode,
plugins: [
// Initialize the content listener
astroContentListenPlugin({ settings, logger, fs }),
],
},
{ settings, logger, mode, sync: false, manifest, ssrManifest: devSSRManifest },
{ settings, command: cmd, logger, mode, sync: false, manifest, ssrManifest: devSSRManifest },
);
await runHookConfigDone({ settings, logger });
return mergeConfig(viteConfig, userViteConfig);
Expand Down
6 changes: 1 addition & 5 deletions packages/astro/src/content/vite-plugin-content-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ import {
import { hasContentFlag } from './utils.js';

export function astroContentAssetPropagationPlugin({
mode,
settings,
}: {
mode: string;
settings: AstroSettings;
}): Plugin {
let devModuleLoader: ModuleLoader;
Expand Down Expand Up @@ -67,9 +65,7 @@ export function astroContentAssetPropagationPlugin({
}
},
configureServer(server) {
if (mode === 'dev') {
devModuleLoader = createViteLoader(server);
}
devModuleLoader = createViteLoader(server);
},
async transform(_, id, options) {
if (hasContentFlag(id, PROPAGATED_ASSET_FLAG)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function astroContentVirtualModPlugin({
name: 'astro-content-virtual-mod-plugin',
enforce: 'pre',
configResolved(config) {
IS_DEV = config.mode === 'development';
IS_DEV = !config.isProduction;
dataStoreFile = getDataStoreFile(settings, IS_DEV);
},
async resolveId(id) {
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export class App {
return AppPipeline.create(manifestData, {
logger: this.#logger,
manifest: this.#manifest,
mode: 'production',
runtimeMode: 'production',
renderers: this.#manifest.renderers,
defaultRoutes: createDefaultRoutes(this.#manifest),
resolve: async (specifier: string) => {
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/app/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export class AppPipeline extends Pipeline {
{
logger,
manifest,
mode,
runtimeMode,
renderers,
resolve,
serverLike,
Expand All @@ -25,7 +25,7 @@ export class AppPipeline extends Pipeline {
AppPipeline,
| 'logger'
| 'manifest'
| 'mode'
| 'runtimeMode'
| 'renderers'
| 'resolve'
| 'serverLike'
Expand All @@ -36,7 +36,7 @@ export class AppPipeline extends Pipeline {
const pipeline = new AppPipeline(
logger,
manifest,
mode,
runtimeMode,
renderers,
resolve,
serverLike,
Expand Down
6 changes: 3 additions & 3 deletions packages/astro/src/core/base-pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export abstract class Pipeline {
readonly logger: Logger,
readonly manifest: SSRManifest,
/**
* "development" or "production"
* "development" or "production" only
*/
readonly mode: RuntimeMode,
readonly runtimeMode: RuntimeMode,
readonly renderers: SSRLoadedRenderer[],
readonly resolve: (s: string) => Promise<string>,
/**
Expand All @@ -51,7 +51,7 @@ export abstract class Pipeline {
readonly compressHTML = manifest.compressHTML,
readonly i18n = manifest.i18n,
readonly middleware = manifest.middleware,
readonly routeCache = new RouteCache(logger, mode),
readonly routeCache = new RouteCache(logger, runtimeMode),
/**
* Used for `Astro.site`.
*/
Expand Down
30 changes: 20 additions & 10 deletions packages/astro/src/core/build/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,15 @@ import { collectPagesData } from './page-data.js';
import { staticBuild, viteBuild } from './static-build.js';
import type { StaticBuildOptions } from './types.js';
import { getTimeStat } from './util.js';

export interface BuildOptions {
/**
* Output a development-based build similar to code transformed in `astro dev`. This
* can be useful to test build-only issues with additional debugging information included.
*
* @default false
*/
devOutput?: boolean;
/**
* Teardown the compiler WASM instance after build. This can improve performance when
* building once, but may cause a performance hit if building multiple times in a row.
Expand All @@ -52,7 +60,7 @@ export default async function build(
inlineConfig: AstroInlineConfig,
options: BuildOptions = {},
): Promise<void> {
ensureProcessNodeEnv('production');
ensureProcessNodeEnv(options.devOutput ? 'development' : 'production');
applyPolyfill();
const logger = createNodeLogger(inlineConfig);
const { userConfig, astroConfig } = await resolveConfig(inlineConfig, 'build');
Expand All @@ -67,29 +75,31 @@ export default async function build(
const builder = new AstroBuilder(settings, {
...options,
logger,
mode: inlineConfig.mode,
mode: inlineConfig.mode ?? 'production',
runtimeMode: options.devOutput ? 'development' : 'production',
});
await builder.run();
}

interface AstroBuilderOptions extends BuildOptions {
logger: Logger;
mode?: RuntimeMode;
mode: string;
runtimeMode: RuntimeMode;
}

class AstroBuilder {
private settings: AstroSettings;
private logger: Logger;
private mode: RuntimeMode = 'production';
private mode: string;
private runtimeMode: RuntimeMode;
private origin: string;
private manifest: ManifestData;
private timer: Record<string, number>;
private teardownCompiler: boolean;

constructor(settings: AstroSettings, options: AstroBuilderOptions) {
if (options.mode) {
this.mode = options.mode;
}
this.mode = options.mode;
this.runtimeMode = options.runtimeMode;
this.settings = settings;
this.logger = options.logger;
this.teardownCompiler = options.teardownCompiler ?? true;
Expand Down Expand Up @@ -127,7 +137,6 @@ class AstroBuilder {

const viteConfig = await createVite(
{
mode: this.mode,
server: {
hmr: false,
middlewareMode: true,
Expand All @@ -136,7 +145,7 @@ class AstroBuilder {
{
settings: this.settings,
logger: this.logger,
mode: 'build',
mode: this.mode,
command: 'build',
sync: false,
manifest: this.manifest,
Expand All @@ -145,6 +154,7 @@ class AstroBuilder {

const { syncInternal } = await import('../sync/index.js');
await syncInternal({
mode: this.mode,
settings: this.settings,
logger,
fs,
Expand Down Expand Up @@ -193,7 +203,7 @@ class AstroBuilder {
settings: this.settings,
logger: this.logger,
manifest: this.manifest,
mode: this.mode,
runtimeMode: this.runtimeMode,
origin: this.origin,
pageNames,
teardownCompiler: this.teardownCompiler,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class BuildPipeline extends Pipeline {
super(
options.logger,
manifest,
options.mode,
options.runtimeMode,
manifest.renderers,
resolve,
serverLike,
Expand Down
2 changes: 0 additions & 2 deletions packages/astro/src/core/build/static-build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ async function ssrBuild(
const { lastVitePlugins, vitePlugins } = await container.runBeforeHook('server', input);
const viteBuildConfig: vite.InlineConfig = {
...viteConfig,
mode: viteConfig.mode || 'production',
logLevel: viteConfig.logLevel ?? 'error',
build: {
target: 'esnext',
Expand Down Expand Up @@ -269,7 +268,6 @@ async function clientBuild(

const viteBuildConfig: vite.InlineConfig = {
...viteConfig,
mode: viteConfig.mode || 'production',
build: {
target: 'esnext',
...viteConfig.build,
Expand Down
Loading

0 comments on commit 93351bc

Please sign in to comment.