diff --git a/__tests__/server/middleware/createRequestStore.spec.js b/__tests__/server/middleware/createRequestStore.spec.js index c04e9e3e9..3b19781b4 100644 --- a/__tests__/server/middleware/createRequestStore.spec.js +++ b/__tests__/server/middleware/createRequestStore.spec.js @@ -35,6 +35,7 @@ jest.mock('holocron', () => { holocron.getModuleMap.mockImplementation(() => fromJS({ modules: { 'test-root': { + baseUrl: 'https://example.com/cdn/test-root/2.2.2/', node: { url: 'https://example.com/cdn/test-root/2.2.2/test-root.node.js', integrity: '4y45hr', diff --git a/__tests__/server/middleware/sendHtml.spec.js b/__tests__/server/middleware/sendHtml.spec.js index 1196a4207..b048beec8 100644 --- a/__tests__/server/middleware/sendHtml.spec.js +++ b/__tests__/server/middleware/sendHtml.spec.js @@ -174,6 +174,7 @@ describe('sendHtml', () => { setClientModuleMapCache({ modules: { 'test-root': { + baseUrl: 'https://example.com/cdn/test-root/2.2.2/', node: { url: 'https://example.com/cdn/test-root/2.2.2/test-root.node.js', integrity: '4y45hr', diff --git a/__tests__/server/utils/addBaseUrlToModuleMap.spec.js b/__tests__/server/utils/addBaseUrlToModuleMap.spec.js new file mode 100644 index 000000000..00dea67c8 --- /dev/null +++ b/__tests__/server/utils/addBaseUrlToModuleMap.spec.js @@ -0,0 +1,60 @@ +/* + * Copyright 2019 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import addBaseUrlToModuleMap from '../../../src/server/utils/addBaseUrlToModuleMap'; + +const moduleMap = { + modules: { + 'module-a': { + node: { + url: 'https://example.com/cdn/module-a/1.0.0/module-a.node.js', + integrity: '234', + }, + browser: { + url: 'https://example.com/cdn/module-a/1.0.0/module-a.browser.js', + integrity: '353', + }, + legacyBrowser: { + url: 'https://example.com/cdn/module-a/1.0.0/module-a.legacy.browser.js', + integrity: '0087', + }, + }, + 'module-b': { + node: { + url: 'https://example.com/cdn/module-b/1.0.0/module-b.node.js', + integrity: '0322380', + }, + browser: { + url: 'https://example.com/cdn/module-b/1.0.0/module-b.browser.js', + integrity: 'sd3o23098', + }, + legacyBrowser: { + url: 'https://example.com/cdn/module-b/1.0.0/module-b.legacy.browser.js', + integrity: 'flj23032', + }, + }, + }, +}; + +describe('addBaseUrlToModuleMap', () => { + it('creates a "baseUrl" entry for each module and returns a module map including the new key', () => { + const updatedModuleMap = addBaseUrlToModuleMap(moduleMap); + Object.keys(updatedModuleMap.modules).forEach((moduleName) => { + const module = updatedModuleMap.modules[moduleName]; + expect(module.baseUrl).toBe(`https://example.com/cdn/${moduleName}/1.0.0/`); + }); + }); +}); diff --git a/__tests__/server/utils/clientModuleMapCache.spec.js b/__tests__/server/utils/clientModuleMapCache.spec.js index 1ff0a5cfb..f34d5b898 100644 --- a/__tests__/server/utils/clientModuleMapCache.spec.js +++ b/__tests__/server/utils/clientModuleMapCache.spec.js @@ -62,16 +62,6 @@ describe('clientModuleMapCache', () => { expect(Object.keys(moduleMapCache)).toEqual(cacheKeys); }); - it('creates a "baseUrl" entry for each module and returns a module map including the addition', () => { - // conflicting eslint rules here - // eslint-disable-next-line max-len - cacheKeys.forEach((cacheKey) => Object.keys(moduleMapCache[cacheKey].modules).forEach((moduleName) => { - const module = moduleMapCache[cacheKey].modules[moduleName]; - expect(module.baseUrl).toBe(`https://example.com/cdn/${moduleName}/1.0.0/`); - }) - ); - }); - it('only includes values for a single bundle per module in each map', () => { // conflicting eslint rules here // eslint-disable-next-line max-len diff --git a/__tests__/server/utils/loadModules.spec.jsx b/__tests__/server/utils/loadModules.spec.jsx index 9e2dfeed8..2372fa1ac 100644 --- a/__tests__/server/utils/loadModules.spec.jsx +++ b/__tests__/server/utils/loadModules.spec.jsx @@ -20,6 +20,7 @@ import { CONFIGURATION_KEY } from '../../../src/server/utils/onModuleLoad'; import loadModules from '../../../src/server/utils/loadModules'; import { updateCSP } from '../../../src/server/middleware/csp'; import { setClientModuleMapCache, getClientModuleMapCache } from '../../../src/server/utils/clientModuleMapCache'; +import addBaseUrlToModuleMap from '../../../src/server/utils/addBaseUrlToModuleMap'; // This named export exists only on the mock // eslint-disable-next-line import/named @@ -95,7 +96,7 @@ describe('loadModules', () => { it('updates the holocron module registry', async () => { await loadModules(); expect(updateModuleRegistry).toHaveBeenCalledWith({ - moduleMap, + moduleMap: addBaseUrlToModuleMap(moduleMap), batchModulesToUpdate: require('../../../src/server/utils/batchModulesToUpdate').default, getModulesToUpdate: require('../../../src/server/utils/getModulesToUpdate').default, onModuleLoad: require('../../../src/server/utils/onModuleLoad').default, diff --git a/prod-sample/sample-modules/needy-frank/0.0.0/package-lock.json b/prod-sample/sample-modules/needy-frank/0.0.0/package-lock.json index 14b7c64b0..cd5154a17 100644 --- a/prod-sample/sample-modules/needy-frank/0.0.0/package-lock.json +++ b/prod-sample/sample-modules/needy-frank/0.0.0/package-lock.json @@ -7444,4 +7444,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/server/utils/addBaseUrlToModuleMap.js b/src/server/utils/addBaseUrlToModuleMap.js new file mode 100644 index 000000000..9c0c31c83 --- /dev/null +++ b/src/server/utils/addBaseUrlToModuleMap.js @@ -0,0 +1,32 @@ +/* + * Copyright 2020 American Express Travel Related Services Company, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +/* The baseUrl key in the module map is used by one-app-ducks to construct +the language pack URL pointing at the location of the language pack */ +const addBaseUrlToModuleMap = (moduleMap) => ({ + ...moduleMap, + modules: Object.entries(moduleMap.modules).reduce((acc, [moduleName, moduleBundles]) => ( + { + ...acc, + [moduleName]: { + ...moduleBundles, + baseUrl: moduleBundles.node.url.replace(/[^/]+\.js$/i, ''), + }, + } + ), {}), +}); + +export default addBaseUrlToModuleMap; diff --git a/src/server/utils/clientModuleMapCache.js b/src/server/utils/clientModuleMapCache.js index 34864ed50..bfe5c39c9 100644 --- a/src/server/utils/clientModuleMapCache.js +++ b/src/server/utils/clientModuleMapCache.js @@ -16,6 +16,8 @@ let cache = {}; +/* Filters bundle types so only the required client moduleBundleType is returned +in ../server/middleware/sendHtml.js and reducing the html payload size */ function filterBundles(moduleMap, moduleBundleType) { return { ...moduleMap, @@ -23,7 +25,7 @@ function filterBundles(moduleMap, moduleBundleType) { { ...acc, [moduleName]: { - baseUrl: moduleBundles[moduleBundleType].url.replace(/[^/]+\.js$/i, ''), + baseUrl: moduleBundles.baseUrl, [moduleBundleType]: moduleBundles[moduleBundleType], }, } diff --git a/src/server/utils/loadModules.js b/src/server/utils/loadModules.js index bbac354c6..6362008d0 100644 --- a/src/server/utils/loadModules.js +++ b/src/server/utils/loadModules.js @@ -23,10 +23,11 @@ import getModulesToUpdate from './getModulesToUpdate'; import { getServerStateConfig } from './stateConfig'; import { setClientModuleMapCache } from './clientModuleMapCache'; import { updateCSP } from '../middleware/csp'; +import addBaseUrlToModuleMap from './addBaseUrlToModuleMap'; const loadModules = async () => { const moduleMapResponse = await fetch(process.env.HOLOCRON_MODULE_MAP_URL); - const moduleMap = await moduleMapResponse.json(); + const moduleMap = addBaseUrlToModuleMap(await moduleMapResponse.json()); const serverConfig = getServerStateConfig(); const loadedModules = await updateModuleRegistry({