8
8
*/
9
9
10
10
import execa from 'execa'
11
+ import getPort from 'get-port'
11
12
import Emittery from 'emittery'
12
13
import { logger as uiLogger } from '@poppinss/cliui'
13
14
import { resolveDir } from '@poppinss/utils/build/helpers'
14
15
16
+ export type DevServerResponse =
17
+ | {
18
+ state : 'not-installed' | 'no-assets'
19
+ }
20
+ | {
21
+ state : 'running'
22
+ port : string
23
+ host : string
24
+ }
25
+
15
26
/**
16
27
* Assets bundler uses webpack encore to build frontend dependencies
17
28
*/
@@ -99,6 +110,40 @@ export class AssetsBundler extends Emittery {
99
110
console . error ( `[ ${ this . logger . colors . cyan ( 'encore' ) } ] ${ line } ` )
100
111
}
101
112
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
+
102
147
/**
103
148
* Execute command
104
149
*/
@@ -166,7 +211,7 @@ export class AssetsBundler extends Emittery {
166
211
/**
167
212
* Start the webpack dev server
168
213
*/
169
- public startDevServer ( ) : { state : 'not-installed' | 'no-assets' | 'running' } {
214
+ public async startDevServer ( ) : Promise < DevServerResponse > {
170
215
if ( ! this . isEncoreInstalled ( ) ) {
171
216
return { state : 'not-installed' }
172
217
}
@@ -175,6 +220,24 @@ export class AssetsBundler extends Emittery {
175
220
return { state : 'no-assets' }
176
221
}
177
222
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
+
178
241
const childProcess = execa (
179
242
this . binaryName ,
180
243
[ 'dev-server' ] . concat ( this . encoreArgs ) ,
@@ -186,6 +249,6 @@ export class AssetsBundler extends Emittery {
186
249
childProcess . on ( 'close' , ( code , signal ) => this . emit ( 'close' , { code, signal } ) )
187
250
childProcess . on ( 'exit' , ( code , signal ) => this . emit ( 'exit' , { code, signal } ) )
188
251
189
- return { state : 'running' }
252
+ return { state : 'running' , port : customPort , host : customHost }
190
253
}
191
254
}
0 commit comments