Add ability to specify hostname in devOptions (#733)
* Add ability to specify hostname in devOptions * Update packages/astro/test/config-hostname.test.js Co-authored-by: Caleb Jasik <calebjasik@jasik.xyz> Co-authored-by: Caleb Jasik <calebjasik@jasik.xyz>
This commit is contained in:
parent
7ad7e16633
commit
0e761b9bdf
10 changed files with 71 additions and 8 deletions
5
.changeset/good-teachers-relax.md
Normal file
5
.changeset/good-teachers-relax.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Add ability to specify hostname in devOptions
|
|
@ -29,6 +29,7 @@ export interface AstroConfig {
|
||||||
};
|
};
|
||||||
/** Options for the development server run with `astro dev`. */
|
/** Options for the development server run with `astro dev`. */
|
||||||
devOptions: {
|
devOptions: {
|
||||||
|
hostname?: string;
|
||||||
/** The port to run the dev server on. */
|
/** The port to run the dev server on. */
|
||||||
port: number;
|
port: number;
|
||||||
projectRoot?: string;
|
projectRoot?: string;
|
||||||
|
@ -42,6 +43,7 @@ export type AstroUserConfig = Omit<AstroConfig, 'buildOptions' | 'devOptions'> &
|
||||||
sitemap: boolean;
|
sitemap: boolean;
|
||||||
};
|
};
|
||||||
devOptions: {
|
devOptions: {
|
||||||
|
hostname?: string;
|
||||||
port?: number;
|
port?: number;
|
||||||
projectRoot?: string;
|
projectRoot?: string;
|
||||||
tailwindConfig?: string;
|
tailwindConfig?: string;
|
||||||
|
|
|
@ -27,6 +27,7 @@ interface CLIState {
|
||||||
options: {
|
options: {
|
||||||
projectRoot?: string;
|
projectRoot?: string;
|
||||||
sitemap?: boolean;
|
sitemap?: boolean;
|
||||||
|
hostname?: string;
|
||||||
port?: number;
|
port?: number;
|
||||||
config?: string;
|
config?: string;
|
||||||
reload?: boolean;
|
reload?: boolean;
|
||||||
|
@ -93,6 +94,7 @@ async function printVersion() {
|
||||||
function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) {
|
function mergeCLIFlags(astroConfig: AstroConfig, flags: CLIState['options']) {
|
||||||
if (typeof flags.sitemap === 'boolean') astroConfig.buildOptions.sitemap = flags.sitemap;
|
if (typeof flags.sitemap === 'boolean') astroConfig.buildOptions.sitemap = flags.sitemap;
|
||||||
if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port;
|
if (typeof flags.port === 'number') astroConfig.devOptions.port = flags.port;
|
||||||
|
if (typeof flags.hostname === 'string') astroConfig.devOptions.hostname = flags.hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Handle `astro run` command */
|
/** Handle `astro run` command */
|
||||||
|
|
|
@ -107,7 +107,8 @@ interface CompileComponentOptions {
|
||||||
/** Compiles an Astro component */
|
/** Compiles an Astro component */
|
||||||
export async function compileComponent(source: string, { compileOptions, filename, projectRoot }: CompileComponentOptions): Promise<CompileResult> {
|
export async function compileComponent(source: string, { compileOptions, filename, projectRoot }: CompileComponentOptions): Promise<CompileResult> {
|
||||||
const result = await transformFromSource(source, { compileOptions, filename, projectRoot });
|
const result = await transformFromSource(source, { compileOptions, filename, projectRoot });
|
||||||
const site = compileOptions.astroConfig.buildOptions.site || `http://localhost:${compileOptions.astroConfig.devOptions.port}`;
|
const { hostname, port } = compileOptions.astroConfig.devOptions
|
||||||
|
const site = compileOptions.astroConfig.buildOptions.site || `http://${hostname}:${port}`;
|
||||||
|
|
||||||
// return template
|
// return template
|
||||||
let moduleJavaScript = `
|
let moduleJavaScript = `
|
||||||
|
|
|
@ -43,6 +43,9 @@ function validateConfig(config: any): void {
|
||||||
if (typeof config.devOptions?.port !== 'number') {
|
if (typeof config.devOptions?.port !== 'number') {
|
||||||
throw new Error(`[config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`);
|
throw new Error(`[config] devOptions.port: Expected number, received ${type(config.devOptions?.port)}`);
|
||||||
}
|
}
|
||||||
|
if (typeof config.devOptions?.hostname !== 'string') {
|
||||||
|
throw new Error(`[config] devOptions.hostname: Expected string, received ${type(config.devOptions?.hostname)}`);
|
||||||
|
}
|
||||||
if (config.devOptions?.tailwindConfig !== undefined && typeof config.devOptions?.tailwindConfig !== 'string') {
|
if (config.devOptions?.tailwindConfig !== undefined && typeof config.devOptions?.tailwindConfig !== 'string') {
|
||||||
throw new Error(`[config] devOptions.tailwindConfig: Expected string, received ${type(config.devOptions?.tailwindConfig)}`);
|
throw new Error(`[config] devOptions.tailwindConfig: Expected string, received ${type(config.devOptions?.tailwindConfig)}`);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +62,7 @@ async function configDefaults(userConfig?: any): Promise<any> {
|
||||||
if (!config.public) config.public = './public';
|
if (!config.public) config.public = './public';
|
||||||
if (!config.devOptions) config.devOptions = {};
|
if (!config.devOptions) config.devOptions = {};
|
||||||
if (!config.devOptions.port) config.devOptions.port = await getPort({ port: getPort.makeRange(3000, 3050) });
|
if (!config.devOptions.port) config.devOptions.port = await getPort({ port: getPort.makeRange(3000, 3050) });
|
||||||
|
if (!config.devOptions.hostname) config.devOptions.hostname = 'localhost';
|
||||||
if (!config.buildOptions) config.buildOptions = {};
|
if (!config.buildOptions) config.buildOptions = {};
|
||||||
if (!config.markdownOptions) config.markdownOptions = {};
|
if (!config.markdownOptions) config.markdownOptions = {};
|
||||||
if (typeof config.buildOptions.sitemap === 'undefined') config.buildOptions.sitemap = true;
|
if (typeof config.buildOptions.sitemap === 'undefined') config.buildOptions.sitemap = true;
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { defaultLogDestination, defaultLogLevel, debug, error, info, parseError
|
||||||
import { createRuntime } from './runtime.js';
|
import { createRuntime } from './runtime.js';
|
||||||
import { stopTimer } from './build/util.js';
|
import { stopTimer } from './build/util.js';
|
||||||
|
|
||||||
const hostname = '127.0.0.1';
|
|
||||||
|
|
||||||
const logging: LogOptions = {
|
const logging: LogOptions = {
|
||||||
level: defaultLogLevel,
|
level: defaultLogLevel,
|
||||||
dest: defaultLogDestination,
|
dest: defaultLogDestination,
|
||||||
|
@ -50,7 +48,8 @@ export default async function dev(astroConfig: AstroConfig) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 404: {
|
case 404: {
|
||||||
const fullurl = new URL(req.url || '/', astroConfig.buildOptions.site || `http://localhost${astroConfig.devOptions.port}`);
|
const { hostname, port } = astroConfig.devOptions;
|
||||||
|
const fullurl = new URL(req.url || '/', astroConfig.buildOptions.site || `http://${hostname}:${port}`);
|
||||||
const reqPath = decodeURI(fullurl.pathname);
|
const reqPath = decodeURI(fullurl.pathname);
|
||||||
error(logging, 'static', 'Not found', reqPath);
|
error(logging, 'static', 'Not found', reqPath);
|
||||||
res.statusCode = 404;
|
res.statusCode = 404;
|
||||||
|
@ -99,7 +98,7 @@ export default async function dev(astroConfig: AstroConfig) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const port = astroConfig.devOptions.port;
|
const { hostname, port } = astroConfig.devOptions;
|
||||||
server
|
server
|
||||||
.listen(port, hostname, () => {
|
.listen(port, hostname, () => {
|
||||||
const endServerTime = performance.now();
|
const endServerTime = performance.now();
|
||||||
|
|
|
@ -66,7 +66,7 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro
|
||||||
const { logging, snowpackRuntime, snowpack, configManager } = config;
|
const { logging, snowpackRuntime, snowpack, configManager } = config;
|
||||||
const { buildOptions, devOptions } = config.astroConfig;
|
const { buildOptions, devOptions } = config.astroConfig;
|
||||||
|
|
||||||
let origin = buildOptions.site ? new URL(buildOptions.site).origin : `http://localhost:${devOptions.port}`;
|
let origin = buildOptions.site ? new URL(buildOptions.site).origin : `http://${devOptions.hostname}:${devOptions.port}`;
|
||||||
const fullurl = new URL(rawPathname || '/', origin);
|
const fullurl = new URL(rawPathname || '/', origin);
|
||||||
|
|
||||||
const reqPath = decodeURI(fullurl.pathname);
|
const reqPath = decodeURI(fullurl.pathname);
|
||||||
|
|
43
packages/astro/test/config-hostname.test.js
Normal file
43
packages/astro/test/config-hostname.test.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { suite } from 'uvu';
|
||||||
|
import * as assert from 'uvu/assert';
|
||||||
|
import { runDevServer } from './helpers.js';
|
||||||
|
import { loadConfig } from '#astro/config';
|
||||||
|
|
||||||
|
const ConfigPort = suite('Config hostname');
|
||||||
|
const MAX_TEST_TIME = 10000; // max time this test suite may take
|
||||||
|
|
||||||
|
const root = new URL('./fixtures/config-hostname/', import.meta.url);
|
||||||
|
const timers = {};
|
||||||
|
|
||||||
|
ConfigPort.before.each(({ __test__ }) => {
|
||||||
|
timers[__test__] = setTimeout(() => {
|
||||||
|
throw new Error(`Test "${__test__}" did not finish within allowed time`);
|
||||||
|
}, MAX_TEST_TIME);
|
||||||
|
});
|
||||||
|
|
||||||
|
ConfigPort('can be specified in the astro config', async (context) => {
|
||||||
|
const astroConfig = await loadConfig(fileURLToPath(root));
|
||||||
|
assert.equal(astroConfig.devOptions.hostname, '0.0.0.0');
|
||||||
|
});
|
||||||
|
|
||||||
|
ConfigPort('can be specified via --hostname flag', async (context) => {
|
||||||
|
const args = ['--hostname', '127.0.0.1'];
|
||||||
|
const proc = runDevServer(root, args);
|
||||||
|
|
||||||
|
proc.stdout.setEncoding('utf8');
|
||||||
|
for await (const chunk of proc.stdout) {
|
||||||
|
if (/Local:/.test(chunk)) {
|
||||||
|
assert.ok(/:127.0.0.1/.test(chunk), 'Using the right hostname');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proc.kill();
|
||||||
|
});
|
||||||
|
|
||||||
|
ConfigPort.after.each(({ __test__ }) => {
|
||||||
|
clearTimeout(timers[__test__]);
|
||||||
|
});
|
||||||
|
|
||||||
|
ConfigPort.run();
|
6
packages/astro/test/fixtures/config-hostname/astro.config.mjs
vendored
Normal file
6
packages/astro/test/fixtures/config-hostname/astro.config.mjs
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
export default {
|
||||||
|
devOptions: {
|
||||||
|
hostname: '0.0.0.0'
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,8 +10,9 @@ export const createConfig = ({ renderers }: { renderers: string[] }) => {
|
||||||
sitemap: true, // Generate sitemap (set to "false" to disable)
|
sitemap: true, // Generate sitemap (set to "false" to disable)
|
||||||
},
|
},
|
||||||
devOptions: {
|
devOptions: {
|
||||||
// port: 3000, // The port to run the dev server on.
|
// hostname: 'localhost', // The hostname to run the dev server on.
|
||||||
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
|
// port: 3000, // The port to run the dev server on.
|
||||||
|
// tailwindConfig: '', // Path to tailwind.config.js if used, e.g. './tailwind.config.js'
|
||||||
},`,
|
},`,
|
||||||
` renderers: ${JSON.stringify(renderers, undefined, 2)
|
` renderers: ${JSON.stringify(renderers, undefined, 2)
|
||||||
.split('\n')
|
.split('\n')
|
||||||
|
|
Loading…
Reference in a new issue