Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/2177/log missing local network ip #2732

Merged
merged 13 commits into from
Mar 8, 2022
5 changes: 5 additions & 0 deletions .changeset/yellow-trees-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Update server start message to use localhost for local hostnames
5 changes: 3 additions & 2 deletions packages/astro/src/core/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { createVite } from '../create-vite.js';
import { defaultLogOptions, info, LogOptions } from '../logger.js';
import * as vite from 'vite';
import * as msg from '../messages.js';
import { getLocalAddress } from './util.js';

export interface DevOptions {
logging: LogOptions;
Expand Down Expand Up @@ -37,10 +38,10 @@ export default async function dev(config: AstroConfig, options: DevOptions = { l
const viteServer = await vite.createServer(viteConfig);
await viteServer.listen(config.devOptions.port);
const address = viteServer.httpServer!.address() as AddressInfo;
const localAddress = getLocalAddress(address.address, config.devOptions.hostname)
// Log to console
const site = config.buildOptions.site ? new URL(config.buildOptions.site) : undefined;
info(options.logging, 'astro', msg.devStart({ startupTime: performance.now() - devStart }));
info(options.logging, 'astro', msg.devHost({ address, site, https: !!viteUserConfig.server?.https }));
info(options.logging, null, msg.devStart({ startupTime: performance.now() - devStart, port: address.port, localAddress, networkAddress: address.address, site, https: !!viteUserConfig.server?.https }));

return {
address,
Expand Down
12 changes: 12 additions & 0 deletions packages/astro/src/core/dev/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,15 @@ export function pad(input: string, minLength: number, dir?: 'left' | 'right'): s
}
return output;
}

export function emoji(char: string, fallback: string) {
return process.platform !== 'win32' ? char : fallback;
}

export function getLocalAddress(serverAddress: string, configHostname: string): string {
if (configHostname === 'localhost' || serverAddress === '127.0.0.1' || serverAddress === '0.0.0.0') {
return 'localhost'
} else {
return serverAddress
}
}
3 changes: 2 additions & 1 deletion packages/astro/src/core/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ export const defaultLogDestination = new Writable({
dest = process.stdout;
}

dest.write(dim(dt.format(new Date()) + ' '));

let type = event.type;
if (type) {
// hide timestamp when type is undefined
dest.write(dim(dt.format(new Date()) + ' '));
if (event.level === 'info') {
type = bold(blue(type));
} else if (event.level === 'warn') {
Expand Down
21 changes: 17 additions & 4 deletions packages/astro/src/core/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
*/

import type { AddressInfo } from 'net';
import { bold, dim, green, magenta, yellow } from 'kleur/colors';
import { pad } from './dev/util.js';
import { bold, dim, green, magenta, yellow, cyan } from 'kleur/colors';
import { pad, emoji } from './dev/util.js';

/** Display */
export function req({ url, statusCode, reqTime }: { url: string; statusCode: number; reqTime?: number }): string {
Expand All @@ -23,8 +23,21 @@ export function reload({ url, reqTime }: { url: string; reqTime: number }): stri
}

/** Display dev server host and startup time */
export function devStart({ startupTime }: { startupTime: number }): string {
return `${pad(`Server started`, 44)} ${dim(`${Math.round(startupTime)}ms`)}`;
export function devStart({ startupTime, port, localAddress, networkAddress, https, site }: { startupTime: number; port: number; localAddress: string; networkAddress: string; https: boolean; site: URL | undefined }): string {
// PACAKGE_VERSION is injected at build-time
const pkgVersion = process.env.PACKAGE_VERSION;

const rootPath = site ? site.pathname : '/';
const toDisplayUrl = (hostname: string) => `${https ? 'https' : 'http'}:https://${hostname}:${port}${rootPath}`
const messages = [
``,
`${emoji('🚀 ', '')}${magenta(`astro ${pkgVersion}`)} ${dim(`started in ${Math.round(startupTime)}ms`)}`,
``,
`Local: ${bold(cyan(toDisplayUrl(localAddress)))}`,
`Network: ${bold(cyan(toDisplayUrl(networkAddress)))}`,
``,
]
return messages.join('\n')
}

/** Display dev server host */
Expand Down
10 changes: 7 additions & 3 deletions packages/astro/src/core/preview/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { AstroConfig } from '../../@types/astro';
import type { LogOptions } from '../logger';
import type { Stats } from 'fs';
import type { AddressInfo } from 'net';

import http from 'http';
import { performance } from 'perf_hooks';
Expand All @@ -11,6 +12,7 @@ import * as msg from '../messages.js';
import { error, info } from '../logger.js';
import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js';
import { appendForwardSlash, trimSlashes } from '../path.js';
import { getLocalAddress } from '../dev/util.js';

interface PreviewOptions {
logging: LogOptions;
Expand Down Expand Up @@ -123,10 +125,12 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO
let showedListenMsg = false;
return new Promise<void>((resolve, reject) => {
const listen = () => {
httpServer = server.listen(port, hostname, () => {
httpServer = server.listen(port, hostname, async () => {
if (!showedListenMsg) {
info(logging, 'astro', msg.devStart({ startupTime: performance.now() - timerStart }));
info(logging, 'astro', msg.devHost({ address: { family: 'ipv4', address: hostname, port }, https: false, site: baseURL }));
const { address: networkAddress } = server.address() as AddressInfo;
const localAddress = getLocalAddress(networkAddress, hostname)

info(logging, null, msg.devStart({ startupTime: performance.now() - timerStart, port, localAddress, networkAddress, https: false, site: baseURL }));
}
showedListenMsg = true;
resolve();
Expand Down
24 changes: 14 additions & 10 deletions packages/astro/test/cli.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,26 @@ describe('astro cli', () => {
expect(proc.stdout).to.equal(pkgVersion);
});

it('astro dev', async () => {
const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
[undefined, '0.0.0.0', '127.0.0.1'].forEach(hostname => {
it(`astro dev --hostname=${hostname}`, async () => {
const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);

const proc = cli('dev', '--project-root', fileURLToPath(projectRootURL));
const hostnameArgs = hostname ? ['--hostname', hostname] : []
const proc = cli('dev', '--project-root', fileURLToPath(projectRootURL), ...hostnameArgs);

let stdout = '';
let stdout = '';

for await (const chunk of proc.stdout) {
stdout += chunk;
for await (const chunk of proc.stdout) {
stdout += chunk;

if (chunk.includes('Local:')) break;
}
if (chunk.includes('Local:')) break;
}

proc.kill();
proc.kill();

expect(stdout).to.include('Server started');
expect(stdout).to.include('Local: https://localhost:3000');
expect(stdout).to.include(`Network: https://${hostname ?? '127.0.0.1'}:3000`);
});
});

it('astro build', async () => {
Expand Down
4 changes: 3 additions & 1 deletion scripts/cmd/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ export default async function build(...args) {
.map((f) => f.replace(/^'/, '').replace(/'$/, '')); // Needed for Windows: glob strings contain surrounding string chars??? remove these
let entryPoints = [].concat(...(await Promise.all(patterns.map((pattern) => glob(pattern, { filesOnly: true, absolute: true })))));

const { type = 'module', dependencies = {} } = await fs.readFile('./package.json').then((res) => JSON.parse(res.toString()));
const { type = 'module', version, dependencies = {} } = await fs.readFile('./package.json').then((res) => JSON.parse(res.toString()));
// expose PACKAGE_VERSION on process.env for CLI utils
config.define = { 'process.env.PACKAGE_VERSION': JSON.stringify(version) };
Comment on lines +31 to +33
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were already reading the local package.json file anyway, so we can inject whatever metadata we need during build

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great call!

const format = type === 'module' ? 'esm' : 'cjs';
const outdir = 'dist';
await clean(outdir);
Expand Down