Skip to content

Commit cb877cf

Browse files
committed
improvement: detect port for the encore dev server when default one is in use
1 parent 232f1ad commit cb877cf

File tree

2 files changed

+71
-9
lines changed

2 files changed

+71
-9
lines changed

src/AssetsBundler/index.ts

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,21 @@
88
*/
99

1010
import execa from 'execa'
11+
import getPort from 'get-port'
1112
import Emittery from 'emittery'
1213
import { logger as uiLogger } from '@poppinss/cliui'
1314
import { resolveDir } from '@poppinss/utils/build/helpers'
1415

16+
export type DevServerResponse =
17+
| {
18+
state: 'not-installed' | 'no-assets'
19+
}
20+
| {
21+
state: 'running'
22+
port: string
23+
host: string
24+
}
25+
1526
/**
1627
* Assets bundler uses webpack encore to build frontend dependencies
1728
*/
@@ -99,6 +110,40 @@ export class AssetsBundler extends Emittery {
99110
console.error(`[ ${this.logger.colors.cyan('encore')} ] ${line}`)
100111
}
101112

113+
/**
114+
* Returns the custom port defined using the `--port` flag in encore
115+
* flags
116+
*/
117+
private findCustomPort(): undefined | string {
118+
let portIndex = this.encoreArgs.findIndex((arg) => arg === '--port')
119+
if (portIndex > -1) {
120+
return this.encoreArgs[portIndex + 1]
121+
}
122+
123+
portIndex = this.encoreArgs.findIndex((arg) => arg.includes('--port'))
124+
if (portIndex > -1) {
125+
const tokens = this.encoreArgs[portIndex].split('=')
126+
return tokens[1] && tokens[1].trim()
127+
}
128+
}
129+
130+
/**
131+
* Returns the custom host defined using the `--host` flag in encore
132+
* flags
133+
*/
134+
private findCustomHost(): undefined | string {
135+
let hostIndex = this.encoreArgs.findIndex((arg) => arg === '--host')
136+
if (hostIndex > -1) {
137+
return this.encoreArgs[hostIndex + 1]
138+
}
139+
140+
hostIndex = this.encoreArgs.findIndex((arg) => arg.includes('--host'))
141+
if (hostIndex > -1) {
142+
const tokens = this.encoreArgs[hostIndex].split('=')
143+
return tokens[1] && tokens[1].trim()
144+
}
145+
}
146+
102147
/**
103148
* Execute command
104149
*/
@@ -166,7 +211,7 @@ export class AssetsBundler extends Emittery {
166211
/**
167212
* Start the webpack dev server
168213
*/
169-
public startDevServer(): { state: 'not-installed' | 'no-assets' | 'running' } {
214+
public async startDevServer(): Promise<DevServerResponse> {
170215
if (!this.isEncoreInstalled()) {
171216
return { state: 'not-installed' }
172217
}
@@ -175,6 +220,24 @@ export class AssetsBundler extends Emittery {
175220
return { state: 'no-assets' }
176221
}
177222

223+
const customHost = this.findCustomHost() || 'localhost'
224+
225+
/**
226+
* Define a random port when the "--port" flag is not passed.
227+
*
228+
* Encore anyways doesn't allow defining port inside the webpack.config.js
229+
* file for generating the manifest and entrypoints file.
230+
*
231+
* @see
232+
* https://github.com/symfony/webpack-encore/issues/941#issuecomment-787568811
233+
*/
234+
let customPort = this.findCustomPort()
235+
if (!customPort) {
236+
const randomPort = await getPort({ port: 8080 })
237+
customPort = String(randomPort)
238+
this.encoreArgs.push('--port', customPort)
239+
}
240+
178241
const childProcess = execa(
179242
this.binaryName,
180243
['dev-server'].concat(this.encoreArgs),
@@ -186,6 +249,6 @@ export class AssetsBundler extends Emittery {
186249
childProcess.on('close', (code, signal) => this.emit('close', { code, signal }))
187250
childProcess.on('exit', (code, signal) => this.emit('exit', { code, signal }))
188251

189-
return { state: 'running' }
252+
return { state: 'running', port: customPort, host: customHost }
190253
}
191254
}

src/DevServer/index.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { EnvParser } from '../EnvParser'
1818
import { HttpServer } from '../HttpServer'
1919

2020
import { ENV_FILES, SERVER_ENTRY_FILE } from '../../config/paths'
21-
import { AssetsBundler } from '../AssetsBundler'
21+
import { AssetsBundler, DevServerResponse } from '../AssetsBundler'
2222

2323
/**
2424
* Exposes the API to watch project for compilition changes.
@@ -39,7 +39,7 @@ export class DevServer {
3939
/**
4040
* Encore dev server host
4141
*/
42-
private encoreDevServerState: 'not-installed' | 'no-assets' | 'running'
42+
private encoreDevServerResponse: DevServerResponse
4343

4444
/**
4545
* A boolean to know if we are watching for filesystem
@@ -155,10 +155,10 @@ export class DevServer {
155155
/**
156156
* Running the encore dev server
157157
*/
158-
if (this.encoreDevServerState !== 'not-installed') {
158+
if (this.encoreDevServerResponse.state === 'running') {
159159
stickerInstance.add(
160-
`Running encore dev server: ${this.logger.colors.cyan(
161-
this.encoreDevServerState === 'running' ? 'YES' : 'NO'
160+
`Encore server address: ${this.logger.colors.cyan(
161+
`http://${this.encoreDevServerResponse.host}:${this.encoreDevServerResponse.port}`
162162
)}`
163163
)
164164
}
@@ -203,8 +203,7 @@ export class DevServer {
203203
this.logger.warning(`Underlying encore dev server died with "${code} code"`)
204204
})
205205

206-
const { state } = encore.startDevServer()
207-
this.encoreDevServerState = state
206+
this.encoreDevServerResponse = await encore.startDevServer()
208207
}
209208

210209
/**

0 commit comments

Comments
 (0)