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:
Maksim Markelov 2021-07-20 07:38:55 +03:00 committed by GitHub
parent 7ad7e16633
commit 0e761b9bdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 8 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add ability to specify hostname in devOptions

View file

@ -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;

View file

@ -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 */

View file

@ -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 = `

View file

@ -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;

View file

@ -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();

View file

@ -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);

View 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();

View file

@ -0,0 +1,6 @@
export default {
devOptions: {
hostname: '0.0.0.0'
}
}

View file

@ -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')