From 27d7f273aec4e308019c0de3d30b96420d64fa1f Mon Sep 17 00:00:00 2001
From: divyakarippath
Date: Mon, 10 Aug 2020 09:26:54 -0700
Subject: [PATCH] Refactor SSR to improve initial subapp loading performance
(#1717)
* Refactoring to improve performance
* fixing lint error
* fix ssr for prod
---
packages/subapp-web/lib/init.js | 110 ---------
packages/subapp-web/lib/load.js | 426 --------------------------------
2 files changed, 536 deletions(-)
delete mode 100644 packages/subapp-web/lib/init.js
delete mode 100644 packages/subapp-web/lib/load.js
diff --git a/packages/subapp-web/lib/init.js b/packages/subapp-web/lib/init.js
deleted file mode 100644
index deec5c8f28..0000000000
--- a/packages/subapp-web/lib/init.js
+++ /dev/null
@@ -1,110 +0,0 @@
-"use strict";
-
-/* eslint-disable max-statements */
-
-const Fs = require("fs");
-const Path = require("path");
-const util = require("./util");
-const subappUtil = require("subapp-util");
-const _ = require("lodash");
-const assert = require("assert");
-
-module.exports = function setup(setupContext) {
- const cdnEnabled = _.get(setupContext, "routeOptions.cdn.enable");
- const distDir = process.env.NODE_ENV === "production" ? "../dist/min" : "../dist/dev";
- const clientJs = Fs.readFileSync(Path.join(__dirname, distDir, "subapp-web.js")).toString();
- const cdnJs = cdnEnabled
- ? Fs.readFileSync(Path.join(__dirname, distDir, "cdn-map.js")).toString()
- : "";
- const loadJs = Fs.readFileSync(require.resolve("loadjs/dist/loadjs.min.js"), "utf8");
- //
- // TODO: in webpack dev mode, we need to reload stats after there's a change
- //
-
- const metricReport = _.get(setupContext, "routeOptions.reporting", {});
-
- const { assets } = util.loadAssetsFromStats(setupContext.routeOptions.stats);
- assert(assets, `subapp-web unable to load assets from ${setupContext.routeOptions.stats}`);
- setupContext.routeOptions.__internals.assets = assets;
-
- const cdnJsBundles = util.getCdnJsBundles(assets, setupContext.routeOptions);
-
- const bundleAssets = {
- jsChunksById: cdnJsBundles,
- // md === mapping data for other assets
- md: util.getCdnOtherMappings(setupContext.routeOptions),
- entryPoints: assets.entryPoints,
- basePath: ""
- };
-
- let inlineRuntimeJS = "";
- let runtimeEntryPoints = [];
- if (process.env.NODE_ENV === "production") {
- runtimeEntryPoints = Object.keys(assets.chunksById.js).filter(ep =>
- assets.chunksById.js[ep].startsWith("runtime.bundle")
- );
- inlineRuntimeJS =
- "/*rt*/" +
- runtimeEntryPoints
- .map(ep => Path.resolve("dist", "js", Path.basename(cdnJsBundles[ep])))
- .filter(fullPath => Fs.existsSync(fullPath))
- .map(fullPath => Fs.readFileSync(fullPath))
- .join(" ")
- .replace(/\/\/#\ssourceMappingURL=.*$/, "") +
- "/*rt*/";
-
- inlineRuntimeJS += `\nwindow.xarcV1.markBundlesLoaded(${JSON.stringify(runtimeEntryPoints)});`;
- }
-
- const webSubAppJs = `
-`;
-
- let subAppServers;
-
- const getSubAppServers = () => {
- if (subAppServers) {
- return subAppServers;
- }
-
- // TODO: where and how is subApps set in __internals?
- const { subApps } = setupContext.routeOptions.__internals;
-
- // check if any subapp has server side code with initialize method and load them
- return (subAppServers =
- subApps &&
- subApps
- .map(({ subapp }) => subappUtil.loadSubAppServerByName(subapp.name, false))
- .filter(x => x && x.initialize));
- };
-
- return {
- process: context => {
- context.user.assets = assets;
- context.user.includedBundles = {};
- runtimeEntryPoints.forEach(ep => {
- context.user.includedBundles[ep] = true;
- });
-
- if (metricReport.enable && metricReport.reporter) {
- context.user.xarcSSREmitter = util.getEventEmiiter(metricReport.reporter);
- }
-
- getSubAppServers();
-
- // invoke the initialize method of subapp's server code
- if (subAppServers && subAppServers.length > 0) {
- for (const server of getSubAppServers()) {
- server.initialize(context);
- }
- }
-
- return webSubAppJs;
- }
- };
-};
diff --git a/packages/subapp-web/lib/load.js b/packages/subapp-web/lib/load.js
deleted file mode 100644
index 45bb9083ad..0000000000
--- a/packages/subapp-web/lib/load.js
+++ /dev/null
@@ -1,426 +0,0 @@
-"use strict";
-
-/* eslint-disable max-statements, no-console, complexity, no-magic-numbers */
-
-/*
- * - Figure out all the dependencies and bundles a subapp needs and make sure
- * to generate all links to load them for index.html.
- * - If serverSideRendering is enabled, then load and render the subapp for SSR.
- * - Prepare initial state (if redux enabled) or props for the subapp
- * - run renderTo* to generate HTML output
- * - include output in index.html
- * - generate code to bootstrap subapp on client
- */
-
-const assert = require("assert");
-const Fs = require("fs");
-const Path = require("path");
-const _ = require("lodash");
-const retrieveUrl = require("request");
-const util = require("./util");
-const xaa = require("xaa");
-const jsesc = require("jsesc");
-const { loadSubAppByName, loadSubAppServerByName, formUrl } = require("subapp-util");
-
-// global name to store client subapp runtime, ie: window.xarcV1
-// V1: version 1.
-const xarc = "window.xarcV1";
-
-// Size threshold of initial state string to embed it as a application/json script tag
-// It's more efficient to JSON.parse large JSON data instead of embedding them as JS.
-// https://quipblog.com/efficiently-loading-inlined-json-data-911960b0ac0a
-// > The data sizes are as follows: large is 1.7MB of JSON, medium is 130K,
-// > small is 10K and tiny is 781 bytes.
-const INITIAL_STATE_SIZE_FOR_JSON = 1024;
-let INITIAL_STATE_TAG_ID = 0;
-
-const makeDevDebugMessage = (msg, reportLink = true) => {
- const reportMsg = reportLink
- ? `\nError: Please capture this info and submit a bug report at https://github.com/electrode-io/electrode`
- : "";
- return `Error: at ${util.removeCwd(__filename)}
-${msg}${reportMsg}`;
-};
-
-const makeDevDebugHtml = msg => {
- return `DEV ERROR
-${msg}
-`;
-};
-
-module.exports = function setup(setupContext, { props: setupProps }) {
- // TODO: create JSON schema to validate props
-
- // name="Header"
- // async=true
- // defer=true
- // useStream=true
- // serverSideRendering=true
- // hydrateServerData=false
- // clientSideRendering=false
- // inlineScript=true
-
- // TODO: how to export and load subapp
-
- // TODO: Need a way to figure out all the subapps need for a page and send out script
- // tags ASAP in