diff --git a/src/AssetsBundler/index.ts b/src/AssetsBundler/index.ts index f14e057..2c8dd48 100644 --- a/src/AssetsBundler/index.ts +++ b/src/AssetsBundler/index.ts @@ -8,10 +8,21 @@ */ import execa from 'execa' +import getPort from 'get-port' import Emittery from 'emittery' import { logger as uiLogger } from '@poppinss/cliui' import { resolveDir } from '@poppinss/utils/build/helpers' +export type DevServerResponse = + | { + state: 'not-installed' | 'no-assets' + } + | { + state: 'running' + port: string + host: string + } + /** * Assets bundler uses webpack encore to build frontend dependencies */ @@ -99,6 +110,40 @@ export class AssetsBundler extends Emittery { console.error(`[ ${this.logger.colors.cyan('encore')} ] ${line}`) } + /** + * Returns the custom port defined using the `--port` flag in encore + * flags + */ + private findCustomPort(): undefined | string { + let portIndex = this.encoreArgs.findIndex((arg) => arg === '--port') + if (portIndex > -1) { + return this.encoreArgs[portIndex + 1] + } + + portIndex = this.encoreArgs.findIndex((arg) => arg.includes('--port')) + if (portIndex > -1) { + const tokens = this.encoreArgs[portIndex].split('=') + return tokens[1] && tokens[1].trim() + } + } + + /** + * Returns the custom host defined using the `--host` flag in encore + * flags + */ + private findCustomHost(): undefined | string { + let hostIndex = this.encoreArgs.findIndex((arg) => arg === '--host') + if (hostIndex > -1) { + return this.encoreArgs[hostIndex + 1] + } + + hostIndex = this.encoreArgs.findIndex((arg) => arg.includes('--host')) + if (hostIndex > -1) { + const tokens = this.encoreArgs[hostIndex].split('=') + return tokens[1] && tokens[1].trim() + } + } + /** * Execute command */ @@ -166,7 +211,7 @@ export class AssetsBundler extends Emittery { /** * Start the webpack dev server */ - public startDevServer(): { state: 'not-installed' | 'no-assets' | 'running' } { + public async startDevServer(): Promise { if (!this.isEncoreInstalled()) { return { state: 'not-installed' } } @@ -175,6 +220,24 @@ export class AssetsBundler extends Emittery { return { state: 'no-assets' } } + const customHost = this.findCustomHost() || 'localhost' + + /** + * Define a random port when the "--port" flag is not passed. + * + * Encore anyways doesn't allow defining port inside the webpack.config.js + * file for generating the manifest and entrypoints file. + * + * @see + * https://github.com/symfony/webpack-encore/issues/941#issuecomment-787568811 + */ + let customPort = this.findCustomPort() + if (!customPort) { + const randomPort = await getPort({ port: 8080 }) + customPort = String(randomPort) + this.encoreArgs.push('--port', customPort) + } + const childProcess = execa( this.binaryName, ['dev-server'].concat(this.encoreArgs), @@ -186,6 +249,6 @@ export class AssetsBundler extends Emittery { childProcess.on('close', (code, signal) => this.emit('close', { code, signal })) childProcess.on('exit', (code, signal) => this.emit('exit', { code, signal })) - return { state: 'running' } + return { state: 'running', port: customPort, host: customHost } } } diff --git a/src/DevServer/index.ts b/src/DevServer/index.ts index 326f8f8..60686d0 100644 --- a/src/DevServer/index.ts +++ b/src/DevServer/index.ts @@ -18,7 +18,7 @@ import { EnvParser } from '../EnvParser' import { HttpServer } from '../HttpServer' import { ENV_FILES, SERVER_ENTRY_FILE } from '../../config/paths' -import { AssetsBundler } from '../AssetsBundler' +import { AssetsBundler, DevServerResponse } from '../AssetsBundler' /** * Exposes the API to watch project for compilition changes. @@ -39,7 +39,7 @@ export class DevServer { /** * Encore dev server host */ - private encoreDevServerState: 'not-installed' | 'no-assets' | 'running' + private encoreDevServerResponse: DevServerResponse /** * A boolean to know if we are watching for filesystem @@ -155,10 +155,10 @@ export class DevServer { /** * Running the encore dev server */ - if (this.encoreDevServerState !== 'not-installed') { + if (this.encoreDevServerResponse.state === 'running') { stickerInstance.add( - `Running encore dev server: ${this.logger.colors.cyan( - this.encoreDevServerState === 'running' ? 'YES' : 'NO' + `Encore server address: ${this.logger.colors.cyan( + `http://${this.encoreDevServerResponse.host}:${this.encoreDevServerResponse.port}` )}` ) } @@ -203,8 +203,7 @@ export class DevServer { this.logger.warning(`Underlying encore dev server died with "${code} code"`) }) - const { state } = encore.startDevServer() - this.encoreDevServerState = state + this.encoreDevServerResponse = await encore.startDevServer() } /**