@americanexpress/holocron-dev-server
Version:
A micro-frontend dev server for Holocron Modules
102 lines (95 loc) • 3.05 kB
JavaScript
/*
* Copyright 2021 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 { fromJS } from 'immutable';
import transit from 'transit-immutable-js';
import React from 'react';
import ReactDOM from 'react-dom/server';
import importJsx from 'import-jsx';
import {
createModuleScriptUrl,
getPublicModulesUrl,
} from './paths';
export function createInitialState({
lang, rootModuleName, errorReportingUrl, ...config
}) {
return transit.toJSON(
fromJS({
config: {
...config,
reportingUrl: errorReportingUrl,
cdnUrl: getPublicModulesUrl(),
rootModuleName,
},
intl: {
activeLocale: lang,
},
})
);
}
export function getWebpackScriptsForLocalModules({ modules = [], moduleMap, rootModuleName }) {
const scripts = [...modules];
// we are creating the script tag info for rendering
// the root module needs to be the first script, and
// we need to ensure that order
// first we check if any of our local modules is a root module
const rootModule = scripts.find(({ rootModule: isRoot }) => isRoot);
if (rootModule) {
// if root module is local, we can sort it to be first
// by using a bool property "rootModule" set on config
scripts.sort(({ rootModule: a }, { rootModule: b }) => {
if (a) return -1;
if (b) return 1;
return 0;
});
} else {
// if there is no local root module, the module map is used to
// set the script as the first module
scripts.unshift({
name: rootModuleName,
src: moduleMap.modules[rootModuleName].browser.url,
});
}
// finally, we need to have the webpack runtime before any local
// modules, including the root module
scripts.unshift({
name: 'runtime',
src: getPublicModulesUrl(createModuleScriptUrl('runtime')),
});
return scripts.map(({ name, src }) => ({ name, src }));
}
export function renderDocument({
modules,
moduleMap,
rootModuleName,
clientConfig,
lang = 'en-US',
}) {
const { default: Document } = importJsx(require.resolve('../components/Document.jsx'));
return '<!DOCTYPE html>'.concat(
ReactDOM.renderToStaticMarkup(
React.createElement(Document, {
lang,
moduleMap,
scripts: [].concat(
getWebpackScriptsForLocalModules({ modules, moduleMap, rootModuleName })
),
initialState: createInitialState({
lang,
rootModuleName,
...clientConfig,
}),
})
)
);
}