From 3b6fddc746307ce4a8fce377418222260cd26c7f Mon Sep 17 00:00:00 2001 From: Jean Lauliac Date: Fri, 22 Sep 2017 07:20:08 -0700 Subject: [PATCH] RN buck: move asset work into transform worker Reviewed By: davidaurelio Differential Revision: D5872268 fbshipit-source-id: 829a0d26930f8893b93a5f42ef7026350dc01f29 --- .../src/ModuleGraph/types.flow.js | 39 ++++++++++++++++++- .../src/ModuleGraph/worker/Platforms.js | 23 +++++++++++ .../ModuleGraph/worker/transform-module.js | 31 ++++++++++++--- 3 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 packages/metro-bundler/src/ModuleGraph/worker/Platforms.js diff --git a/packages/metro-bundler/src/ModuleGraph/types.flow.js b/packages/metro-bundler/src/ModuleGraph/types.flow.js index 8b4f7401..89419814 100644 --- a/packages/metro-bundler/src/ModuleGraph/types.flow.js +++ b/packages/metro-bundler/src/ModuleGraph/types.flow.js @@ -141,9 +141,46 @@ export type TransformedCodeFile = { +type: CodeFileTypes, }; +export type ImageSize = {|+width: number, +height: number|}; + export type AssetFile = {| - +assetContentBase64: string, + /** + * The path of the asset that is shared by all potential variants + * of this asset. For example `foo/bar@3x.png` would have the + * asset path `foo/bar.png`. + */ + +assetPath: string, + /** + * The content is encoded in Base64 so that it can be stored in JSON files, + * that are used to communicate between different commands of a Buck + * build worker, for example. + */ + +contentBase64: string, + /** + * Guessed from the file extension, for example `png` or `html`. + */ + +contentType: string, + /** + * The path of the original file for this asset. For example + * `foo/bar@3x.ios.png`. This is most useful for reporting purposes, such as + * error messages. + */ +filePath: string, + /** + * If the asset is an image, this contain the size in physical pixels (ie. + * regarless of whether it's a `@2x` or `@3x` version of a smaller image). + */ + +physicalSize: ?ImageSize, + /** + * The platform this asset is designed for, for example `ios` if the file name + * is `foo.ios.js`. `null` if the asset is not platform-specific. + */ + +platform: ?string, + /** + * The scale this asset is designed for, for example `2` + * if the file name is `foo@2x.png`. + */ + +scale: number, |}; export type TransformedSourceFile = diff --git a/packages/metro-bundler/src/ModuleGraph/worker/Platforms.js b/packages/metro-bundler/src/ModuleGraph/worker/Platforms.js new file mode 100644 index 00000000..9db8a832 --- /dev/null +++ b/packages/metro-bundler/src/ModuleGraph/worker/Platforms.js @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2016-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. + * + * @flow + * @format + */ + +'use strict'; + +/** + * By knowing all the valid platforms, we're able to say that "foo.ios.png" is + * effectively the asset "foo" specific to "ios", and not a generic asset + * "foo.ios". This is important so that we can discard asset variants that don't + * match the platform being built. + */ +const VALID_PLATFORMS: Set = new Set(['ios', 'android', 'web']); + +module.exports = {VALID_PLATFORMS}; diff --git a/packages/metro-bundler/src/ModuleGraph/worker/transform-module.js b/packages/metro-bundler/src/ModuleGraph/worker/transform-module.js index 809ba72c..07f3b83a 100644 --- a/packages/metro-bundler/src/ModuleGraph/worker/transform-module.js +++ b/packages/metro-bundler/src/ModuleGraph/worker/transform-module.js @@ -12,19 +12,24 @@ 'use strict'; +const AssetPaths = require('../../node-haste/lib/AssetPaths'); const JsFileWrapping = require('./JsFileWrapping'); +const Platforms = require('./Platforms'); const collectDependencies = require('./collect-dependencies'); const defaults = require('../../defaults'); const docblock = require('jest-docblock'); const generate = require('./generate'); +const getImageSize = require('image-size'); const invariant = require('fbjs/lib/invariant'); const path = require('path'); +const {isAssetTypeAnImage} = require('../../Bundler/util'); const {basename} = require('path'); import type {HasteImpl} from '../../node-haste/Module'; import type { + ImageSize, TransformedCodeFile, TransformedSourceFile, Transformer, @@ -147,13 +152,27 @@ function transformAsset( content: Buffer, options: TransformOptions, ): TransformedSourceFile { - return { - details: { - assetContentBase64: content.toString('base64'), - filePath: options.filename, - }, - type: 'asset', + const filePath = options.filename; + const assetData = AssetPaths.parse(filePath, Platforms.VALID_PLATFORMS); + const contentType = path.extname(filePath).slice(1); + const details = { + assetPath: assetData.assetName, + contentBase64: content.toString('base64'), + contentType, + filePath, + physicalSize: getAssetSize(contentType, content), + platform: assetData.platform, + scale: assetData.resolution, }; + return {details, type: 'asset'}; +} + +function getAssetSize(type: string, content: Buffer): ?ImageSize { + if (!isAssetTypeAnImage(type)) { + return null; + } + const {width, height} = getImageSize(content); + return {width, height}; } function makeResult(ast: Ast, filename, sourceCode, isPolyfill = false) {