Skip to content

Commit 0df1541

Browse files
robhoganfacebook-github-bot
authored andcommitted
Disable global package resolution by default
Summary: Prior to Metro symlink support, many users relied on "global package" resolution in setups such as Yarn workspaces. With global packages, any `package.json` *outside* `node_modules` may be resolved by name from anywhere in the project. In the case of Yarn (etc.) workspaces, we're now able to resolve the same packages through the symlinks the packager creates under `node_modules`, in the same manner as Node JS and other tooling does. Global packages now provide little value for most users, and in fact are a potential footgun - if your global package happens to share its name with a `node_modules` package, the former will always take precedence, even when resolving relative to another `node_modules` package. This changes the default for `resolver.enableGlobalPackages` to `false`. If you require global packages, you will need to explicitly enable them in your config. Changelog ``` - **[Breaking]:** Disable global package resolution (`resolver.enableGlobalPackages`) by default ``` Reviewed By: motiz88 Differential Revision: D48777893 fbshipit-source-id: 23b8a5884582e20ca92c8356e67909f2d66b9e7b
1 parent 9e7cec1 commit 0df1541

File tree

5 files changed

+58
-43
lines changed

5 files changed

+58
-43
lines changed

docs/Configuration.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,7 @@ What module to use as the canonical "empty" module when one is needed. Defaults
247247
248248
Type: `boolean`.
249249
250-
Whether to automatically resolve references first-party packages (e.g. workspaces) in your project. Any `package.json` file with a valid `name` property within `projectRoot` or `watchFolders` (but outside of `node_modules`) counts as a package for this purpose. Defaults to `true`.
251-
252-
:::note
253-
The default value of this option may change in a future version of Metro. If your project relies on it, it's recommended that you set it explicitly in your config file.
254-
:::
250+
Whether to automatically resolve references to first-party packages (e.g. workspaces) in your project. Any `package.json` file with a valid `name` property within `projectRoot` or `watchFolders` (but outside of `node_modules`) counts as a package for this purpose. Defaults to `false`.
255251
256252
#### `extraNodeModules`
257253

packages/metro-config/src/__tests__/__snapshots__/loadConfig-test.js.snap

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Object {
4949
"dependencyExtractor": undefined,
5050
"disableHierarchicalLookup": false,
5151
"emptyModulePath": "metro-runtime/src/modules/empty-module",
52-
"enableGlobalPackages": true,
52+
"enableGlobalPackages": false,
5353
"extraNodeModules": Object {},
5454
"hasteImplModulePath": undefined,
5555
"nodeModulesPaths": Array [],
@@ -227,7 +227,7 @@ Object {
227227
"dependencyExtractor": undefined,
228228
"disableHierarchicalLookup": false,
229229
"emptyModulePath": "metro-runtime/src/modules/empty-module",
230-
"enableGlobalPackages": true,
230+
"enableGlobalPackages": false,
231231
"extraNodeModules": Object {},
232232
"hasteImplModulePath": undefined,
233233
"nodeModulesPaths": Array [],
@@ -405,7 +405,7 @@ Object {
405405
"dependencyExtractor": undefined,
406406
"disableHierarchicalLookup": false,
407407
"emptyModulePath": "metro-runtime/src/modules/empty-module",
408-
"enableGlobalPackages": true,
408+
"enableGlobalPackages": false,
409409
"extraNodeModules": Object {},
410410
"hasteImplModulePath": undefined,
411411
"nodeModulesPaths": Array [],
@@ -583,7 +583,7 @@ Object {
583583
"dependencyExtractor": undefined,
584584
"disableHierarchicalLookup": false,
585585
"emptyModulePath": "metro-runtime/src/modules/empty-module",
586-
"enableGlobalPackages": true,
586+
"enableGlobalPackages": false,
587587
"extraNodeModules": Object {},
588588
"hasteImplModulePath": undefined,
589589
"nodeModulesPaths": Array [],

packages/metro-config/src/defaults/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const getDefaultValues = (projectRoot: ?string): ConfigT => ({
4444
emptyModulePath: require.resolve(
4545
'metro-runtime/src/modules/empty-module.js',
4646
),
47-
enableGlobalPackages: true,
47+
enableGlobalPackages: false,
4848
extraNodeModules: {},
4949
hasteImplModulePath: undefined,
5050
nodeModulesPaths: [],

packages/metro/src/DeltaBundler/__tests__/__snapshots__/resolver-test.js.snap

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,19 @@ None of these files exist:
4848
3 | import bar from 'foo';"
4949
`;
5050

51-
exports[`linux global packages default config uses the name in the package.json as the package name 1`] = `
51+
exports[`linux global packages default config does not resolve global packages 1`] = `
5252
"Unable to resolve module aPackage from /root/index.js: aPackage could not be found within the project.
53-
1 | import foo from 'bar';
54-
> 2 | import a from 'aPackage';
55-
| ^
56-
3 | import bar from 'foo';"
53+
> 1 |"
54+
`;
55+
56+
exports[`linux global packages default config does not resolve global packages 2`] = `
57+
"Unable to resolve module aPackage/ from /root/index.js: aPackage/ could not be found within the project.
58+
> 1 |"
59+
`;
60+
61+
exports[`linux global packages default config does not resolve global packages 3`] = `
62+
"Unable to resolve module aPackage/other from /root/index.js: aPackage/other could not be found within the project.
63+
> 1 |"
5764
`;
5865

5966
exports[`linux global packages explicitly disabled does not resolve global packages 1`] = `
@@ -248,12 +255,19 @@ None of these files exist:
248255
3 | import bar from 'foo';"
249256
`;
250257

251-
exports[`win32 global packages default config uses the name in the package.json as the package name 1`] = `
258+
exports[`win32 global packages default config does not resolve global packages 1`] = `
252259
"Unable to resolve module aPackage from C:\\\\root\\\\index.js: aPackage could not be found within the project.
253-
1 | import foo from 'bar';
254-
> 2 | import a from 'aPackage';
255-
| ^
256-
3 | import bar from 'foo';"
260+
> 1 |"
261+
`;
262+
263+
exports[`win32 global packages default config does not resolve global packages 2`] = `
264+
"Unable to resolve module aPackage/ from C:\\\\root\\\\index.js: aPackage/ could not be found within the project.
265+
> 1 |"
266+
`;
267+
268+
exports[`win32 global packages default config does not resolve global packages 3`] = `
269+
"Unable to resolve module aPackage/other from C:\\\\root\\\\index.js: aPackage/other could not be found within the project.
270+
> 1 |"
257271
`;
258272

259273
exports[`win32 global packages explicitly disabled does not resolve global packages 1`] = `

packages/metro/src/DeltaBundler/__tests__/resolver-test.js

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1633,17 +1633,12 @@ function dep(name: string): TransformResultDependency {
16331633
});
16341634

16351635
describe('global packages', () => {
1636-
describe.each([
1637-
{name: 'default config', config: {}},
1638-
{
1639-
name: 'explicitly enabled',
1640-
config: {
1641-
resolver: {
1642-
enableGlobalPackages: true,
1643-
},
1636+
describe('explicitly enabled', () => {
1637+
const config = {
1638+
resolver: {
1639+
enableGlobalPackages: true,
16441640
},
1645-
},
1646-
])('$name', ({config}) => {
1641+
};
16471642
it('treats any folder with a package.json as a global package', async () => {
16481643
setMockFileSystem({
16491644
'index.js': '',
@@ -1843,7 +1838,7 @@ function dep(name: string): TransformResultDependency {
18431838
},
18441839
});
18451840

1846-
await expect(createResolver()).rejects.toThrow(
1841+
await expect(createResolver(config)).rejects.toThrow(
18471842
'Duplicated files or mocks. Please check the console for more info',
18481843
);
18491844
expect(console.error).toHaveBeenCalledWith(
@@ -1989,13 +1984,17 @@ function dep(name: string): TransformResultDependency {
19891984
});
19901985
});
19911986

1992-
describe('explicitly disabled', () => {
1993-
const config = {
1994-
resolver: {
1995-
enableGlobalPackages: false,
1987+
describe.each([
1988+
{name: 'default config', config: {}},
1989+
{
1990+
name: 'explicitly disabled',
1991+
config: {
1992+
resolver: {
1993+
enableGlobalPackages: false,
1994+
},
19961995
},
1997-
};
1998-
1996+
},
1997+
])('$name', ({config}) => {
19991998
test('does not resolve global packages', async () => {
20001999
setMockFileSystem({
20012000
'index.js': '',
@@ -2050,6 +2049,7 @@ function dep(name: string): TransformResultDependency {
20502049
__dirname,
20512050
'../__fixtures__/hasteImpl.js',
20522051
),
2052+
enableGlobalPackages: true,
20532053
},
20542054
};
20552055
});
@@ -2381,10 +2381,12 @@ function dep(name: string): TransformResultDependency {
23812381
'package.json': '{}',
23822382
'index.js': '',
23832383
},
2384-
foo: {
2385-
'package.json': JSON.stringify({name: 'foo'}),
2386-
lib: {'bar.js': ''},
2387-
'index.js': '',
2384+
node_modules: {
2385+
foo: {
2386+
'package.json': JSON.stringify({name: 'foo'}),
2387+
lib: {'bar.js': ''},
2388+
'index.js': '',
2389+
},
23882390
},
23892391
});
23902392

@@ -2396,11 +2398,14 @@ function dep(name: string): TransformResultDependency {
23962398
resolver.resolve(p('/root/folder/index.js'), dep('foo')),
23972399
).toEqual({
23982400
type: 'sourceFile',
2399-
filePath: p('/root/foo/index.js'),
2401+
filePath: p('/root/node_modules/foo/index.js'),
24002402
});
24012403
expect(
24022404
resolver.resolve(p('/root/folder/index.js'), dep('foo/lib/bar')),
2403-
).toEqual({type: 'sourceFile', filePath: p('/root/foo/lib/bar.js')});
2405+
).toEqual({
2406+
type: 'sourceFile',
2407+
filePath: p('/root/node_modules/foo/lib/bar.js'),
2408+
});
24042409
});
24052410

24062411
it('supports scoped `extraNodeModules`', async () => {

0 commit comments

Comments
 (0)