Skip to content

Commit

Permalink
[minor] Loading subapps from a different repo (#1700)
Browse files Browse the repository at this point in the history
  • Loading branch information
divyakarippath authored Jul 16, 2020
1 parent 1471872 commit c3e45e0
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 17 deletions.
14 changes: 11 additions & 3 deletions packages/subapp-server/lib/setup-hapi-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,25 @@ function setupRouteRender({ subAppsByPath, srcDir, routeOptions }) {
// load subapps for the route
if (routeOptions.subApps) {
routeOptions.__internals.subApps = [].concat(routeOptions.subApps).map(x => {
let options = {};
let options;
if (Array.isArray(x)) {
options = x[1];
x = x[0];
}
// absolute: use as path
// module: resolve module path
// else: assume dir under srcDir
// TBD: handle it being a module
if (!x.startsWith(".") && !x.startsWith("/")) {
const subAppPath = optionalRequire.resolve(x);
if (subAppPath) {
const { manifest, subAppOptions } = require(x);
x = manifest ? Path.dirname(subAppPath) : x;
options = options || subAppOptions;
}
}
return {
subapp: subAppsByPath[Path.isAbsolute(x) ? x : Path.resolve(srcDir, x)],
options
options: options || {}
};
});
}
Expand Down
54 changes: 47 additions & 7 deletions packages/subapp-util/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
const Url = require("url");
const Path = require("path");
const assert = require("assert");
const _ = require("lodash");
const optionalRequire = require("optional-require")(require);
const scanDir = require("filter-scan-dir");
const appMode = optionalRequire(Path.resolve(".prod/.app-mode.json"), { default: {} });
Expand All @@ -29,6 +30,18 @@ function removeExt(f) {
return ix > 0 ? f.substring(0, ix) : f;
}

const validateModuleManifest = manifest => {
const entries = _.pick(manifest, ["entry", "serverEntry", "reducers"]);
Object.keys(entries).forEach(x => {
if (!Path.isAbsolute(entries[x])) {
throw new Error(
`Could not resolve subapp ${x} "${entries[x]}".\
Please provide absolute path to the ${x} in subapp manifest`
);
}
});
};

//
// scan a subapp's directory for additional things:
// - server side entry in server.js, server-{name}.js, server-{verbatimName}.js
Expand Down Expand Up @@ -122,11 +135,12 @@ function scanSubAppsFromDir(srcDir, maxLevel = Infinity) {
const fullSrcDir = Path.resolve(srcDir);

const subApps = { [MAP_BY_PATH_SYM]: {} };
const { maniFiles = [], files = [] } = scanDir.sync({
const { maniFiles = [], files = [], modFiles = [] } = scanDir.sync({
dir: srcDir,
grouping: true,
maxLevel,
filter: (f, p, ex) => {
if (ex.noExt === "subapps-modules") return "modFiles";
if (ex.noExt === "subapp-manifest") return "maniFiles";
return f.startsWith("subapp");
},
Expand Down Expand Up @@ -162,7 +176,25 @@ function scanSubAppsFromDir(srcDir, maxLevel = Infinity) {
return null;
});

const errors = [].concat(errors1, errors2).filter(x => x);
// process subapps modules
let errors3 = [];
if (modFiles.length > 0) {
const manifests = es6Require(Path.join(fullSrcDir, modFiles[0]));
errors3 = Object.keys(manifests).map(modName => {
try {
const manifest = manifests[modName];
validateModuleManifest(manifest);
const modFullDir = Path.dirname(require.resolve(modName));
const subapp = Object.assign({ subAppDir: modName, module: true }, manifest);
subApps[manifest.name] = subApps[MAP_BY_PATH_SYM][modFullDir] = subapp;
} catch (error) {
return error;
}
return null;
});
}

const errors = [].concat(errors1, errors2, errors3).filter(x => x);
if (errors.length > 0) {
console.error("Loading SubApps failed");
errors.forEach(err => {
Expand Down Expand Up @@ -242,7 +274,7 @@ function loadSubAppByName(name) {
const container = getSubAppContainer();
const subAppDir = manifest.subAppDir;
// load subapp's entry
xrequire(Path.resolve(appSrcDir(), subAppDir, manifest.entry));
xrequire(manifest.module ? manifest.entry : Path.resolve(appSrcDir(), subAppDir, manifest.entry));

// if subapp did not register itself then register it
if (!container[name]) {
Expand All @@ -258,13 +290,17 @@ function loadSubAppServerByName(name) {
const { subAppDir, serverEntry } = manifest;

if (serverEntry) {
return es6Require(Path.resolve(appSrcDir(), subAppDir, serverEntry));
return es6Require(
manifest.module ? serverEntry : Path.resolve(appSrcDir(), subAppDir, serverEntry)
);
} else if (serverEntry === false) {
return {};
}

// generate a server from subapp's main file
const subapp = es6Require(Path.resolve(appSrcDir(), subAppDir, manifest.entry));
const subapp = es6Require(
manifest.module ? manifest.entry : Path.resolve(appSrcDir(), subAppDir, manifest.entry)
);

return {
StartComponent: subapp.Component
Expand All @@ -275,11 +311,15 @@ function refreshSubAppByName(name) {
const manifest = subAppManifest()[name];
const { subAppDir } = manifest;

const entryFullPath = xrequire.resolve(Path.resolve(appSrcDir(), subAppDir, manifest.entry));
const entryFullPath = xrequire.resolve(
manifest.module ? manifest.entry : Path.resolve(appSrcDir(), subAppDir, manifest.entry)
);
if (!xrequire.cache[entryFullPath] && manifest.serverEntry) {
// also reload server side module
const serverEntryFullPath = xrequire.resolve(
Path.resolve(appSrcDir(), subAppDir, manifest.serverEntry)
manifest.module
? manifest.serverEntry
: Path.resolve(appSrcDir(), subAppDir, manifest.serverEntry)
);
console.log("reloading server side subapp", name, serverEntryFullPath);
delete xrequire.cache[serverEntryFullPath];
Expand Down
11 changes: 7 additions & 4 deletions packages/xarc-webpack/lib/partials/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,24 @@ function makeEntryPartial() {
}

function genSubAppHmrEntry(hmrDir, isDev, manifest) {
let subAppReq = `${manifest.subAppDir}/${manifest.entry}`;
let subAppReq = manifest.module ? manifest.entry : `${manifest.subAppDir}/${manifest.entry}`;

// subapp has built-in code to handle HMR accept
// or not running in webpack dev mode
// => do not generate HMR accept code
if (manifest.hmrSelfAccept || !isDev) {
return `./${subAppReq}`;
return manifest.module ? subAppReq : `./${subAppReq}`;
}

const hmrEntry = `hmr-${manifest.subAppDir.replace(/[\/\\]/g, "-")}.js`;
subAppReq = `../${subAppReq}`;
subAppReq = manifest.module ? subAppReq : `../${subAppReq}`;

let reducerHmrCode = "";

if (manifest.reducers) {
const subAppReducers = `../${manifest.subAppDir}/reducers`;
const subAppReducers = manifest.module
? manifest.reducers
: `../${manifest.subAppDir}/reducers`;
reducerHmrCode = `
import { getReduxCreateStore } from "subapp-redux";
import reducers from "${subAppReducers}";
Expand Down
1 change: 1 addition & 0 deletions samples/demo-tree-shaking/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"lodash": "^4.17.10",
"milligram": "^1.3.0",
"react-intl": "^3.11.0",
"intl-format-cache": "4.2.46",
"react-notify-toast": "^0.4.1",
"react-router-config": "^5.1.1"
},
Expand Down
5 changes: 2 additions & 3 deletions samples/react-jest-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
"@xarc/app-dev": "^5.3.4",
"electrode-archetype-opt-critical-css": "^1.0.3",
"electrode-archetype-opt-eslint": "^1.0.3",
"electrode-archetype-opt-jest": "^25.0.0",
"electrode-archetype-opt-jest": "^26.0.0",
"electrode-archetype-opt-less": "^1.0.2",
"electrode-archetype-opt-mocha": "^1.0.3",
"electrode-archetype-opt-phantomjs": "^1.0.2",
Expand All @@ -80,8 +80,7 @@
"electrode-auto-ssr": "../../packages/electrode-auto-ssr"
},
"devDependencies": {
"@xarc/app-dev": "../../packages/xarc-app-dev",
"electrode-archetype-opt-jest": "../../packages/electrode-archetype-opt-jest"
"@xarc/app-dev": "../../packages/xarc-app-dev"
}
},
"optionalDependencies": {}
Expand Down

0 comments on commit c3e45e0

Please sign in to comment.