From ce421a5878be5567ef05b39a29ea875fb92cd1c9 Mon Sep 17 00:00:00 2001 From: leeyeh Date: Mon, 31 Aug 2015 13:03:16 +0800 Subject: [PATCH] [react-packager] Add package to file redirection support. According to the browser field spec for package.json, bundler should support redirect a module to a specific file. "browser": { "module-a": "./shims/module-a.js", } --- .../__tests__/DependencyGraph-test.js | 98 +++++++++++++++++++ .../DependencyGraph/index.js | 54 +++++----- .../src/DependencyResolver/Package.js | 28 ++++-- 3 files changed, 148 insertions(+), 32 deletions(-) diff --git a/packager/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js b/packager/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js index eab9138391c48c..efe144f2e11bb6 100644 --- a/packager/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js +++ b/packager/react-packager/src/DependencyResolver/DependencyGraph/__tests__/DependencyGraph-test.js @@ -2125,6 +2125,104 @@ describe('DependencyGraph', function() { }); }); + pit('node_modules with browser mapping for packages', function() { + var root = '/root'; + fs.__setMockFilesystem({ + 'root': { + 'index.js': [ + '/**', + ' * @providesModule index', + ' */', + 'require("aPackage")', + ].join('\n'), + 'node_modules': { + 'aPackage': { + 'package.json': JSON.stringify({ + name: 'aPackage', + browser: { + 'node-package': 'browser-package', + 'node-package-b': './browser.js', + } + }), + 'index.js': [ + 'require("node-package")', + 'require("node-package-b")', + ].join('\n'), + 'node_modules': { + 'node-package': { + 'package.json': JSON.stringify({ + 'name': 'node-package', + }), + 'index.js': 'some node code', + }, + 'browser-package': { + 'package.json': JSON.stringify({ + 'name': 'browser-package', + }), + 'index.js': 'some browser code', + }, + 'node-package-b': { + 'package.json': JSON.stringify({ + 'name': 'node-package-b', + }), + 'index.js': 'some node code', + }, + }, + 'browser.js': 'some browser code', + } + } + } + }); + + var dgraph = new DependencyGraph({ + roots: [root], + fileWatcher: fileWatcher, + assetExts: ['png', 'jpg'], + cache: cache, + }); + return getOrderedDependenciesAsJSON(dgraph, '/root/index.js').then(function(deps) { + expect(deps) + .toEqual([ + { id: 'index', + path: '/root/index.js', + dependencies: ['aPackage'], + isAsset: false, + isAsset_DEPRECATED: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { id: 'aPackage/index.js', + path: '/root/node_modules/aPackage/index.js', + dependencies: ['node-package', 'node-package-b'], + isAsset: false, + isAsset_DEPRECATED: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { id: 'browser-package/index.js', + path: '/root/node_modules/aPackage/node_modules/browser-package/index.js', + dependencies: [], + isAsset: false, + isAsset_DEPRECATED: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + { id: 'aPackage/browser.js', + path: '/root/node_modules/aPackage/browser.js', + dependencies: [], + isAsset: false, + isAsset_DEPRECATED: false, + isJSON: false, + isPolyfill: false, + resolution: undefined, + }, + ]); + }); + }); + pit('node_modules should support multi level', function() { var root = '/root'; fs.__setMockFilesystem({ diff --git a/packager/react-packager/src/DependencyResolver/DependencyGraph/index.js b/packager/react-packager/src/DependencyResolver/DependencyGraph/index.js index f2b77f4d585047..f4cf0b54b5a5b4 100644 --- a/packager/react-packager/src/DependencyResolver/DependencyGraph/index.js +++ b/packager/react-packager/src/DependencyResolver/DependencyGraph/index.js @@ -332,19 +332,26 @@ class DependencyGraph { }); } + _isFilePath(moduleName) { + return moduleName[0] === '.' || moduleName[0] === '/'; + } + _resolveNodeDependency(fromModule, toModuleName) { - if (toModuleName[0] === '.' || toModuleName[1] === '/') { - const potentialModulePath = isAbsolutePath(toModuleName) ? - toModuleName : - path.join(path.dirname(fromModule.path), toModuleName); - return this._redirectRequire(fromModule, potentialModulePath).then( - realModuleName => this._loadAsFile(realModuleName) - .catch(() => this._loadAsDir(realModuleName)) - ); - } else { - return this._redirectRequire(fromModule, toModuleName).then( - realModuleName => { - const searchQueue = []; + if (this._isFilePath(toModuleName)) { + if (!isAbsolutePath(toModuleName)) { + toModuleName = path.join(path.dirname(fromModule.path), toModuleName); + } + } + return this._redirectRequire(fromModule, toModuleName).then( + realModuleName => { + const searchQueue = []; + if (this._isFilePath(realModuleName)) { + if (!isAbsolutePath(realModuleName)) { + realModuleName = path.join(path.dirname(fromModule.path), realModuleName); + } + searchQueue.push(realModuleName); + } + else { for (let currDir = path.dirname(fromModule.path); currDir !== '/'; currDir = path.dirname(currDir)) { @@ -352,19 +359,20 @@ class DependencyGraph { path.join(currDir, 'node_modules', realModuleName) ); } + } - let p = Promise.reject(new Error('Node module not found')); - searchQueue.forEach(potentialModulePath => { - p = p.catch( - () => this._loadAsFile(potentialModulePath) - ).catch( - () => this._loadAsDir(potentialModulePath) - ); - }); - - return p; + let p = Promise.reject(new Error('Node module not found')); + searchQueue.forEach(potentialModulePath => { + p = p.catch( + () => this._loadAsFile(potentialModulePath) + ).catch( + () => this._loadAsDir(potentialModulePath) + ); }); - } + + return p; + } + ); } _resolveAsset_DEPRECATED(fromModule, toModuleName) { diff --git a/packager/react-packager/src/DependencyResolver/Package.js b/packager/react-packager/src/DependencyResolver/Package.js index 5354e588c15074..0b5beba8319b1a 100644 --- a/packager/react-packager/src/DependencyResolver/Package.js +++ b/packager/react-packager/src/DependencyResolver/Package.js @@ -57,18 +57,28 @@ class Package { return name; } - if (name[0] !== '/') { - return browser[name] || name; - } + let redirect; - if (!isAbsolutePath(name)) { - throw new Error(`Expected ${name} to be absolute path`); + if (name[0] !== '/') { + if (browser[name]) { + if (browser[name][0] !== '.') { + return browser[name]; + } else { + redirect = browser[name]; + } + } + } else { + if (!isAbsolutePath(name)) { + throw new Error(`Expected ${name} to be absolute path`); + } + + const relPath = './' + path.relative(this.root, name); + + redirect = browser[relPath] || + browser[relPath + '.js'] || + browser[relPath + '.json']; } - const relPath = './' + path.relative(this.root, name); - const redirect = browser[relPath] || - browser[relPath + '.js'] || - browser[relPath + '.json']; if (redirect) { return path.join( this.root,