Skip to content

Commit

Permalink
[eyeglass] perf: use asset-register-all to register all the assets fo…
Browse files Browse the repository at this point in the history
…r a module, and optimize it to avoid map-merge over maps with many keys.
  • Loading branch information
chriseppstein committed Apr 11, 2019
1 parent 649d020 commit 01779d1
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 26 deletions.
18 changes: 15 additions & 3 deletions packages/eyeglass/sass/assets.scss
Expand Up @@ -18,6 +18,13 @@ $eg-registered-assets: () !default;

@return $uri;
}
@function eyeglass-normalize-assets($assets) {
@if function-exists(-eyeglass-normalize-assets) {
@return -eyeglass-normalize-assets($assets);
}

@return $assets;
}
// Registers many assets for a module at once.
// @param $module string The name of the module to which these assets belong.
// @param $url the source url of the asset. This is what is passed to asset-url().
Expand Down Expand Up @@ -54,10 +61,15 @@ $eg-registered-assets: () !default;
// @param $assets map<string => map> maps source urls to the asset information
// as described in the docs for `$eg-registered-assets` above.
@function asset-register-all($module, $assets) {
// iterate through the given assets and register
@each $key, $asset in $assets {
$trash: asset-register($module, $key, map-get($asset, filepath), map-get($asset, uri));
$assets: eyeglass-normalize-assets($assets);
$mod-assets: map-get($eg-registered-assets, $module);
@if ($mod-assets) {
$mod-assets: map-merge($mod-assets, $assets);
}
@else {
$mod-assets: $assets;
}
$eg-registered-assets: map-merge($eg-registered-assets, ($module: $mod-assets)) !global;
@return null;
}

Expand Down
37 changes: 19 additions & 18 deletions packages/eyeglass/src/assets/AssetsCollection.ts
Expand Up @@ -4,8 +4,6 @@ import { URI } from "../util/URI";
import { Config, AssetSourceOptions } from "../util/Options";
import { SassImplementation } from "../util/SassImplementation";

let assetRegisterTmpl = "@include asset-register(${namespace}, ${name}, ${sourcePath}, ${uri});\n";

export default class AssetsCollection {
options: Config;
sass: SassImplementation;
Expand Down Expand Up @@ -37,26 +35,29 @@ export default class AssetsCollection {
// builds the scss to register all the assets
// this will look something like...
// @import "eyeglass/assets";
// @include asset-register(
// "namespace",
// "path/to/foo.png",
// "/absolute/namespace/path/to/foo.png",
// "namespace/path/to/foo.png"
// @include asset-register-all("namespace",
// "path/to/foo.png": (
// filepath: "/absolute/namespace/path/to/foo.png",
// uri: "namespace/path/to/foo.png"
// ),
// );
return this.sources.reduce((importStr, source) => {
let contents = [
'@import "eyeglass/assets";',
];
for (let source of this.sources) {
// get the assets for the entry
let assets = source.getAssets(name);
let namespace = (stringUtils.quoteJS(this.sass, assets.namespace) || "null");
// reduce the assets into a `asset-register` calls
return importStr + assets.files.reduce((registerStr, asset) => {
return registerStr + stringUtils.tmpl(this.sass, assetRegisterTmpl, {
namespace: namespace,
name: URI.sass(this.sass, asset.name),
sourcePath: URI.sass(this.sass, asset.sourcePath),
uri: URI.sass(this.sass, asset.uri)
});
}, "");
}, '@import "eyeglass/assets";\n');
contents.push(`@include asset-register-all(${namespace}, (`)
for (let asset of assets.files) {
let url = URI.sass(this.sass, asset.name);
let uri = URI.sass(this.sass, asset.uri);
let filepath = URI.sass(this.sass, asset.sourcePath);
contents.push(` ${url}: (filepath: ${filepath}, uri: ${uri}),`)
}
contents.push("));")
}
return contents.join("\n");
}

/**
Expand Down
68 changes: 63 additions & 5 deletions packages/eyeglass/src/functions/normalize-uri.ts
@@ -1,6 +1,6 @@
import { URI } from "../util/URI";
import { IEyeglass } from "../IEyeglass";
import { SassImplementation, isSassString, typeError } from "../util/SassImplementation";
import { SassImplementation, isSassString, typeError, isSassMap } from "../util/SassImplementation";
import { SassFunctionCallback, FunctionDeclarations } from "node-sass";
import * as nodeSass from "node-sass";
const IS_WINDOWS = /win32/.test(require("os").platform());
Expand Down Expand Up @@ -28,18 +28,76 @@ const normalizeURI = function(_eyeglass: IEyeglass, sass: SassImplementation): F
};

if (IS_WINDOWS || process.env.EYEGLASS_NORMALIZE_PATHS) {
methods["-eyeglass-normalize-uri($uri, $type: web)"] = function($uri: nodeSass.types.Value, $type: nodeSass.types.Value, done: SassFunctionCallback) {
let $web = nodeSass.types.String("web");
let $system = nodeSass.types.String("system");
let egNormalizeUri = function($uri: nodeSass.types.Value, $type: nodeSass.types.Value): nodeSass.types.String {
if (!isSassString(sass, $type)) {
return done(typeError(sass, "string", $type));
throw typeError(sass, "string", $type);
}
if (!isSassString(sass, $uri)) {
return done(typeError(sass, "string", $uri));
throw typeError(sass, "string", $uri);
}
let type = $type.getValue() as "web" | "system" | "preserve" | "restore";
let uri = $uri.getValue();
// normalize the uri for the given type
uri = URI[type](uri);
done(sass.types.String(uri));
return sass.types.String(uri);
};
methods["-eyeglass-normalize-uri($uri, $type: web)"] = function($uri: nodeSass.types.Value, $type: nodeSass.types.Value, done: SassFunctionCallback) {
try {
done(egNormalizeUri($uri, $type));
} catch (e) {
done(e);
}
};
methods["-eyeglass-normalize-assets($assets)"] = function($assets: nodeSass.types.Value, done: SassFunctionCallback): void {
if (!isSassMap(sass, $assets)) {
done($assets);
return;
}
let size = $assets.getLength();
let $newAssets = new sass.types.Map(size);
for (let i = 0; i < size; i++) {
let $url = $assets.getKey(i);
if (isSassString(sass, $url)) {
$url = egNormalizeUri($url, $web);
}
$newAssets.setKey(i, $url)
let $assetProps = $assets.getValue(i);
if (isSassMap(sass, $assetProps)) {
let numAssetProps = $assetProps.getLength();
let $newAssetProps = new sass.types.Map(numAssetProps);
for (let pi = 0; pi < numAssetProps; pi++) {
let $propName = $assetProps.getKey(pi);
let $propValue = $assetProps.getValue(pi);
$newAssetProps.setKey(pi, $propName);
if (isSassString(sass, $propName)) {
let propName = $propName.getValue();
try {
switch (propName) {
case "filepath":
$newAssetProps.setValue(pi, egNormalizeUri($propValue, $system));
break;
case "uri":
$newAssetProps.setValue(pi, egNormalizeUri($propValue, $web));
break;
default:
$newAssetProps.setValue(pi, $propValue);
}
} catch(e) {
done(e);
return;
}
} else {
$newAssetProps.setValue(pi, $propValue);
}
}
$newAssets.setValue(i, $newAssetProps);
} else {
$newAssets.setValue(i, $assetProps);
}
}
done($newAssets);
};
}

Expand Down

0 comments on commit 01779d1

Please sign in to comment.