Skip to content

Commit 018f1b0

Browse files
authored
feat(alias): add warning to avoid unintended duplicate modules (#1634)
* feat(alias): add warning to avoid unintended duplicate modules * test: normalize slash * test: normalize slash correctly * test: return promise
1 parent 73ef021 commit 018f1b0

File tree

4 files changed

+86
-7
lines changed

4 files changed

+86
-7
lines changed

packages/alias/src/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import path from 'path';
2+
13
import type { Plugin } from 'rollup';
24

35
import type { ResolvedAlias, ResolverFunction, ResolverObject, RollupAliasOptions } from '../types';
@@ -97,7 +99,18 @@ export default function alias(options: RollupAliasOptions = {}): Plugin {
9799
updatedId,
98100
importer,
99101
Object.assign({ skipSelf: true }, resolveOptions)
100-
).then((resolved) => resolved || { id: updatedId });
102+
).then((resolved) => {
103+
if (resolved) return resolved;
104+
105+
if (!path.isAbsolute(updatedId)) {
106+
this.warn(
107+
`rewrote ${importee} to ${updatedId} but was not an abolute path and was not handled by other plugins. ` +
108+
`This will lead to duplicated modules for the same path. ` +
109+
`To avoid duplicating modules, you should resolve to an absolute path.`
110+
);
111+
}
112+
return { id: updatedId };
113+
});
101114
}
102115
};
103116
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import '@/warn-importee.js'
2+
import './folder/warn-importee.js'

packages/alias/test/test.mjs

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import path, { posix } from 'path';
22
import { fileURLToPath } from 'url';
33
import { createRequire } from 'module';
4+
import os from 'os';
45

56
import test from 'ava';
67
import { rollup } from 'rollup';
@@ -10,13 +11,16 @@ import alias from 'current-package';
1011

1112
const DIRNAME = fileURLToPath(new URL('.', import.meta.url));
1213

14+
const isWindows = os.platform() === 'win32';
15+
1316
/**
1417
* Helper function to test configuration with Rollup
1518
* @param plugins is an array of plugins for Rollup, they should include "alias"
19+
* @param externalIds is an array of ids that will be external
1620
* @param tests is an array of pairs [source, importer]
1721
* @returns {Promise<unknown>}
1822
*/
19-
function resolveWithRollup(plugins, tests) {
23+
function resolveWithRollup(plugins, externalIds, tests) {
2024
if (!plugins.find((p) => p.name === 'alias')) {
2125
throw new Error('`plugins` should include the alias plugin.');
2226
}
@@ -41,6 +45,7 @@ function resolveWithRollup(plugins, tests) {
4145
},
4246
resolveId(id) {
4347
if (id === 'dummy-input') return id;
48+
if (externalIds.includes(id)) return { id, external: true };
4449
return null;
4550
},
4651
load(id) {
@@ -58,11 +63,12 @@ function resolveWithRollup(plugins, tests) {
5863
/**
5964
* Helper function to test configuration with Rollup and injected alias plugin
6065
* @param aliasOptions is a configuration for alias plugin
66+
* @param externalIds is an array of ids that will be external
6167
* @param tests is an array of pairs [source, importer]
6268
* @returns {Promise<unknown>}
6369
*/
64-
function resolveAliasWithRollup(aliasOptions, tests) {
65-
return resolveWithRollup([alias(aliasOptions)], tests);
70+
function resolveAliasWithRollup(aliasOptions, externalIds, tests) {
71+
return resolveWithRollup([alias(aliasOptions)], externalIds, tests);
6672
}
6773

6874
test('type', (t) => {
@@ -90,6 +96,7 @@ test('Simple aliasing (array)', (t) =>
9096
{ find: './local', replacement: 'global' }
9197
]
9298
},
99+
['bar', 'paradise', 'global'],
93100
[
94101
{ source: 'foo', importer: '/src/importer.js' },
95102
{ source: 'pony', importer: '/src/importer.js' },
@@ -106,6 +113,7 @@ test('Simple aliasing (object)', (t) =>
106113
'./local': 'global'
107114
}
108115
},
116+
['bar', 'paradise', 'global'],
109117
[
110118
{ source: 'foo', importer: '/src/importer.js' },
111119
{ source: 'pony', importer: '/src/importer.js' },
@@ -125,6 +133,7 @@ test('RegExp aliasing', (t) =>
125133
{ find: /^test\/$/, replacement: 'this/is/strict' }
126134
]
127135
},
136+
['fooooooooobar2019', 'i/am/a/barbie/girl', 'this/is/strict'],
128137
[
129138
{
130139
source: 'fooooooooobar',
@@ -150,6 +159,7 @@ test('Will not confuse modules with similar names', (t) =>
150159
{ find: './foo', replacement: 'bar' }
151160
]
152161
},
162+
[],
153163
[
154164
{ source: 'foo2', importer: '/src/importer.js' },
155165
{
@@ -168,6 +178,7 @@ test('Alias entry file', (t) =>
168178
{
169179
entries: [{ find: 'abacaxi', replacement: './abacaxi' }]
170180
},
181+
['./abacaxi/entry.js'],
171182
// eslint-disable-next-line no-undefined
172183
[{ source: 'abacaxi/entry.js' }]
173184
).then((result) => t.deepEqual(result, ['./abacaxi/entry.js'])));
@@ -177,11 +188,17 @@ test('i/am/a/file', (t) =>
177188
{
178189
entries: [{ find: 'resolve', replacement: 'i/am/a/file' }]
179190
},
191+
['i/am/a/file'],
180192
[{ source: 'resolve', importer: '/src/import.js' }]
181193
).then((result) => t.deepEqual(result, ['i/am/a/file'])));
182194

183-
test('Windows absolute path aliasing', (t) =>
184-
resolveAliasWithRollup(
195+
test('Windows absolute path aliasing', (t) => {
196+
if (!isWindows) {
197+
t.deepEqual(1, 1);
198+
return null;
199+
}
200+
201+
return resolveAliasWithRollup(
185202
{
186203
entries: [
187204
{
@@ -190,13 +207,15 @@ test('Windows absolute path aliasing', (t) =>
190207
}
191208
]
192209
},
210+
[],
193211
[
194212
{
195213
source: 'resolve',
196214
importer: posix.resolve(DIRNAME, './fixtures/index.js')
197215
}
198216
]
199-
).then((result) => t.deepEqual(result, ['E:\\react\\node_modules\\fbjs\\lib\\warning'])));
217+
).then((result) => t.deepEqual(result, ['E:\\react\\node_modules\\fbjs\\lib\\warning']));
218+
});
200219

201220
/**
202221
* Helper function to get moduleIDs from final Rollup bundle
@@ -276,6 +295,7 @@ test('Global customResolver function', (t) => {
276295
],
277296
customResolver: () => customResult
278297
},
298+
[],
279299
[
280300
{
281301
source: 'test',
@@ -300,6 +320,7 @@ test('Local customResolver function', (t) => {
300320
],
301321
customResolver: () => customResult
302322
},
323+
[],
303324
[
304325
{
305326
source: 'test',
@@ -322,6 +343,7 @@ test('Global customResolver plugin-like object', (t) => {
322343
],
323344
customResolver: { resolveId: () => customResult }
324345
},
346+
[],
325347
[
326348
{
327349
source: 'test',
@@ -348,6 +370,7 @@ test('Local customResolver plugin-like object', (t) => {
348370
],
349371
customResolver: { resolveId: () => customResult }
350372
},
373+
[],
351374
[
352375
{
353376
source: 'test',
@@ -373,6 +396,7 @@ test('supports node-resolve as a custom resolver', (t) =>
373396
],
374397
customResolver: nodeResolvePlugin()
375398
},
399+
[],
376400
[
377401
{
378402
source: 'local-resolver',
@@ -450,6 +474,7 @@ test('Forwards isEntry and custom options to a custom resolver', (t) => {
450474
return args[0];
451475
}
452476
},
477+
[],
453478
[
454479
{ source: 'entry', importer: '/src/importer.js', options: { isEntry: true } },
455480
{
@@ -497,9 +522,15 @@ test('Forwards isEntry and custom options to other plugins', (t) => {
497522
name: 'test',
498523
resolveId(...args) {
499524
resolverCalls.push(args);
525+
526+
if (['entry-point', 'non-entry-point'].includes(args[0])) {
527+
return { id: args[0], external: true };
528+
}
529+
return null;
500530
}
501531
}
502532
],
533+
[],
503534
[
504535
{ source: 'entry', importer: '/src/importer.js', options: { isEntry: true } },
505536
{
@@ -558,6 +589,7 @@ test('CustomResolver plugin-like object with buildStart', (t) => {
558589
buildStart: () => (count.option += 1)
559590
}
560591
},
592+
[],
561593
[]
562594
).then(() =>
563595
t.deepEqual(count, {
@@ -608,3 +640,34 @@ test('Works as CJS plugin', async (t) => {
608640
)
609641
);
610642
});
643+
644+
test('show warning for non-absolute non-plugin resolved id', async (t) => {
645+
const warnList = [];
646+
await rollup({
647+
input: './test/fixtures/warn.js',
648+
plugins: [
649+
alias({
650+
entries: [
651+
{
652+
find: '@',
653+
replacement: path.relative(process.cwd(), path.join(DIRNAME, './fixtures/folder'))
654+
}
655+
]
656+
})
657+
],
658+
onwarn(log) {
659+
const formattedLog = { ...log, message: log.message.replace(/\\/g, '/') };
660+
warnList.push(formattedLog);
661+
}
662+
});
663+
t.deepEqual(warnList, [
664+
{
665+
message:
666+
'rewrote @/warn-importee.js to test/fixtures/folder/warn-importee.js but was not an abolute path and was not handled by other plugins. ' +
667+
'This will lead to duplicated modules for the same path. ' +
668+
'To avoid duplicating modules, you should resolve to an absolute path.',
669+
code: 'PLUGIN_WARNING',
670+
plugin: 'alias'
671+
}
672+
]);
673+
});

0 commit comments

Comments
 (0)