diff --git a/packages/subapp-web/lib/init.js b/packages/subapp-web/lib/init.js
index e4d63ea20..3413c28bc 100644
--- a/packages/subapp-web/lib/init.js
+++ b/packages/subapp-web/lib/init.js
@@ -17,30 +17,35 @@ module.exports = function setup(setupContext) {
const routeData = setupContext.routeOptions.__internals;
- const vendorAssets = util.getVendorBundles(routeData.assets);
- const bundleBase = util.getBundleBase(setupContext.routeOptions);
- const bundleNames = vendorAssets.map(a => a.chunkNames[0]);
+ const cdnJsBundles = util.getCdnJsBundles(
+ routeData.assets.byChunkName,
+ setupContext.routeOptions
+ );
+
let vendorBundleLoadJs = "";
let commonScript = "";
+
+ const vendorAssets = util.getVendorBundles(routeData.assets);
+ const bundleNames = vendorAssets.map(a => a.chunkNames[0]);
+
if (vendorAssets.length > 0) {
vendorBundleLoadJs = `markBundlesLoaded(${JSON.stringify(bundleNames)});`;
commonScript = vendorAssets
- .map(a => ``)
+ .map(a => {
+ // map all chunk names that has a URL mapped and load them with script tags
+ return a.chunkNames
+ .map(x => cdnJsBundles[x] && ``)
+ .filter(x => x)
+ .join("");
+ })
.join("\n");
}
- const jsBundleByChunkName = Object.entries(routeData.assets.byChunkName).reduce(
- (a, [name, bundle]) => {
- a[name] = Array.isArray(bundle) ? bundle.find(x => x.endsWith(".js")) : bundle;
- return a;
- },
- {}
- );
-
const bundleAssets = {
- byChunkName: jsBundleByChunkName,
- basePath: bundleBase
+ byChunkName: cdnJsBundles,
+ basePath: ""
};
+
const webSubAppJs = `\n
diff --git a/packages/subapp-web/lib/load.js b/packages/subapp-web/lib/load.js
index 9e98712fa..9e114dc61 100644
--- a/packages/subapp-web/lib/load.js
+++ b/packages/subapp-web/lib/load.js
@@ -35,7 +35,6 @@ module.exports = function setup(setupContext, token) {
const name = props.name;
const routeData = setupContext.routeOptions.__internals;
const bundleAsset = util.getSubAppBundle(name, routeData.assets);
- const bundleJs = bundleAsset.name;
const async = props.async ? " async" : "";
const defer = props.defer ? " defer" : "";
const bundleBase = util.getBundleBase(setupContext.routeOptions);
@@ -43,7 +42,7 @@ module.exports = function setup(setupContext, token) {
const retrieveDevServerBundle = async () => {
return new Promise((resolve, reject) => {
- request(`${bundleBase}${bundleJs}`, (err, resp, body) => {
+ request(`${bundleBase}${bundleAsset.name}`, (err, resp, body) => {
if (err) {
reject(err);
} else {
@@ -56,13 +55,21 @@ module.exports = function setup(setupContext, token) {
let bundleScript;
const webpackDev = process.env.WEBPACK_DEV === "true";
+ const cdnJsBundles = util.getCdnJsBundles(
+ routeData.assets.byChunkName,
+ setupContext.routeOptions
+ );
+
if (props.inlineScript === "always" || (props.inlineScript === true && !webpackDev)) {
if (!webpackDev) {
- const src = Fs.readFileSync(Path.resolve("dist/js", bundleJs)).toString();
+ const src = Fs.readFileSync(Path.resolve("dist/js", bundleAsset.name)).toString();
bundleScript = ``;
}
} else {
- bundleScript = ``;
+ bundleScript = bundleAsset.chunkNames
+ .map(x => cdnJsBundles[x] && ``)
+ .filter(x => x)
+ .join("");
}
let SubApp;
diff --git a/packages/subapp-web/lib/util.js b/packages/subapp-web/lib/util.js
index 6f6da4ad7..830d407b5 100644
--- a/packages/subapp-web/lib/util.js
+++ b/packages/subapp-web/lib/util.js
@@ -1,10 +1,14 @@
"use strict";
-/* eslint-disable global-require */
+/* eslint-disable global-require, max-statements */
const assert = require("assert");
+const Path = require("path");
-module.exports = {
+let CDN_ASSETS;
+let CDN_JS_BUNDLES;
+
+const utils = {
getVendorBundles: assets => {
const chunkNames = Object.keys(assets.byChunkName)
.filter(x => x.startsWith("vendors"))
@@ -34,5 +38,78 @@ module.exports = {
} else {
return routeData.devBundleBase;
}
+ },
+
+ /*
+ From an object of bundles:
+
+ {
+ bundleName: "bundle-file.js"
+ }
+
+ map with a CDN assets object:
+
+ {
+ "/dist/js/bundle-file.js": "/cdn.com/hash-12345.js"
+ }
+
+ to:
+
+ {
+ bundleName: "/cdn.com/hash-12345.js"
+ }
+
+ If a bundleName doesn't have a CDN map, then its URL is created by prepending basePath:
+
+ {
+ bundleName: "${basePath}bundle-file.js"
+ }
+ */
+
+ mapCdnAssets(bundlesByName, basePath = "", assetsFile = "config/assets.json") {
+ if (!CDN_ASSETS) {
+ const assetsFp = Path.resolve(assetsFile);
+ try {
+ CDN_ASSETS = require(assetsFp);
+ } catch (err) {
+ CDN_ASSETS = {};
+ }
+ }
+
+ const cdnBundles = {};
+ const bundleNames = Object.keys(bundlesByName);
+
+ for (const name of bundleNames) {
+ const bundleFile = bundlesByName[name];
+ for (const mapName in CDN_ASSETS) {
+ if (mapName.endsWith(bundleFile)) {
+ cdnBundles[name] = CDN_ASSETS[mapName];
+ break;
+ }
+ }
+
+ if (!cdnBundles[name]) {
+ cdnBundles[name] = basePath.concat(bundlesByName[name]);
+ }
+ }
+
+ return cdnBundles;
+ },
+
+ getCdnJsBundles(byChunkNameAssets, routeOptions) {
+ if (CDN_JS_BUNDLES) {
+ return CDN_JS_BUNDLES;
+ }
+
+ const jsBundleByChunkName = Object.entries(byChunkNameAssets).reduce((a, [name, bundle]) => {
+ a[name] = Array.isArray(bundle) ? bundle.find(x => x.endsWith(".js")) : bundle;
+ return a;
+ }, {});
+
+ const bundleBase = utils.getBundleBase(routeOptions);
+
+ return (CDN_JS_BUNDLES = utils.mapCdnAssets(jsBundleByChunkName, bundleBase));
}
};
+
+module.exports = utils;