diff --git a/react-packager/src/Bundler/__tests__/Bundler-test.js b/react-packager/src/Bundler/__tests__/Bundler-test.js index b397f24e..74a246b8 100644 --- a/react-packager/src/Bundler/__tests__/Bundler-test.js +++ b/react-packager/src/Bundler/__tests__/Bundler-test.js @@ -24,6 +24,27 @@ var sizeOf = require('image-size'); var fs = require('fs'); describe('Bundler', function() { + + function createModule({ + path, + id, + dependencies, + isAsset, + isAsset_DEPRECATED, + isJSON, + resolution, + }) { + return { + path, + resolution, + getDependencies() { return Promise.resolve(dependencies); }, + getName() { return Promise.resolve(id); }, + isJSON() { return isJSON; }, + isAsset() { return isAsset; }, + isAsset_DEPRECATED() { return isAsset_DEPRECATED; }, + }; + } + var getDependencies; var wrapModule; var bundler; @@ -59,27 +80,6 @@ describe('Bundler', function() { assetServer: assetServer, }); - - function createModule({ - path, - id, - dependencies, - isAsset, - isAsset_DEPRECATED, - isJSON, - resolution, - }) { - return { - path, - resolution, - getDependencies() { return Promise.resolve(dependencies); }, - getName() { return Promise.resolve(id); }, - isJSON() { return isJSON; }, - isAsset() { return isAsset; }, - isAsset_DEPRECATED() { return isAsset_DEPRECATED; }, - }; - } - modules = [ createModule({id: 'foo', path: '/root/foo.js', dependencies: []}), createModule({id: 'bar', path: '/root/bar.js', dependencies: []}), @@ -129,18 +129,23 @@ describe('Bundler', function() { sizeOf.mockImpl(function(path, cb) { cb(null, { width: 50, height: 100 }); }); + }); - assetServer.getAssetData.mockImpl(function() { + pit('create a bundle', function() { + assetServer.getAssetData.mockImpl(() => { return { scales: [1,2,3], + files: [ + '/root/img/img.png', + '/root/img/img@2x.png', + '/root/img/img@3x.png', + ], hash: 'i am a hash', name: 'img', type: 'png', }; }); - }); - pit('create a bundle', function() { return bundler.bundle('/root/foo.js', true, 'source_map_url') .then(function(p) { expect(p.addModule.mock.calls[0][0]).toEqual({ @@ -186,6 +191,11 @@ describe('Bundler', function() { width: 25, height: 50, scales: [1, 2, 3], + files: [ + '/root/img/img.png', + '/root/img/img@2x.png', + '/root/img/img@3x.png', + ], hash: 'i am a hash', name: 'img', type: 'png', @@ -235,4 +245,64 @@ describe('Bundler', function() { .toBeCalledWith('/root/foo.js', { dev: true }) ); }); + + describe('getOrderedDependencyPaths', () => { + beforeEach(() => { + assetServer.getAssetData.mockImpl(function(relPath) { + if (relPath === 'img/new_image.png') { + return { + scales: [1,2,3], + files: [ + '/root/img/new_image.png', + '/root/img/new_image@2x.png', + '/root/img/new_image@3x.png', + ], + hash: 'i am a hash', + name: 'img', + type: 'png', + }; + } else if (relPath === 'img/new_image2.png') { + return { + scales: [1,2,3], + files: [ + '/root/img/new_image2.png', + '/root/img/new_image2@2x.png', + '/root/img/new_image2@3x.png', + ], + hash: 'i am a hash', + name: 'img', + type: 'png', + }; + } + + throw new Error('unknown image ' + relPath); + }); + }); + + pit('should get the concrete list of all dependency files', () => { + modules.push( + createModule({ + id: 'new_image2.png', + path: '/root/img/new_image2.png', + isAsset: true, + resolution: 2, + dependencies: [] + }), + ); + + return bundler.getOrderedDependencyPaths('/root/foo.js', true) + .then((paths) => expect(paths).toEqual([ + '/root/foo.js', + '/root/bar.js', + '/root/img/img.png', + '/root/img/new_image.png', + '/root/img/new_image@2x.png', + '/root/img/new_image@3x.png', + '/root/file.json', + '/root/img/new_image2.png', + '/root/img/new_image2@2x.png', + '/root/img/new_image2@3x.png', + ])); + }); + }); }); diff --git a/react-packager/src/Bundler/index.js b/react-packager/src/Bundler/index.js index d2d8ae7f..289911d4 100644 --- a/react-packager/src/Bundler/index.js +++ b/react-packager/src/Bundler/index.js @@ -187,6 +187,38 @@ class Bundler { return this._resolver.getDependencies(main, { dev: isDev, platform }); } + getOrderedDependencyPaths({ entryFile, dev, platform }) { + return this.getDependencies(entryFile, dev, platform).then( + ({ dependencies }) => { + const ret = []; + const promises = []; + const placeHolder = {}; + dependencies.forEach(dep => { + if (dep.isAsset()) { + const relPath = getPathRelativeToRoot( + this._projectRoots, + dep.path + ); + promises.push( + this._assetServer.getAssetData(relPath, platform) + ); + ret.push(placeHolder); + } else { + ret.push(dep.path); + } + }); + + return Promise.all(promises).then(assetsData => { + assetsData.forEach(({ files }) => { + const index = ret.indexOf(placeHolder); + ret.splice(index, 1, ...files); + }); + return ret; + }); + } + ); + } + _transformModule(bundle, response, module, platform = null) { let transform; diff --git a/react-packager/src/Server/index.js b/react-packager/src/Server/index.js index 346f4bcb..74e83927 100644 --- a/react-packager/src/Server/index.js +++ b/react-packager/src/Server/index.js @@ -200,6 +200,13 @@ class Server { }); } + getOrderedDependencyPaths(options) { + return Promise.resolve().then(() => { + const opts = dependencyOpts(options); + return this._bundler.getOrderedDependencyPaths(opts); + }); + } + _onFileChange(type, filepath, root) { const absPath = path.join(root, filepath); this._bundler.invalidateFile(absPath); diff --git a/react-packager/src/SocketInterface/SocketClient.js b/react-packager/src/SocketInterface/SocketClient.js index b89f5cca..41ce0df1 100644 --- a/react-packager/src/SocketInterface/SocketClient.js +++ b/react-packager/src/SocketInterface/SocketClient.js @@ -86,6 +86,13 @@ class SocketClient { }); } + getOrderedDependencyPaths(main) { + return this._send({ + type: 'getOrderedDependencyPaths', + data: main, + }); + } + buildBundle(options) { return this._send({ type: 'buildBundle', diff --git a/react-packager/src/SocketInterface/SocketServer.js b/react-packager/src/SocketInterface/SocketServer.js index 5098ea87..8258873a 100644 --- a/react-packager/src/SocketInterface/SocketServer.js +++ b/react-packager/src/SocketInterface/SocketServer.js @@ -121,6 +121,14 @@ class SocketServer { ); break; + case 'getOrderedDependencyPaths': + this._jobs++; + this._packagerServer.getOrderedDependencyPaths(m.data).then( + (dependencies) => this._reply(sock, m.id, 'result', dependencies), + handleError, + ); + break; + default: this._reply(sock, m.id, 'error', 'Unknown message type: ' + m.type); }