Skip to content

Commit

Permalink
fix: rewrite dynamic imports
Browse files Browse the repository at this point in the history
  • Loading branch information
Dschungelabenteuer committed Apr 28, 2024
1 parent 1e2d648 commit 7c205c8
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/clever-insects-teach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vite-plugin-entry-shaking": patch
---

Fixed an issue with dynamic/async imports (#37)
37 changes: 36 additions & 1 deletion packages/core/src/analyze-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import Parsers from './parse';
import Utils from './utils';

const WILDCARD_IMPORT_PREFIX = 'import *';
const DYNAMIC_IMPORT_PREFIX = 'import(';
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/plugins/importAnalysis.ts#L83
const VITE_IGNORE_REGEX = /\/\*\s*@vite-ignore\s*\*\//;

/**
* Analyzes and transforms a single target import.
Expand All @@ -33,6 +36,9 @@ export async function analyzeImportStatement(
const isWildCardImport = catchWildcardImport(src, code, startPosition, endPosition, entryPath);
if (isWildCardImport) return;

const isDynamicImport = catchDynamicImport(src, code, startPosition, endPosition, entryPath);
if (isDynamicImport) return;

const imports = methods.getImportedEntryExports(code, startPosition, endPosition);
const imported = await methods.getImportsMap(ctx, entry, entryPath, imports);
const replacement = await methods.getImportReplacements(ctx, imported, entryPath);
Expand Down Expand Up @@ -323,7 +329,7 @@ function formatImportReplacement({ name, alias, originalName, importDefault }: I
}

/**
* Catches and handles import statement is a wildcard import.
* Catches and handles wildcard import statement.
* @param src MagicString instance to prepare transforms.
* @param code Source code of the file.
* @param startPosition Start position of the import statement.
Expand Down Expand Up @@ -352,6 +358,34 @@ function catchWildcardImport(
return isWildCardImport;
}

/**
* Catches and handles a dynamic/async import statement.
* @param src MagicString instance to prepare transforms.
* @param code Source code of the file.
* @param startPosition Start position of the import statement.
* @param endPosition End position of the import statement.
* @param entryPath Absolute path to the target entry.
*/
function catchDynamicImport(
src: MagicString,
code: string,
startPosition: number,
endPosition: number,
entryPath: EntryPath,
) {
const source = code.slice(startPosition, endPosition);
const flatSource = source.replace(/\s/gm, '');
const isViteIgnored = VITE_IGNORE_REGEX.test(flatSource);
const isDynamicImport = flatSource.startsWith(DYNAMIC_IMPORT_PREFIX);
const updatedPath = addSourceQuerySuffix(entryPath);

if (isDynamicImport && !isViteIgnored) {
src.overwrite(startPosition, endPosition, `import('${updatedPath}')`);
}

return isDynamicImport;
}

const methods = {
analyzeImportStatement,
getImportedEntryExports,
Expand All @@ -365,6 +399,7 @@ const methods = {
resolveImportedCircularEntities,
formatImportReplacement,
catchWildcardImport,
catchDynamicImport,
};

export default methods;
43 changes: 43 additions & 0 deletions packages/core/tests/analyze-import.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,3 +752,46 @@ describe('catchWildcardImport', () => {
expect(src.toString()).toStrictEqual(input);
});
});

describe('catchDynamicImport', () => {
const entryPath = 'path/to/entry';

/**
* Next two suites suppose the following statement:
* `const { Utils } = await import('path/to/entry');`
*/

it('should return true and rewrite if the import is a dynamic import', () => {
const input = `import('${entryPath}')`;
const src = new MagicString(input);
const output = ImportAnalyzer.catchDynamicImport(src, input, 0, input.length, entryPath);
expect(output).toStrictEqual(true);
expect(src.toString()).toStrictEqual(`import('${entryPath}?source=1')`);
});

const commentCases = {
before: `import(/* @vite-ignore */ '${entryPath}')`,
after: `import(/* @vite-ignore */ '${entryPath}')`,
multiline: `import(
/* @vite-ignore */
'${entryPath}'
)`,
};

Object.entries(commentCases).forEach(([name, input]) => {
it(`should return true but not rewrite if the import is a dynamic import with a vite-ignore comment ${name}`, () => {
const src = new MagicString(input);
const output = ImportAnalyzer.catchDynamicImport(src, input, 0, input.length, entryPath);
expect(output).toStrictEqual(true);
expect(src.toString()).toStrictEqual(input);
});
});

it('should return false and not rewrite if the import is not a dynamic import', () => {
const input = `import { Something as Utils } from './somewhere';`;
const src = new MagicString(input);
const output = ImportAnalyzer.catchDynamicImport(src, input, 0, input.length - 1, entryPath);
expect(output).toStrictEqual(false);
expect(src.toString()).toStrictEqual(input);
});
});

0 comments on commit 7c205c8

Please sign in to comment.