mirror of https://github.com/status-im/metro.git
[react-packager] Add support for platform in the resolver
Summary: Teach the resolver about platform-based resolution. The platform extension is inferred from the entry point. It works for haste modules, as well as node-based resolution.
This commit is contained in:
parent
ab23c251c3
commit
63a96af6c6
|
@ -1809,6 +1809,77 @@ describe('DependencyGraph', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('platform should work with node_modules', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.ios.js': [
|
||||||
|
'/**',
|
||||||
|
' * @providesModule index',
|
||||||
|
' */',
|
||||||
|
'require("foo");',
|
||||||
|
'require("bar");',
|
||||||
|
].join('\n'),
|
||||||
|
'node_modules': {
|
||||||
|
'foo': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'foo',
|
||||||
|
}),
|
||||||
|
'index.ios.js': '',
|
||||||
|
},
|
||||||
|
'bar': {
|
||||||
|
'package.json': JSON.stringify({
|
||||||
|
name: 'bar',
|
||||||
|
main: 'main'
|
||||||
|
}),
|
||||||
|
'main.ios.js': '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
|
});
|
||||||
|
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||||
|
expect(deps)
|
||||||
|
.toEqual([
|
||||||
|
{
|
||||||
|
id: 'index',
|
||||||
|
path: '/root/index.ios.js',
|
||||||
|
dependencies: ['foo', 'bar'],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'foo/index.ios.js',
|
||||||
|
path: '/root/node_modules/foo/index.ios.js',
|
||||||
|
dependencies: [],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'bar/main.ios.js',
|
||||||
|
path: '/root/node_modules/bar/main.ios.js',
|
||||||
|
dependencies: [],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
pit('nested node_modules with specific paths', function() {
|
pit('nested node_modules with specific paths', function() {
|
||||||
var root = '/root';
|
var root = '/root';
|
||||||
fs.__setMockFilesystem({
|
fs.__setMockFilesystem({
|
||||||
|
@ -2333,6 +2404,169 @@ describe('DependencyGraph', function() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pit('should work with multiple platforms (haste)', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.ios.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule index
|
||||||
|
*/
|
||||||
|
require('a');
|
||||||
|
`,
|
||||||
|
'a.ios.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule a
|
||||||
|
*/
|
||||||
|
`,
|
||||||
|
'a.android.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule a
|
||||||
|
*/
|
||||||
|
`,
|
||||||
|
'a.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule a
|
||||||
|
*/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
|
});
|
||||||
|
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||||
|
expect(deps)
|
||||||
|
.toEqual([
|
||||||
|
{
|
||||||
|
id: 'index',
|
||||||
|
path: '/root/index.ios.js',
|
||||||
|
dependencies: ['a'],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'a',
|
||||||
|
path: '/root/a.ios.js',
|
||||||
|
dependencies: [],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should pick the generic file', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.ios.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule index
|
||||||
|
*/
|
||||||
|
require('a');
|
||||||
|
`,
|
||||||
|
'a.android.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule a
|
||||||
|
*/
|
||||||
|
`,
|
||||||
|
'a.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule a
|
||||||
|
*/
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
|
});
|
||||||
|
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||||
|
expect(deps)
|
||||||
|
.toEqual([
|
||||||
|
{
|
||||||
|
id: 'index',
|
||||||
|
path: '/root/index.ios.js',
|
||||||
|
dependencies: ['a'],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'a',
|
||||||
|
path: '/root/a.js',
|
||||||
|
dependencies: [],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('should work with multiple platforms (node)', function() {
|
||||||
|
var root = '/root';
|
||||||
|
fs.__setMockFilesystem({
|
||||||
|
'root': {
|
||||||
|
'index.ios.js': `
|
||||||
|
/**
|
||||||
|
* @providesModule index
|
||||||
|
*/
|
||||||
|
require('./a');
|
||||||
|
`,
|
||||||
|
'a.ios.js': '',
|
||||||
|
'a.android.js': '',
|
||||||
|
'a.js': '',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var dgraph = new DependencyGraph({
|
||||||
|
roots: [root],
|
||||||
|
fileWatcher: fileWatcher,
|
||||||
|
assetExts: ['png', 'jpg'],
|
||||||
|
});
|
||||||
|
return dgraph.getOrderedDependencies('/root/index.ios.js').then(function(deps) {
|
||||||
|
expect(deps)
|
||||||
|
.toEqual([
|
||||||
|
{
|
||||||
|
id: 'index',
|
||||||
|
path: '/root/index.ios.js',
|
||||||
|
dependencies: ['./a'],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '/root/a.ios.js',
|
||||||
|
path: '/root/a.ios.js',
|
||||||
|
dependencies: [],
|
||||||
|
isAsset: false,
|
||||||
|
isAsset_DEPRECATED: false,
|
||||||
|
isJSON: false,
|
||||||
|
isPolyfill: false,
|
||||||
|
resolution: undefined,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('file watch updating', function() {
|
describe('file watch updating', function() {
|
||||||
|
|
|
@ -56,6 +56,10 @@ const validateOpts = declareOpts({
|
||||||
'parse',
|
'parse',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
platforms: {
|
||||||
|
type: 'array',
|
||||||
|
default: ['ios', 'android'],
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class DependencyGraph {
|
class DependencyGraph {
|
||||||
|
@ -169,6 +173,13 @@ class DependencyGraph {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const platformExt = getPlatformExt(entryPath);
|
||||||
|
if (platformExt && this._opts.platforms.indexOf(platformExt) > -1) {
|
||||||
|
this._platformExt = platformExt;
|
||||||
|
} else {
|
||||||
|
this._platformExt = null;
|
||||||
|
}
|
||||||
|
|
||||||
const entry = this._moduleCache.getModule(absolutePath);
|
const entry = this._moduleCache.getModule(absolutePath);
|
||||||
const deps = [];
|
const deps = [];
|
||||||
const visited = Object.create(null);
|
const visited = Object.create(null);
|
||||||
|
@ -237,16 +248,14 @@ class DependencyGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
return p.then((realModuleName) => {
|
return p.then((realModuleName) => {
|
||||||
let dep = this._hasteMap[realModuleName];
|
let dep = this._getHasteModule(realModuleName);
|
||||||
|
|
||||||
if (dep && dep.type === 'Module') {
|
if (dep && dep.type === 'Module') {
|
||||||
return dep;
|
return dep;
|
||||||
}
|
}
|
||||||
|
|
||||||
let packageName = realModuleName;
|
let packageName = realModuleName;
|
||||||
|
|
||||||
while (packageName && packageName !== '.') {
|
while (packageName && packageName !== '.') {
|
||||||
dep = this._hasteMap[packageName];
|
dep = this._getHasteModule(packageName);
|
||||||
if (dep && dep.type === 'Package') {
|
if (dep && dep.type === 'Package') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -349,6 +358,9 @@ class DependencyGraph {
|
||||||
let file;
|
let file;
|
||||||
if (this._fastfs.fileExists(potentialModulePath)) {
|
if (this._fastfs.fileExists(potentialModulePath)) {
|
||||||
file = potentialModulePath;
|
file = potentialModulePath;
|
||||||
|
} else if (this._platformExt != null &&
|
||||||
|
this._fastfs.fileExists(potentialModulePath + '.' + this._platformExt + '.js')) {
|
||||||
|
file = potentialModulePath + '.' + this._platformExt + '.js';
|
||||||
} else if (this._fastfs.fileExists(potentialModulePath + '.js')) {
|
} else if (this._fastfs.fileExists(potentialModulePath + '.js')) {
|
||||||
file = potentialModulePath + '.js';
|
file = potentialModulePath + '.js';
|
||||||
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
|
} else if (this._fastfs.fileExists(potentialModulePath + '.json')) {
|
||||||
|
@ -419,15 +431,32 @@ class DependencyGraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateHasteMap(name, mod) {
|
_updateHasteMap(name, mod) {
|
||||||
if (this._hasteMap[name]) {
|
if (this._hasteMap[name] == null) {
|
||||||
debug('WARNING: conflicting haste modules: ' + name);
|
this._hasteMap[name] = [];
|
||||||
if (mod.type === 'Package' &&
|
|
||||||
this._hasteMap[name].type === 'Module') {
|
|
||||||
// Modules takes precendence over packages.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this._hasteMap[name] = mod;
|
|
||||||
|
if (mod.type === 'Module') {
|
||||||
|
// Modules takes precendence over packages.
|
||||||
|
this._hasteMap[name].unshift(mod);
|
||||||
|
} else {
|
||||||
|
this._hasteMap[name].push(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getHasteModule(name) {
|
||||||
|
if (this._hasteMap[name]) {
|
||||||
|
const modules = this._hasteMap[name];
|
||||||
|
if (this._platformExt != null) {
|
||||||
|
for (let i = 0; i < modules.length; i++) {
|
||||||
|
if (getPlatformExt(modules[i].path) === this._platformExt) {
|
||||||
|
return modules[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modules[0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isNodeModulesDir(file) {
|
_isNodeModulesDir(file) {
|
||||||
|
@ -511,12 +540,17 @@ class DependencyGraph {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*eslint no-labels: 0 */
|
||||||
if (type === 'delete' || type === 'change') {
|
if (type === 'delete' || type === 'change') {
|
||||||
_.each(this._hasteMap, (mod, name) => {
|
loop: for (let name in this._hasteMap) {
|
||||||
if (mod.path === absPath) {
|
let modules = this._hasteMap[name];
|
||||||
delete this._hasteMap[name];
|
for (var i = 0; i < modules.length; i++) {
|
||||||
|
if (modules[i].path === absPath) {
|
||||||
|
modules.splice(i, 1);
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
if (type === 'delete') {
|
if (type === 'delete') {
|
||||||
return;
|
return;
|
||||||
|
@ -566,6 +600,15 @@ function normalizePath(modulePath) {
|
||||||
return modulePath.replace(/\/$/, '');
|
return modulePath.replace(/\/$/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract platform extension: index.ios.js -> ios
|
||||||
|
function getPlatformExt(file) {
|
||||||
|
const parts = path.basename(file).split('.');
|
||||||
|
if (parts.length < 3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return parts[parts.length - 2];
|
||||||
|
}
|
||||||
|
|
||||||
util.inherits(NotFoundError, Error);
|
util.inherits(NotFoundError, Error);
|
||||||
|
|
||||||
module.exports = DependencyGraph;
|
module.exports = DependencyGraph;
|
||||||
|
|
Loading…
Reference in New Issue