From c6838154bdca5fa75414eed89899ee5fe5133da4 Mon Sep 17 00:00:00 2001 From: Kevin He Date: Wed, 4 May 2022 18:14:20 -0700 Subject: [PATCH 1/4] implement dev serveStaticFile --- .../src/ssr/server/build-dev-server.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.js b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.js index 0d7a5af920..927d8b3378 100644 --- a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.js +++ b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.js @@ -181,6 +181,40 @@ export const DevServerMixin = { }) }, + serveStaticFile(filePath, opts = {}) { + return (req, res) => { + req.app.__devMiddleware.waitUntilValid(() => { + const options = req.app.options + const webpackStats = req.app.__devMiddleware.context.stats.stats + + const serverCompilation = webpackStats.find( + // static files are copied into bundle + // in the server webpack config + (stat) => stat.compilation.name === SERVER + ).compilation + const {assetsInfo} = serverCompilation + const assetInfo = assetsInfo.get(filePath) + + // if the asset is not in the webpack bundle, then + // return 404, we don't care whether or not the file + // exists in the local file system + if (!assetInfo) { + res.sendStatus(404) + return + } + const {sourceFilename} = assetInfo + const sourceFilePath = path.resolve(sourceFilename) + + res.sendFile(sourceFilePath, { + headers: { + 'cache-control': options.defaultCacheControl + }, + ...opts + }) + }) + } + }, + serveServiceWorker(req, res) { req.app.__devMiddleware.waitUntilValid(() => { const sourceMap = req.path.endsWith('.map') From 9b255e7f04bfef4e6d398e2aa684677582ebb760 Mon Sep 17 00:00:00 2001 From: Kevin He Date: Wed, 4 May 2022 18:36:09 -0700 Subject: [PATCH 2/4] serve favicon in typescript template --- packages/template-typescript-minimal/app/ssr.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/template-typescript-minimal/app/ssr.js b/packages/template-typescript-minimal/app/ssr.js index dbe129457f..7eb7c4b97e 100644 --- a/packages/template-typescript-minimal/app/ssr.js +++ b/packages/template-typescript-minimal/app/ssr.js @@ -40,7 +40,7 @@ const {handler} = runtime.createHandler(options, (app) => { res.send() }) - app.get('/robots.txt', runtime.serveStaticFile('static/robots.txt')) + app.get('/favicon.ico', runtime.serveStaticFile('static/favicon.ico')) app.get('/worker.js(.map)?', runtime.serveServiceWorker) app.get('*', runtime.render) From b80254346a391b70598301020b699b80613d3e2b Mon Sep 17 00:00:00 2001 From: Kevin He Date: Thu, 5 May 2022 15:19:01 -0700 Subject: [PATCH 3/4] add test --- .../src/ssr/server/build-dev-server.test.js | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js index aa95f590fb..2a7803f9a2 100644 --- a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js +++ b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js @@ -35,6 +35,40 @@ const NoWebpackDevServerFactory = { } } +// This isn't ideal! We need a way to test the dev middleware +// including the on demand webpack compiler. However, the webpack config and +// the Dev server assumes the code runs at the root of a project. +// When we run the tests, we are not in a project. +// We have a /test_fixtures project, but Jest does not support process.chdir(), +// nor mocking process.cwd(), so we mock the dev middleware for now. +// TODO: create a proper testing fixture project and run the tests in the isolated +// project environment. +const MockWebpackDevMiddleware = { + waitUntilValid: (cb) => cb(), + context: { + stats: { + stats: [ + { + compilation: { + name: 'server', + assetsInfo: new Map([ + [ + 'static/favicon.ico', + { + sourceFilename: path.resolve( + testFixtures, + 'app/static/favicon.ico' + ) + } + ] + ]) + } + } + ] + } + } +} + const httpAgent = new http.Agent({}) /** @@ -620,3 +654,25 @@ describe('DevServer persistent caching support', () => { }) }) }) + +describe('DevServer serveStaticFile', () => { + test('should serve static files', async () => { + const options = opts() + const app = NoWebpackDevServerFactory._createApp(options) + app.__devMiddleware = MockWebpackDevMiddleware + app.use('/test', NoWebpackDevServerFactory.serveStaticFile('static/favicon.ico')) + return request(app) + .get('/test') + .expect(200) + }) + + test('should return 404 if static file does not exist', async () => { + const options = opts() + const app = NoWebpackDevServerFactory._createApp(options) + app.__devMiddleware = MockWebpackDevMiddleware + app.use('/test', NoWebpackDevServerFactory.serveStaticFile('static/IDoNotExist.ico')) + return request(app) + .get('/test') + .expect(404) + }) +}) From f0d1943524a20ce1fa13c7620a0e35b3ae97b4fc Mon Sep 17 00:00:00 2001 From: Kevin He Date: Fri, 6 May 2022 10:03:36 -0700 Subject: [PATCH 4/4] move mock closer to test case --- .../src/ssr/server/build-dev-server.test.js | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js index 2a7803f9a2..ac525ae163 100644 --- a/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js +++ b/packages/pwa-kit-dev/src/ssr/server/build-dev-server.test.js @@ -35,40 +35,6 @@ const NoWebpackDevServerFactory = { } } -// This isn't ideal! We need a way to test the dev middleware -// including the on demand webpack compiler. However, the webpack config and -// the Dev server assumes the code runs at the root of a project. -// When we run the tests, we are not in a project. -// We have a /test_fixtures project, but Jest does not support process.chdir(), -// nor mocking process.cwd(), so we mock the dev middleware for now. -// TODO: create a proper testing fixture project and run the tests in the isolated -// project environment. -const MockWebpackDevMiddleware = { - waitUntilValid: (cb) => cb(), - context: { - stats: { - stats: [ - { - compilation: { - name: 'server', - assetsInfo: new Map([ - [ - 'static/favicon.ico', - { - sourceFilename: path.resolve( - testFixtures, - 'app/static/favicon.ico' - ) - } - ] - ]) - } - } - ] - } - } -} - const httpAgent = new http.Agent({}) /** @@ -656,6 +622,40 @@ describe('DevServer persistent caching support', () => { }) describe('DevServer serveStaticFile', () => { + // This isn't ideal! We need a way to test the dev middleware + // including the on demand webpack compiler. However, the webpack config and + // the Dev server assumes the code runs at the root of a project. + // When we run the tests, we are not in a project. + // We have a /test_fixtures project, but Jest does not support process.chdir(), + // nor mocking process.cwd(), so we mock the dev middleware for now. + // TODO: create a proper testing fixture project and run the tests in the isolated + // project environment. + const MockWebpackDevMiddleware = { + waitUntilValid: (cb) => cb(), + context: { + stats: { + stats: [ + { + compilation: { + name: 'server', + assetsInfo: new Map([ + [ + 'static/favicon.ico', + { + sourceFilename: path.resolve( + testFixtures, + 'app/static/favicon.ico' + ) + } + ] + ]) + } + } + ] + } + } + } + test('should serve static files', async () => { const options = opts() const app = NoWebpackDevServerFactory._createApp(options)