fix(metro-config): ignore hoisted react-native if a local copy exists (#50)

This commit is contained in:
Tommy Nguyen 2021-02-18 10:29:23 +01:00 коммит произвёл GitHub
Родитель 17a3896f24
Коммит 7cd8fc3229
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 88 добавлений и 12 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -10,3 +10,4 @@ dist/
lib/
local.properties
node_modules/
!**/__fixtures__/**/node_modules/

Просмотреть файл

@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "Ignore hoisted react-native if a local copy exists",
"packageName": "@rnx-kit/metro-config",
"email": "4123478+tido64@users.noreply.github.com",
"dependentChangeType": "patch"
}

Просмотреть файл

@ -18,9 +18,6 @@
"test": "jest"
},
"dependencies": {
"@babel/core": "^7.0.0",
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/types": "^7.0.0",
"babel-plugin-const-enum": "^1.0.0",
"fast-glob": "^3.2.2",
"find-up": "^4.1.0"
@ -30,7 +27,6 @@
},
"devDependencies": {
"@types/babel__core": "^7.0.0",
"@types/babel__helper-plugin-utils": "^7.0.0",
"@types/jest": "^26.0.0",
"jest": "^26.0.0",
"metro-config": "^0.59.0",

Просмотреть файл

@ -70,6 +70,38 @@ function defaultWatchFolders(projectRoot) {
return watchFolders.map((p) => path.join(rootPath, p));
}
/**
* Returns a list of installed react-native copies.
* @param {string} projectRoot
* @returns {string[]}
*/
function findReactNative(projectRoot) {
const findUp = require("find-up");
const path = require("path");
/** @type {string[]} */
const paths = [];
findUp.sync(
(directory) => {
const candidate = path.join(
directory,
"node_modules",
"react-native",
"package.json"
);
if (findUp.sync.exists(candidate)) {
paths.push(path.relative(projectRoot, path.dirname(candidate)));
}
return undefined;
},
{
cwd: projectRoot,
}
);
return paths;
}
/**
* Helper function for generating a package exclusion list.
* @param {(string | RegExp)[]=} additionalExclusions
@ -88,6 +120,11 @@ function exclusionList(additionalExclusions = []) {
})();
return exclusionList([
// Ignore extra copies of react-native
...findReactNative(process.cwd())
.slice(1)
.map((p) => new RegExp(`${p}/.*`)),
// Ignore nested copies of react-native
/node_modules\/.*\/node_modules\/react-native\/.*/,

10
packages/metro-config/test/__fixtures__/awesome-repo/node_modules/react-native/package.json сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
{
"name": "react-native",
"version": "1000.0.0",
"description": "A framework for building native apps using React",
"license": "MIT",
"repository": {
"type": "git",
"url": "git@github.com:facebook/react-native.git"
}
}

10
packages/metro-config/test/__fixtures__/awesome-repo/packages/john/node_modules/react-native/package.json сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
{
"name": "react-native",
"version": "1000.0.0",
"description": "A framework for building native apps using React",
"license": "MIT",
"repository": {
"type": "git",
"url": "git@github.com:facebook/react-native.git"
}
}

Просмотреть файл

@ -11,6 +11,9 @@ describe("@rnx-kit/metro-config", () => {
makeMetroConfig,
} = require("../src");
const defaultExclusionList =
"node_modules\\/.*\\/node_modules\\/react-native\\/.*|.*\\.ProjectImports\\.zip|node_modules\\/react\\/dist\\/.*|website\\/node_modules\\/.*|heapCapture\\/bundle\\.js|.*\\/__tests__\\/.*";
const babelConfigKeys = ["presets", "overrides"];
const babelConfigPresets = ["module:metro-react-native-babel-preset"];
const babelTypeScriptTest = "\\.tsx?$";
@ -71,10 +74,26 @@ describe("@rnx-kit/metro-config", () => {
expect(folders.sort()).toEqual(expectedFolders);
});
test("exclusionList() ignores hoisted react-native if a local copy exists", () => {
// /rnx-kit/packages/metro-config/test/__fixtures__/awesome-repo/node_modules/react-native
const fixtureCopy = "..\\/..\\/node_modules\\/react-native\\/.*";
// /rnx-kit/node_modules/react-native
const repoCopy = "..\\/..\\/..\\/..\\/..\\/..\\/..\\/node_modules\\/react-native\\/.*";
// Conan does not have a local copy of react-native but since we're
// in a monorepo, we'll find the repo's copy.
setFixture("awesome-repo/packages/conan");
expect(exclusionList().source).toBe(`(${repoCopy}|${defaultExclusionList})$`);
// John has a local copy of react-native and should ignore the
// hoisted copy (in addition to the repo's own copy).
setFixture("awesome-repo/packages/john");
expect(exclusionList().source).toBe(`(${fixtureCopy}|${repoCopy}|${defaultExclusionList})$`);
});
test("exclusionList() returns additional exclusions", () => {
expect(exclusionList().source).toBe(
"(node_modules\\/.*\\/node_modules\\/react-native\\/.*|.*\\.ProjectImports\\.zip|node_modules\\/react\\/dist\\/.*|website\\/node_modules\\/.*|heapCapture\\/bundle\\.js|.*\\/__tests__\\/.*)$"
);
expect(exclusionList().source).toBe(`(${defaultExclusionList})$`);
expect(exclusionList([/.*[\/\\]__fixtures__[\/\\].*/]).source).toBe(
"(node_modules\\/.*\\/node_modules\\/react-native\\/.*|.*\\.ProjectImports\\.zip|.*[\\/\\\\]__fixtures__[\\/\\\\].*|node_modules\\/react\\/dist\\/.*|website\\/node_modules\\/.*|heapCapture\\/bundle\\.js|.*\\/__tests__\\/.*)$"
);
@ -155,10 +174,6 @@ describe("@rnx-kit/metro-config", () => {
);
expect(
files.filter((file) => !file.startsWith("CHANGELOG")).sort()
).toEqual([
"README.md",
"package.json",
"src/index.js",
]);
).toEqual(["README.md", "package.json", "src/index.js"]);
});
});