@nlabs/lex 1.51.5 → 1.51.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -54
- package/lib/commands/build/build.js +10 -3
- package/lib/commands/dev/dev.js +18 -6
- package/lib/utils/file.js +24 -3
- package/package.json +1 -1
- package/scripts/test-static-manual.js +117 -0
- package/scripts/test-webpack.js +124 -30
- package/webpack.config.js +140 -10
package/scripts/test-webpack.js
CHANGED
|
@@ -215,9 +215,14 @@ try {
|
|
|
215
215
|
});
|
|
216
216
|
|
|
217
217
|
let serverOutput = '';
|
|
218
|
+
let serverStartedOutput = false;
|
|
218
219
|
devServerProcess.stdout.on('data', (data) => {
|
|
219
220
|
const output = data.toString();
|
|
220
221
|
serverOutput += output;
|
|
222
|
+
// Check for server ready indicators
|
|
223
|
+
if (output.includes('compiled') || output.includes('Local:') || output.includes('http://') || output.includes('webpack compiled')) {
|
|
224
|
+
serverStartedOutput = true;
|
|
225
|
+
}
|
|
221
226
|
});
|
|
222
227
|
|
|
223
228
|
devServerProcess.stderr.on('data', (data) => {
|
|
@@ -226,6 +231,10 @@ try {
|
|
|
226
231
|
if (output.includes('error') || output.includes('Error') || output.includes('ERROR')) {
|
|
227
232
|
serverError = output;
|
|
228
233
|
}
|
|
234
|
+
// Sometimes webpack outputs to stderr but it's not an error
|
|
235
|
+
if (output.includes('compiled') || output.includes('webpack')) {
|
|
236
|
+
serverStartedOutput = true;
|
|
237
|
+
}
|
|
229
238
|
});
|
|
230
239
|
|
|
231
240
|
devServerProcess.on('error', (error) => {
|
|
@@ -253,33 +262,65 @@ try {
|
|
|
253
262
|
};
|
|
254
263
|
|
|
255
264
|
const waitForServer = async () => {
|
|
256
|
-
for (let i = 0; i <
|
|
265
|
+
for (let i = 0; i < 90; i++) {
|
|
257
266
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
258
267
|
|
|
259
268
|
const portOpen = await checkPort(testPort);
|
|
260
|
-
if (portOpen) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
269
|
+
if (portOpen || serverStartedOutput) {
|
|
270
|
+
// Give it a bit more time to fully initialize
|
|
271
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
272
|
+
|
|
273
|
+
// Try to access the static file directly
|
|
274
|
+
try {
|
|
275
|
+
const controller = new AbortController();
|
|
276
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
277
|
+
const response = await fetch(`http://localhost:${testPort}/test.txt`, {
|
|
278
|
+
signal: controller.signal
|
|
279
|
+
});
|
|
280
|
+
clearTimeout(timeoutId);
|
|
281
|
+
if (response.ok && response.status === 200) {
|
|
282
|
+
const content = await response.text();
|
|
283
|
+
if (content.includes('Static file content')) {
|
|
272
284
|
return true;
|
|
273
285
|
}
|
|
274
|
-
}
|
|
275
|
-
|
|
286
|
+
}
|
|
287
|
+
} catch (error) {
|
|
288
|
+
if (error.name !== 'AbortError' && i > 5) {
|
|
289
|
+
// Only log after a few attempts
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Also try index.html as a fallback check
|
|
294
|
+
try {
|
|
295
|
+
const controller = new AbortController();
|
|
296
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
297
|
+
const response = await fetch(`http://localhost:${testPort}/index.html`, {
|
|
298
|
+
signal: controller.signal
|
|
299
|
+
});
|
|
300
|
+
clearTimeout(timeoutId);
|
|
301
|
+
if (response.ok || response.status === 200) {
|
|
302
|
+
// Server is up, even if static file test didn't work yet
|
|
303
|
+
if (i > 10) {
|
|
304
|
+
// After 10 seconds, if server is up, try static file again
|
|
305
|
+
try {
|
|
306
|
+
const staticResponse = await fetch(`http://localhost:${testPort}/test.txt`, {
|
|
307
|
+
signal: controller.signal
|
|
308
|
+
});
|
|
309
|
+
if (staticResponse.ok) {
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
} catch {
|
|
313
|
+
}
|
|
276
314
|
}
|
|
277
315
|
}
|
|
316
|
+
} catch (error) {
|
|
317
|
+
if (error.name !== 'AbortError') {
|
|
318
|
+
}
|
|
278
319
|
}
|
|
279
320
|
}
|
|
280
321
|
|
|
281
322
|
if (i % 10 === 9 && i > 0) {
|
|
282
|
-
console.log(` Still waiting... (${i + 1}/
|
|
323
|
+
console.log(` Still waiting... (${i + 1}/90 seconds)`);
|
|
283
324
|
}
|
|
284
325
|
}
|
|
285
326
|
return false;
|
|
@@ -288,29 +329,49 @@ try {
|
|
|
288
329
|
serverReady = await waitForServer();
|
|
289
330
|
|
|
290
331
|
if (serverError) {
|
|
291
|
-
console.log(
|
|
292
|
-
console.log('
|
|
332
|
+
console.log(`❌ Dev server error: ${serverError}`);
|
|
333
|
+
console.log('❌ HTTP tests cannot run due to server error');
|
|
293
334
|
console.log('💡 Note: Static files are copied to build directory and should be accessible via dev server');
|
|
335
|
+
throw new Error(`Dev server failed to start: ${serverError}`);
|
|
294
336
|
} else if (!serverReady) {
|
|
295
|
-
console.log('
|
|
296
|
-
console.log('
|
|
337
|
+
console.log('❌ Dev server did not start within 60 seconds');
|
|
338
|
+
console.log('❌ HTTP tests cannot run - this is a required test');
|
|
297
339
|
console.log('💡 To test manually, run: cd <test-dir> && lex dev --port 3001');
|
|
298
340
|
if (serverOutput) {
|
|
299
|
-
const lastOutput = serverOutput.slice(-
|
|
300
|
-
console.log('\nServer output (last
|
|
341
|
+
const lastOutput = serverOutput.slice(-2000);
|
|
342
|
+
console.log('\nServer output (last 2000 chars):');
|
|
301
343
|
console.log(lastOutput);
|
|
344
|
+
// Check if there are any obvious errors
|
|
345
|
+
if (lastOutput.includes('Error') || lastOutput.includes('error') || lastOutput.includes('Cannot find')) {
|
|
346
|
+
console.log('\n⚠️ Potential errors detected in server output above');
|
|
347
|
+
}
|
|
302
348
|
} else {
|
|
303
349
|
console.log(' (No server output captured - server may not have started)');
|
|
350
|
+
console.log(' This could indicate the process failed to spawn or exited immediately');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Check if process is still running
|
|
354
|
+
if (devServerProcess && !devServerProcess.killed) {
|
|
355
|
+
try {
|
|
356
|
+
devServerProcess.kill(0); // Check if process exists
|
|
357
|
+
console.log(' (Dev server process is still running but not responding)');
|
|
358
|
+
} catch {
|
|
359
|
+
console.log(' (Dev server process has exited)');
|
|
360
|
+
}
|
|
304
361
|
}
|
|
362
|
+
throw new Error('Dev server did not start within timeout period - HTTP static file access test cannot run');
|
|
305
363
|
} else {
|
|
306
364
|
console.log(`✅ Dev server started on port ${testPort}`);
|
|
307
365
|
|
|
308
366
|
const testUrls = [
|
|
309
|
-
{url: '/test.txt', expectedContent: 'Static file content', description: 'Static file from staticPath'},
|
|
310
|
-
{url: '/index.html', expectedContent: 'Test App', description: 'HTML file'},
|
|
311
|
-
{url: '/images/test.png', expectedContent: 'fake-png-content', description: 'Image file'}
|
|
367
|
+
{url: '/test.txt', expectedContent: 'Static file content', description: 'Static file from staticPath', required: true},
|
|
368
|
+
{url: '/index.html', expectedContent: 'Test App', description: 'HTML file', required: false},
|
|
369
|
+
{url: '/images/test.png', expectedContent: 'fake-png-content', description: 'Image file', required: false}
|
|
312
370
|
];
|
|
313
371
|
|
|
372
|
+
let httpTestFailed = false;
|
|
373
|
+
const httpTestErrors = [];
|
|
374
|
+
|
|
314
375
|
for (const test of testUrls) {
|
|
315
376
|
try {
|
|
316
377
|
const response = await fetch(`http://localhost:${testPort}${test.url}`);
|
|
@@ -319,19 +380,47 @@ try {
|
|
|
319
380
|
if (content.includes(test.expectedContent)) {
|
|
320
381
|
console.log(`✅ ${test.description} accessible via HTTP (${test.url})`);
|
|
321
382
|
} else {
|
|
322
|
-
|
|
383
|
+
const errorMsg = `${test.description} accessible but content doesn't match (${test.url})`;
|
|
384
|
+
console.log(`❌ ${errorMsg}`);
|
|
385
|
+
if (test.required) {
|
|
386
|
+
httpTestFailed = true;
|
|
387
|
+
httpTestErrors.push(errorMsg);
|
|
388
|
+
}
|
|
323
389
|
}
|
|
324
390
|
} else {
|
|
325
|
-
|
|
391
|
+
const errorMsg = `${test.description} returned status ${response.status} (${test.url})`;
|
|
392
|
+
console.log(`❌ ${errorMsg}`);
|
|
393
|
+
if (test.required) {
|
|
394
|
+
httpTestFailed = true;
|
|
395
|
+
httpTestErrors.push(errorMsg);
|
|
396
|
+
}
|
|
326
397
|
}
|
|
327
398
|
} catch (error) {
|
|
328
|
-
|
|
399
|
+
const errorMsg = `Failed to fetch ${test.description}: ${error.message}`;
|
|
400
|
+
console.log(`❌ ${errorMsg}`);
|
|
401
|
+
if (test.required) {
|
|
402
|
+
httpTestFailed = true;
|
|
403
|
+
httpTestErrors.push(errorMsg);
|
|
404
|
+
}
|
|
329
405
|
}
|
|
330
406
|
}
|
|
407
|
+
|
|
408
|
+
if (httpTestFailed) {
|
|
409
|
+
console.log('\n❌ HTTP static file access test FAILED!');
|
|
410
|
+
console.log('Errors:');
|
|
411
|
+
httpTestErrors.forEach(err => console.log(` - ${err}`));
|
|
412
|
+
console.log('\n💡 The dev server must be able to serve static files from the staticPath directory.');
|
|
413
|
+
console.log('💡 Check that the middleware in webpack.config.js is correctly serving files from staticPathFull.');
|
|
414
|
+
throw new Error('HTTP static file access test failed');
|
|
415
|
+
} else {
|
|
416
|
+
console.log('\n✅ All HTTP static file access tests passed!');
|
|
417
|
+
}
|
|
331
418
|
}
|
|
332
419
|
|
|
333
420
|
} catch (error) {
|
|
334
|
-
console.
|
|
421
|
+
console.error(`\n❌ Dev server HTTP test failed: ${error.message}`);
|
|
422
|
+
console.error('This test is required and must pass.');
|
|
423
|
+
throw error;
|
|
335
424
|
} finally {
|
|
336
425
|
if (devServerProcess) {
|
|
337
426
|
console.log('🛑 Stopping dev server...');
|
|
@@ -344,12 +433,17 @@ try {
|
|
|
344
433
|
}
|
|
345
434
|
}
|
|
346
435
|
|
|
436
|
+
// Only print success if we didn't throw an error
|
|
347
437
|
console.log('\n🎉 All tests passed!');
|
|
348
438
|
console.log(`\n📁 Test project location: ${testDir}`);
|
|
349
439
|
console.log('💡 You can inspect the build output in the build/ directory');
|
|
350
440
|
|
|
351
441
|
} catch (error) {
|
|
352
|
-
console.error('❌
|
|
442
|
+
console.error('\n❌ Test suite failed:', error.message);
|
|
443
|
+
if (error.stack) {
|
|
444
|
+
console.error('\nStack trace:');
|
|
445
|
+
console.error(error.stack);
|
|
446
|
+
}
|
|
353
447
|
process.exit(1);
|
|
354
448
|
} finally {
|
|
355
449
|
console.log('\n🧹 Cleaning up...');
|
package/webpack.config.js
CHANGED
|
@@ -15,7 +15,9 @@ import {existsSync} from 'fs';
|
|
|
15
15
|
import {sync as globSync} from 'glob';
|
|
16
16
|
import HtmlWebPackPlugin from 'html-webpack-plugin';
|
|
17
17
|
import isEmpty from 'lodash/isEmpty.js';
|
|
18
|
+
import {createRequire} from 'module';
|
|
18
19
|
import {resolve as pathResolve} from 'path';
|
|
20
|
+
import {fileURLToPath} from 'url';
|
|
19
21
|
import postcssBrowserReporter from 'postcss-browser-reporter';
|
|
20
22
|
import postcssCustomProperties from 'postcss-custom-properties';
|
|
21
23
|
import postcssFlexbugsFixes from 'postcss-flexbugs-fixes';
|
|
@@ -40,6 +42,7 @@ const {ProgressPlugin, ProvidePlugin} = webpack;
|
|
|
40
42
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
41
43
|
const lexConfig = JSON.parse(process.env.LEX_CONFIG) || {};
|
|
42
44
|
const dirName = new URL('.', import.meta.url).pathname;
|
|
45
|
+
const require = createRequire(fileURLToPath(import.meta.url));
|
|
43
46
|
|
|
44
47
|
const {
|
|
45
48
|
isStatic,
|
|
@@ -100,6 +103,48 @@ const plugins = [
|
|
|
100
103
|
console.log('\x1b[32m[webpack]\x1b[0m Build complete. Watching for changes...');
|
|
101
104
|
}
|
|
102
105
|
});
|
|
106
|
+
compiler.hooks.normalModuleFactory.tap('ImportMetaTransform', (normalModuleFactory) => {
|
|
107
|
+
normalModuleFactory.hooks.parser.for('javascript/auto').tap('ImportMetaTransform', (parser) => {
|
|
108
|
+
parser.hooks.expression.for('import.meta').tap('ImportMetaTransform', (expr) => {
|
|
109
|
+
const dep = new webpack.dependencies.ConstDependency(
|
|
110
|
+
'({ url: typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : "") })',
|
|
111
|
+
expr.range
|
|
112
|
+
);
|
|
113
|
+
dep.loc = expr.loc;
|
|
114
|
+
parser.state.module.addPresentationalDependency(dep);
|
|
115
|
+
return true;
|
|
116
|
+
});
|
|
117
|
+
parser.hooks.expression.for('import.meta.url').tap('ImportMetaTransform', (expr) => {
|
|
118
|
+
const dep = new webpack.dependencies.ConstDependency(
|
|
119
|
+
'(typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : ""))',
|
|
120
|
+
expr.range
|
|
121
|
+
);
|
|
122
|
+
dep.loc = expr.loc;
|
|
123
|
+
parser.state.module.addPresentationalDependency(dep);
|
|
124
|
+
return true;
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
normalModuleFactory.hooks.parser.for('javascript/esm').tap('ImportMetaTransform', (parser) => {
|
|
128
|
+
parser.hooks.expression.for('import.meta').tap('ImportMetaTransform', (expr) => {
|
|
129
|
+
const dep = new webpack.dependencies.ConstDependency(
|
|
130
|
+
'({ url: typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : "") })',
|
|
131
|
+
expr.range
|
|
132
|
+
);
|
|
133
|
+
dep.loc = expr.loc;
|
|
134
|
+
parser.state.module.addPresentationalDependency(dep);
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
parser.hooks.expression.for('import.meta.url').tap('ImportMetaTransform', (expr) => {
|
|
138
|
+
const dep = new webpack.dependencies.ConstDependency(
|
|
139
|
+
'(typeof document !== "undefined" && document.currentScript && document.currentScript.src ? new URL(document.currentScript.src, window.location.href).href : (typeof window !== "undefined" ? new URL("", window.location.href).href : ""))',
|
|
140
|
+
expr.range
|
|
141
|
+
);
|
|
142
|
+
dep.loc = expr.loc;
|
|
143
|
+
parser.state.module.addPresentationalDependency(dep);
|
|
144
|
+
return true;
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
});
|
|
103
148
|
}
|
|
104
149
|
}
|
|
105
150
|
];
|
|
@@ -155,26 +200,31 @@ const fontPath = `${sourceFullPath}/fonts/`;
|
|
|
155
200
|
const docPath = `${sourceFullPath}/docs/`;
|
|
156
201
|
|
|
157
202
|
const staticPathFull = pathResolve(process.cwd(), webpackStaticPath);
|
|
203
|
+
|
|
158
204
|
if(existsSync(staticPathFull)) {
|
|
159
205
|
staticPaths.push({
|
|
160
206
|
from: staticPathFull,
|
|
207
|
+
globOptions: {
|
|
208
|
+
ignore: ['**/.DS_Store']
|
|
209
|
+
},
|
|
210
|
+
noErrorOnMissing: true,
|
|
161
211
|
to: './'
|
|
162
212
|
});
|
|
163
213
|
watchIgnorePaths.push(staticPathFull);
|
|
164
214
|
}
|
|
165
215
|
|
|
166
216
|
if(existsSync(imagePath)) {
|
|
167
|
-
staticPaths.push({from: imagePath, to: './images/'});
|
|
217
|
+
staticPaths.push({from: imagePath, noErrorOnMissing: true, to: './images/'});
|
|
168
218
|
watchIgnorePaths.push(imagePath);
|
|
169
219
|
}
|
|
170
220
|
|
|
171
221
|
if(existsSync(fontPath)) {
|
|
172
|
-
staticPaths.push({from: fontPath, to: './fonts/'});
|
|
222
|
+
staticPaths.push({from: fontPath, noErrorOnMissing: true, to: './fonts/'});
|
|
173
223
|
watchIgnorePaths.push(fontPath);
|
|
174
224
|
}
|
|
175
225
|
|
|
176
226
|
if(existsSync(docPath)) {
|
|
177
|
-
staticPaths.push({from: docPath, to: './docs/'});
|
|
227
|
+
staticPaths.push({from: docPath, noErrorOnMissing: true, to: './docs/'});
|
|
178
228
|
}
|
|
179
229
|
|
|
180
230
|
if(staticPaths.length) {
|
|
@@ -307,8 +357,42 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
307
357
|
{
|
|
308
358
|
test: /\.js$/,
|
|
309
359
|
include: /node_modules/,
|
|
360
|
+
exclude: [
|
|
361
|
+
/[\\/]websocket\.js$/,
|
|
362
|
+
/[\\/]websocket.*\.js$/
|
|
363
|
+
],
|
|
310
364
|
type: 'javascript/auto'
|
|
311
365
|
},
|
|
366
|
+
{
|
|
367
|
+
test: /[\\/]websocket(.*)?\.js$/,
|
|
368
|
+
include: /node_modules/,
|
|
369
|
+
use: {
|
|
370
|
+
loader: swcLoaderPath,
|
|
371
|
+
options: {
|
|
372
|
+
jsc: {
|
|
373
|
+
parser: {
|
|
374
|
+
syntax: 'ecmascript',
|
|
375
|
+
dynamicImport: true,
|
|
376
|
+
importAssertions: true
|
|
377
|
+
},
|
|
378
|
+
target: 'es2020',
|
|
379
|
+
transform: {
|
|
380
|
+
legacyDecorator: false,
|
|
381
|
+
decoratorMetadata: false
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
module: {
|
|
385
|
+
type: 'es6',
|
|
386
|
+
strict: false,
|
|
387
|
+
strictMode: true,
|
|
388
|
+
lazy: false,
|
|
389
|
+
noInterop: true
|
|
390
|
+
},
|
|
391
|
+
minify: false,
|
|
392
|
+
sourceMaps: false
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
},
|
|
312
396
|
{
|
|
313
397
|
enforce: 'pre',
|
|
314
398
|
exclude: /(node_modules)/,
|
|
@@ -323,6 +407,7 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
323
407
|
`${sourceFullPath}/**/*.test.ts*`
|
|
324
408
|
],
|
|
325
409
|
include: sourceFullPath,
|
|
410
|
+
type: 'javascript/esm',
|
|
326
411
|
loader: swcLoaderPath,
|
|
327
412
|
options: {
|
|
328
413
|
...LexConfig.config.swc,
|
|
@@ -330,8 +415,14 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
330
415
|
...LexConfig.config.swc?.jsc,
|
|
331
416
|
parser: {
|
|
332
417
|
...LexConfig.config.swc?.jsc?.parser,
|
|
333
|
-
tsx: false
|
|
334
|
-
|
|
418
|
+
tsx: false,
|
|
419
|
+
dynamicImport: true
|
|
420
|
+
},
|
|
421
|
+
target: LexConfig.config.swc?.jsc?.target || 'es2020'
|
|
422
|
+
},
|
|
423
|
+
module: {
|
|
424
|
+
...LexConfig.config.swc?.module,
|
|
425
|
+
type: 'es6'
|
|
335
426
|
}
|
|
336
427
|
},
|
|
337
428
|
resolve: {
|
|
@@ -346,6 +437,7 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
346
437
|
`${sourceFullPath}/**/*.test.ts*`
|
|
347
438
|
],
|
|
348
439
|
include: sourceFullPath,
|
|
440
|
+
type: 'javascript/esm',
|
|
349
441
|
loader: swcLoaderPath,
|
|
350
442
|
options: {
|
|
351
443
|
...LexConfig.config.swc,
|
|
@@ -538,7 +630,10 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
538
630
|
library: libraryName,
|
|
539
631
|
libraryTarget,
|
|
540
632
|
path: outputFullPath,
|
|
541
|
-
publicPath: '/'
|
|
633
|
+
publicPath: '/',
|
|
634
|
+
environment: {
|
|
635
|
+
module: true
|
|
636
|
+
}
|
|
542
637
|
},
|
|
543
638
|
plugins,
|
|
544
639
|
recordsPath: relativeFilePath('webpack.records.json', process.cwd()),
|
|
@@ -615,7 +710,7 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
615
710
|
}
|
|
616
711
|
},
|
|
617
712
|
{
|
|
618
|
-
from: /\\.(css|gif|ico|jpg|json|png|svg)$/,
|
|
713
|
+
from: /\\.(css|gif|ico|jpg|json|png|svg|txt)$/,
|
|
619
714
|
to: ({parsedUrl: {pathname}}) => pathname
|
|
620
715
|
}
|
|
621
716
|
],
|
|
@@ -623,15 +718,50 @@ export default (webpackEnv, webpackOptions) => {
|
|
|
623
718
|
},
|
|
624
719
|
hmr: false,
|
|
625
720
|
log: {level: 'trace'},
|
|
626
|
-
middleware: (app) =>
|
|
721
|
+
middleware: (app, builtins) => {
|
|
722
|
+
if(existsSync(staticPathFull)) {
|
|
723
|
+
if (process.env.LEX_CONFIG_DEBUG) {
|
|
724
|
+
console.log(`[LEX_DEBUG] Setting up static file serving from: ${staticPathFull}`);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
const koaStatic = require('koa-static');
|
|
728
|
+
|
|
729
|
+
app.use(koaStatic(staticPathFull, {
|
|
730
|
+
index: false, // Don't auto-serve index files
|
|
731
|
+
defer: false, // CRITICAL: Don't defer - serve immediately if file exists
|
|
732
|
+
hidden: false,
|
|
733
|
+
gzip: true,
|
|
734
|
+
br: false
|
|
735
|
+
}));
|
|
736
|
+
|
|
737
|
+
if (process.env.LEX_CONFIG_DEBUG) {
|
|
738
|
+
app.use(async (ctx, next) => {
|
|
739
|
+
const path = ctx.path || ctx.url || '';
|
|
740
|
+
if (path && !path.match(/^\/wps/) && !path.match(/^\/webpack/)) {
|
|
741
|
+
console.log(`[LEX_DEBUG] Request: ${path}`);
|
|
742
|
+
}
|
|
743
|
+
await next();
|
|
744
|
+
if (ctx.status === 404 && path && path.includes('.')) {
|
|
745
|
+
console.log(`[LEX_DEBUG] 404 for: ${path}, body set: ${ctx.body !== undefined}`);
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
}
|
|
749
|
+
} else {
|
|
750
|
+
if (process.env.LEX_CONFIG_DEBUG) {
|
|
751
|
+
console.log(`[LEX_DEBUG] Static path does not exist: ${staticPathFull}`);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
627
755
|
app.use(async (ctx, next) => {
|
|
628
|
-
|
|
756
|
+
const path = ctx.path || ctx.url || (ctx.request && ctx.request.path) || '';
|
|
757
|
+
if(path && path.match(/^\/wps/)) {
|
|
629
758
|
const {accept, Accept, ...remainingHeaders} =
|
|
630
759
|
ctx.request.header;
|
|
631
760
|
ctx.request.header = remainingHeaders;
|
|
632
761
|
}
|
|
633
762
|
await next();
|
|
634
|
-
})
|
|
763
|
+
});
|
|
764
|
+
},
|
|
635
765
|
open: process.env.WEBPACK_DEV_OPEN === 'true',
|
|
636
766
|
port: port || 3000,
|
|
637
767
|
progress: 'minimal',
|