Skip to content

Commit

Permalink
feat: add dynamic imports for .json assets (#2740)
Browse files Browse the repository at this point in the history
Change the default way asset discovery and loading works from static ES6 imports of .json files to dynamic ES6 imports of .json files.
  • Loading branch information
pskelin committed Feb 12, 2021
1 parent f2f3889 commit 46e38fb
Show file tree
Hide file tree
Showing 43 changed files with 532 additions and 500 deletions.
11 changes: 5 additions & 6 deletions packages/base/bundle.esm.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { registerThemeProperties } from "./dist/AssetRegistry.js";
import { registerThemePropertiesLoader } from "./dist/AssetRegistry.js";

// ESM bundle targets browsers with native support
import "./dist/features/OpenUI5Support.js";
Expand All @@ -20,11 +20,10 @@ import { isIE } from "./dist/Device.js";
window.isIE = isIE; // attached to the window object for testing purposes

// used for tests - to register a custom theme
window.registerThemeProperties = registerThemeProperties;
window.registerThemePropertiesLoader = registerThemePropertiesLoader;

// i18n
import "./dist/features/PropertiesFormatSupport.js";
import { registerI18nBundle, fetchI18nBundle, getI18nBundle } from "./dist/i18nBundle.js";
import { registerI18nLoader, fetchI18nBundle, getI18nBundle } from "./dist/i18nBundle.js";

// Note: keep in sync with rollup.config value for IIFE
import { getAnimationMode } from "./dist/config/AnimationMode.js";
Expand All @@ -34,7 +33,7 @@ import { getTheme, setTheme } from "./dist/config/Theme.js";
import { getNoConflict, setNoConflict } from "./dist/config/NoConflict.js";
import { getRTL } from "./dist/config/RTL.js";
import { getFirstDayOfWeek } from "./dist/config/FormatSettings.js";
import { getRegisteredNames as getIconNames } from "./dist/SVGIconRegistry.js"
import { _getRegisteredNames as getIconNames } from "./dist/asset-registries/Icons.js"
window["sap-ui-webcomponents-bundle"] = {
configuration : {
getAnimationMode,
Expand All @@ -48,7 +47,7 @@ window["sap-ui-webcomponents-bundle"] = {
getFirstDayOfWeek,
},
getIconNames,
registerI18nBundle,
registerI18nLoader,
fetchI18nBundle,
getI18nBundle,
renderFinished,
Expand Down
17 changes: 8 additions & 9 deletions packages/base/src/AssetRegistry.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { registerI18nBundle } from "./asset-registries/i18n.js";
import { registerCldr, _registerMappingFunction as registerCldrMappingFunction } from "./asset-registries/LocaleData.js";
import { registerThemeProperties } from "./asset-registries/Themes.js";
import { registerAssetPathMappingFunction } from "./util/EffectiveAssetPath.js";
import { registerI18nLoader } from "./asset-registries/i18n.js";
import { registerLocaleDataLoader } from "./asset-registries/LocaleData.js";
import { registerThemePropertiesLoader } from "./asset-registries/Themes.js";
import { registerIconLoader } from "./asset-registries/Icons.js";

export {
registerCldr,
registerCldrMappingFunction,
registerThemeProperties,
registerI18nBundle,
registerAssetPathMappingFunction,
registerI18nLoader,
registerLocaleDataLoader,
registerThemePropertiesLoader,
registerIconLoader,
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ const mEscapes = {
"\\t": "\t",
};

/**
* Parses a .properties format
* @param {string} sText the contents a of a .properties file
* @returns a object with key/value pairs parsed from the .properties file format
* @public
*/
const parseProperties = sText => {
const properties = {},
aLines = sText.split(rLines);
Expand Down
73 changes: 0 additions & 73 deletions packages/base/src/SVGIconRegistry.js

This file was deleted.

108 changes: 94 additions & 14 deletions packages/base/src/asset-registries/Icons.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { registerIcon, registerCollectionPromise } from "../SVGIconRegistry.js";
import { fetchJsonOnce } from "../util/FetchHelper.js";
import { getEffectiveAssetPath } from "../util/EffectiveAssetPath.js";
import getSharedResource from "../getSharedResource.js";

const loaders = new Map();
const registry = getSharedResource("SVGIcons.registry", new Map());
const iconCollectionPromises = getSharedResource("SVGIcons.promises", new Map());

const ICON_NOT_FOUND = "ICON_NOT_FOUND";
const DEFAULT_COLLECTION = "SAP-icons";

/**
* @deprecated
*/
const registerIconBundle = async (collectionName, bundleData) => {
let resolveFn;
const collectionFetched = new Promise(resolve => {
resolveFn = resolve;
});
registerCollectionPromise(collectionName, collectionFetched);
throw new Error("This method has been removed. Use `registerIconLoader` instead.");
};

if (typeof bundleData !== "object") { // not inlined from build -> fetch it
bundleData = await fetchJsonOnce(getEffectiveAssetPath(bundleData));
const registerIconLoader = async (collectionName, loader) => {
loaders.set(collectionName, loader);
};

const _loadIconCollectionOnce = async collectionName => {
if (!iconCollectionPromises.has(collectionName)) {
const loadIcons = loaders.get(collectionName);
iconCollectionPromises.set(collectionName, loadIcons(collectionName));
}
fillRegistry(bundleData);
resolveFn();

return iconCollectionPromises.get(collectionName);
};

const fillRegistry = bundleData => {
const _fillRegistry = bundleData => {
Object.keys(bundleData.data).forEach(iconName => {
const iconData = bundleData.data[iconName];

Expand All @@ -29,4 +40,73 @@ const fillRegistry = bundleData => {
});
};

export { registerIconBundle }; // eslint-disable-line
// set
const registerIcon = (name, { pathData, ltr, accData, collection } = {}) => { // eslint-disable-line
if (!collection) {
collection = DEFAULT_COLLECTION;
}

const key = `${collection}/${name}`;
registry.set(key, { pathData, ltr, accData });
};

const _parseName = name => {
// silently support ui5-compatible URIs
if (name.startsWith("sap-icon://")) {
name = name.replace("sap-icon://", "");
}

let collection;
[name, collection] = name.split("/").reverse();
collection = collection || DEFAULT_COLLECTION;
// hardcoded alias in case icon explorer is used, resolve `SAP-icons-TNT` to `tnt`
// aliases can be made a feature in the future if more collections need it or more aliases are needed.
if (collection === "SAP-icons-TNT") {
collection = "tnt";
}
const registryKey = `${collection}/${name}`;
return { name, collection, registryKey };
};

const getIconDataSync = nameProp => {
const { registryKey } = _parseName(nameProp);
return registry.get(registryKey);
};

const getIconData = async nameProp => {
const { collection, registryKey } = _parseName(nameProp);

let iconData = ICON_NOT_FOUND;
try {
iconData = await _loadIconCollectionOnce(collection);
} catch (e) {
console.error(e.message); /* eslint-disable-line */
}

if (iconData === ICON_NOT_FOUND) {
return iconData;
}

if (!registry.has(registryKey)) {
// not filled by another await. many getters will await on the same loader, but fill only once
_fillRegistry(iconData);
}
return registry.get(registryKey);
};

// test page usage only
const _getRegisteredNames = async () => {
// fetch one icon of each collection to trigger the bundle load
await getIconData("edit");
await getIconData("tnt/arrow");
return Array.from(registry.keys());
};

export {
registerIconBundle,
registerIconLoader,
getIconData,
getIconDataSync,
registerIcon,
_getRegisteredNames,
};
Loading

0 comments on commit 46e38fb

Please sign in to comment.