mirror of https://github.com/status-im/metro.git
Support for remote assets
Reviewed By: davidaurelio Differential Revision: D6030886 fbshipit-source-id: c188b39e104f5c3f65a98336fecbffc93091ff4c
This commit is contained in:
parent
1a2a46a9fb
commit
0fdf36d06d
|
@ -89,9 +89,9 @@ type __TransformOptions = {
|
|||
|
||||
type _TransformOptions =
|
||||
__TransformOptions & {env?: {[key: string]: __TransformOptions}};
|
||||
declare class _Ast {}
|
||||
declare class Ast {}
|
||||
type TransformResult = {
|
||||
ast: _Ast,
|
||||
ast: Ast,
|
||||
code: ?string,
|
||||
ignored: boolean,
|
||||
map: ?_SourceMap,
|
||||
|
@ -101,14 +101,14 @@ type VisitFn = <State>(path: Object, state: State) => any;
|
|||
declare module 'babel-core' {
|
||||
declare type Plugins = _Plugins;
|
||||
declare type SourceMap = _SourceMap;
|
||||
declare type Ast = _Ast;
|
||||
declare type Ast = Ast;
|
||||
declare type TransformOptions = _TransformOptions;
|
||||
declare function transform(
|
||||
code: string,
|
||||
options?: _TransformOptions,
|
||||
): TransformResult;
|
||||
declare function traverse<State>(
|
||||
ast: _Ast,
|
||||
ast: Ast,
|
||||
visitor: {[key: string]: VisitFn<State> |
|
||||
{enter?: VisitFn<State>, exit?: VisitFn<State>}},
|
||||
scope?: ?Object,
|
||||
|
@ -117,7 +117,7 @@ declare module 'babel-core' {
|
|||
): void;
|
||||
declare var types: {[key: string]: Function};
|
||||
declare function transformFromAst(
|
||||
ast: _Ast,
|
||||
ast: Ast,
|
||||
code?: ?string,
|
||||
babelOptions?: _TransformOptions,
|
||||
): TransformResult;
|
||||
|
@ -133,7 +133,7 @@ type RawMapping = {
|
|||
declare module 'babel-generator' {
|
||||
declare type RawMapping = RawMapping;
|
||||
declare function exports(
|
||||
ast: _Ast,
|
||||
ast: Ast,
|
||||
options?: GeneratorOptions,
|
||||
): TransformResult & {rawMappings: ?Array<RawMapping>};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @emails oncall+javascript_foundation
|
||||
* @format
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const generator = require('babel-generator').default;
|
||||
const util = require('../util');
|
||||
|
||||
it('generates the right AST for remote assets', () => {
|
||||
const asset = {
|
||||
__packager_asset: true,
|
||||
fileSystemLocation: '/js/RKJSModules/Apps/Wilde/AdsPayments/images',
|
||||
hash: '3e9b7b3c4d4fa37f9eb580dc426412dbde2925ff',
|
||||
height: 48,
|
||||
httpServerLocation: '/assets/RKJSModules/Apps/Wilde/AdsPayments/images',
|
||||
name: 'pending',
|
||||
scales: [1.5, 2, 3, 4],
|
||||
type: 'png',
|
||||
width: 48,
|
||||
};
|
||||
|
||||
const map = {
|
||||
'/js/RKJSModules/Apps/Wilde/AdsPayments/images': {
|
||||
pending: {
|
||||
'2': 'img2x',
|
||||
'3': 'img3x',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const {ast} = util.generateRemoteAssetCodeFileAst(
|
||||
'gen',
|
||||
asset,
|
||||
'https://remote.server.com/',
|
||||
map,
|
||||
);
|
||||
|
||||
const code = generator(ast, {minified: true}).code;
|
||||
|
||||
expect(code).toBe(
|
||||
'module.exports={"uri":"https://remote.server.com/"+{"2":"img2x","3":"img3x"}[require("gen").pickScale([2,3])]};',
|
||||
);
|
||||
});
|
|
@ -86,7 +86,6 @@ export type AssetDescriptor = {
|
|||
|
||||
export type ExtendedAssetDescriptor = AssetDescriptor & {
|
||||
+fileSystemLocation: string,
|
||||
+files: Array<string>,
|
||||
};
|
||||
|
||||
const sizeOf = denodeify(imageSize);
|
||||
|
|
|
@ -16,7 +16,7 @@ const babel = require('babel-core');
|
|||
const babelGenerate = require('babel-generator').default;
|
||||
const babylon = require('babylon');
|
||||
|
||||
import type {AssetDescriptor} from '.';
|
||||
import type {AssetDescriptor, ExtendedAssetDescriptor} from '.';
|
||||
import type {ModuleTransportLike} from '../shared/types.flow';
|
||||
|
||||
type SubTree<T: ModuleTransportLike> = (
|
||||
|
@ -26,10 +26,104 @@ type SubTree<T: ModuleTransportLike> = (
|
|||
|
||||
const assetPropertyBlacklist = new Set(['files', 'fileSystemLocation', 'path']);
|
||||
|
||||
// Structure of the object: dir.name.scale = asset
|
||||
export type RemoteFileMap = {
|
||||
[string]: {
|
||||
[string]: {
|
||||
[number]: string,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Structure of the object: platform.dir.name.scale = asset
|
||||
export type PlatformRemoteFileMap = {
|
||||
['ios' | 'android']: RemoteFileMap,
|
||||
};
|
||||
|
||||
type AssetResult = {
|
||||
remote: boolean,
|
||||
ast: Ast,
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the code involved in requiring an asset, but to be loaded remotely.
|
||||
* If the asset cannot be found within the map, then it falls back to the
|
||||
* standard asset.
|
||||
*/
|
||||
function generateRemoteAssetCodeFileAst(
|
||||
assetSourceResolverPath: string,
|
||||
assetDescriptor: ExtendedAssetDescriptor,
|
||||
remoteServer: string,
|
||||
remoteFileMap: RemoteFileMap,
|
||||
): ?AssetResult {
|
||||
const t = babel.types;
|
||||
|
||||
const file = remoteFileMap[assetDescriptor.fileSystemLocation];
|
||||
const descriptor = file && file[assetDescriptor.name];
|
||||
|
||||
if (!descriptor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// require('AssetSourceResolver')
|
||||
const requireCall = t.callExpression(t.identifier('require'), [
|
||||
t.stringLiteral(assetSourceResolverPath),
|
||||
]);
|
||||
|
||||
// require('AssetSourceResolver').pickScale
|
||||
const pickScale = t.memberExpression(requireCall, t.identifier('pickScale'));
|
||||
|
||||
// require('AssetSourceResolver').pickScale([2, 3, ...])
|
||||
const call = t.callExpression(pickScale, [
|
||||
t.arrayExpression(
|
||||
Object.keys(descriptor)
|
||||
.map(Number)
|
||||
.sort((a, b) => a - b)
|
||||
.map(scale => t.numericLiteral(scale)),
|
||||
),
|
||||
]);
|
||||
|
||||
// {2: 'path/to/image@2x', 3: 'path/to/image@3x', ...}
|
||||
const data = babylon.parseExpression(JSON.stringify(descriptor));
|
||||
|
||||
// ({2: '...', 3: '...'})[require(...).pickScale(...)]
|
||||
const handler = t.memberExpression(data, call, true);
|
||||
|
||||
// 'https://remote.server.com/' + ({2: ...})[require(...).pickScale(...)]
|
||||
const result = t.binaryExpression(
|
||||
'+',
|
||||
t.stringLiteral(remoteServer),
|
||||
handler,
|
||||
);
|
||||
|
||||
// module.exports
|
||||
const moduleExports = t.memberExpression(
|
||||
t.identifier('module'),
|
||||
t.identifier('exports'),
|
||||
);
|
||||
|
||||
return {
|
||||
remote: true,
|
||||
ast: t.file(
|
||||
t.program([
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression(
|
||||
'=',
|
||||
moduleExports,
|
||||
t.objectExpression([
|
||||
t.objectProperty(t.stringLiteral('uri'), result),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function generateAssetCodeFileAst(
|
||||
assetRegistryPath: string,
|
||||
assetDescriptor: AssetDescriptor,
|
||||
): Object {
|
||||
): AssetResult {
|
||||
const properDescriptor = filterObject(
|
||||
assetDescriptor,
|
||||
assetPropertyBlacklist,
|
||||
|
@ -52,13 +146,16 @@ function generateAssetCodeFileAst(
|
|||
const registerAssetCall = t.callExpression(registerAssetFunction, [
|
||||
descriptorAst,
|
||||
]);
|
||||
return t.file(
|
||||
t.program([
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression('=', moduleExports, registerAssetCall),
|
||||
),
|
||||
]),
|
||||
);
|
||||
return {
|
||||
remote: false,
|
||||
ast: t.file(
|
||||
t.program([
|
||||
t.expressionStatement(
|
||||
t.assignmentExpression('=', moduleExports, registerAssetCall),
|
||||
),
|
||||
]),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
function generateAssetTransformResult(
|
||||
|
@ -70,7 +167,7 @@ function generateAssetTransformResult(
|
|||
dependencyOffsets: Array<number>,
|
||||
|} {
|
||||
const {code} = babelGenerate(
|
||||
generateAssetCodeFileAst(assetRegistryPath, assetDescriptor),
|
||||
generateAssetCodeFileAst(assetRegistryPath, assetDescriptor).ast,
|
||||
{comments: false, compact: true},
|
||||
);
|
||||
const dependencies = [assetRegistryPath];
|
||||
|
@ -177,5 +274,6 @@ module.exports = {
|
|||
createRamBundleGroups,
|
||||
generateAssetCodeFileAst,
|
||||
generateAssetTransformResult,
|
||||
generateRemoteAssetCodeFileAst,
|
||||
isAssetTypeAnImage,
|
||||
};
|
||||
|
|
|
@ -157,6 +157,7 @@ export type TransformedCodeFile = {
|
|||
+hasteID: ?string,
|
||||
package?: PackageData,
|
||||
+transformed: TransformResults,
|
||||
+remoteAsset?: boolean,
|
||||
+type: CodeFileTypes,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue