mirror of
https://github.com/withastro/astro.git
synced 2024-12-30 22:03:56 -05:00
Fix/2177/log missing local network ip (#2732)
* feat: show "localhost" for local network IPs
* refactor: remove timestamps from addr logs
* fix: hide timestamp on null types
* feat: add emoji OS helper
* feat: make logs 100% nicer
* refactor: extract isLocalHost to util
* feat: update preview logs to match
* chore: add changeset
* fix: pull pkg version from package.json
* refactor: remove 👉 guys
* fix: devStart return type
* feat: inject process.env.PACKAGE_VERSION at build time
* feat: update unit test for hostname checks
Co-authored-by: Nate Moore <nate@skypack.dev>
This commit is contained in:
parent
6bf124fb2f
commit
0ae96bb749
8 changed files with 63 additions and 21 deletions
5
.changeset/yellow-trees-clean.md
Normal file
5
.changeset/yellow-trees-clean.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Update server start message to use localhost for local hostnames
|
|
@ -6,6 +6,7 @@ import { createVite } from '../create-vite.js';
|
||||||
import { defaultLogOptions, info, LogOptions } from '../logger.js';
|
import { defaultLogOptions, info, LogOptions } from '../logger.js';
|
||||||
import * as vite from 'vite';
|
import * as vite from 'vite';
|
||||||
import * as msg from '../messages.js';
|
import * as msg from '../messages.js';
|
||||||
|
import { getLocalAddress } from './util.js';
|
||||||
|
|
||||||
export interface DevOptions {
|
export interface DevOptions {
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
|
@ -37,10 +38,10 @@ export default async function dev(config: AstroConfig, options: DevOptions = { l
|
||||||
const viteServer = await vite.createServer(viteConfig);
|
const viteServer = await vite.createServer(viteConfig);
|
||||||
await viteServer.listen(config.devOptions.port);
|
await viteServer.listen(config.devOptions.port);
|
||||||
const address = viteServer.httpServer!.address() as AddressInfo;
|
const address = viteServer.httpServer!.address() as AddressInfo;
|
||||||
|
const localAddress = getLocalAddress(address.address, config.devOptions.hostname)
|
||||||
// Log to console
|
// Log to console
|
||||||
const site = config.buildOptions.site ? new URL(config.buildOptions.site) : undefined;
|
const site = config.buildOptions.site ? new URL(config.buildOptions.site) : undefined;
|
||||||
info(options.logging, 'astro', msg.devStart({ startupTime: performance.now() - devStart }));
|
info(options.logging, null, msg.devStart({ startupTime: performance.now() - devStart, port: address.port, localAddress, networkAddress: address.address, site, https: !!viteUserConfig.server?.https }));
|
||||||
info(options.logging, 'astro', msg.devHost({ address, site, https: !!viteUserConfig.server?.https }));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
address,
|
address,
|
||||||
|
|
|
@ -6,3 +6,15 @@ export function pad(input: string, minLength: number, dir?: 'left' | 'right'): s
|
||||||
}
|
}
|
||||||
return output;
|
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
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,10 +35,11 @@ export const defaultLogDestination = new Writable({
|
||||||
dest = process.stdout;
|
dest = process.stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
dest.write(dim(dt.format(new Date()) + ' '));
|
|
||||||
|
|
||||||
let type = event.type;
|
let type = event.type;
|
||||||
if (type) {
|
if (type) {
|
||||||
|
// hide timestamp when type is undefined
|
||||||
|
dest.write(dim(dt.format(new Date()) + ' '));
|
||||||
if (event.level === 'info') {
|
if (event.level === 'info') {
|
||||||
type = bold(blue(type));
|
type = bold(blue(type));
|
||||||
} else if (event.level === 'warn') {
|
} else if (event.level === 'warn') {
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { AddressInfo } from 'net';
|
import type { AddressInfo } from 'net';
|
||||||
import { bold, dim, green, magenta, yellow } from 'kleur/colors';
|
import { bold, dim, green, magenta, yellow, cyan } from 'kleur/colors';
|
||||||
import { pad } from './dev/util.js';
|
import { pad, emoji } from './dev/util.js';
|
||||||
|
|
||||||
/** Display */
|
/** Display */
|
||||||
export function req({ url, statusCode, reqTime }: { url: string; statusCode: number; reqTime?: number }): string {
|
export function req({ url, statusCode, reqTime }: { url: string; statusCode: number; reqTime?: number }): string {
|
||||||
|
@ -23,8 +23,21 @@ export function reload({ url, reqTime }: { url: string; reqTime: number }): stri
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Display dev server host and startup time */
|
/** Display dev server host and startup time */
|
||||||
export function devStart({ startupTime }: { startupTime: number }): string {
|
export function devStart({ startupTime, port, localAddress, networkAddress, https, site }: { startupTime: number; port: number; localAddress: string; networkAddress: string; https: boolean; site: URL | undefined }): string {
|
||||||
return `${pad(`Server started`, 44)} ${dim(`${Math.round(startupTime)}ms`)}`;
|
// 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'}://${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 */
|
/** Display dev server host */
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import type { AstroConfig } from '../../@types/astro';
|
import type { AstroConfig } from '../../@types/astro';
|
||||||
import type { LogOptions } from '../logger';
|
import type { LogOptions } from '../logger';
|
||||||
import type { Stats } from 'fs';
|
import type { Stats } from 'fs';
|
||||||
|
import type { AddressInfo } from 'net';
|
||||||
|
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
|
@ -11,6 +12,7 @@ import * as msg from '../messages.js';
|
||||||
import { error, info } from '../logger.js';
|
import { error, info } from '../logger.js';
|
||||||
import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js';
|
import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js';
|
||||||
import { appendForwardSlash, trimSlashes } from '../path.js';
|
import { appendForwardSlash, trimSlashes } from '../path.js';
|
||||||
|
import { getLocalAddress } from '../dev/util.js';
|
||||||
|
|
||||||
interface PreviewOptions {
|
interface PreviewOptions {
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
|
@ -123,10 +125,12 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO
|
||||||
let showedListenMsg = false;
|
let showedListenMsg = false;
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
const listen = () => {
|
const listen = () => {
|
||||||
httpServer = server.listen(port, hostname, () => {
|
httpServer = server.listen(port, hostname, async () => {
|
||||||
if (!showedListenMsg) {
|
if (!showedListenMsg) {
|
||||||
info(logging, 'astro', msg.devStart({ startupTime: performance.now() - timerStart }));
|
const { address: networkAddress } = server.address() as AddressInfo;
|
||||||
info(logging, 'astro', msg.devHost({ address: { family: 'ipv4', address: hostname, port }, https: false, site: baseURL }));
|
const localAddress = getLocalAddress(networkAddress, hostname)
|
||||||
|
|
||||||
|
info(logging, null, msg.devStart({ startupTime: performance.now() - timerStart, port, localAddress, networkAddress, https: false, site: baseURL }));
|
||||||
}
|
}
|
||||||
showedListenMsg = true;
|
showedListenMsg = true;
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
@ -19,22 +19,26 @@ describe('astro cli', () => {
|
||||||
expect(proc.stdout).to.equal(pkgVersion);
|
expect(proc.stdout).to.equal(pkgVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('astro dev', async () => {
|
[undefined, '0.0.0.0', '127.0.0.1'].forEach(hostname => {
|
||||||
const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
|
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) {
|
for await (const chunk of proc.stdout) {
|
||||||
stdout += chunk;
|
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: http://localhost:3000');
|
||||||
|
expect(stdout).to.include(`Network: http://${hostname ?? '127.0.0.1'}:3000`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('astro build', async () => {
|
it('astro build', async () => {
|
||||||
|
|
|
@ -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
|
.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 })))));
|
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) };
|
||||||
const format = type === 'module' ? 'esm' : 'cjs';
|
const format = type === 'module' ? 'esm' : 'cjs';
|
||||||
const outdir = 'dist';
|
const outdir = 'dist';
|
||||||
await clean(outdir);
|
await clean(outdir);
|
||||||
|
|
Loading…
Reference in a new issue