Skip to content

Commit

Permalink
fix(ssr): remove unused imports (#4873)
Browse files Browse the repository at this point in the history
  • Loading branch information
nolanlawson authored Nov 15, 2024
1 parent 09f0355 commit b47e18c
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 19 deletions.
15 changes: 3 additions & 12 deletions packages/@lwc/ssr-compiler/src/__tests__/fixtures.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,10 @@ async function compileFixture({ input, dirname }: { input: string; dirname: stri
modules: [{ dir: modulesDir }],
}),
],
onwarn({ message, code, names }) {
if (code === 'CIRCULAR_DEPENDENCY') {
return;
onwarn({ message, code }) {
if (code !== 'CIRCULAR_DEPENDENCY') {
throw new Error(message);
}
// TODO [#4793]: fix unused imports
if (code === 'UNUSED_EXTERNAL_IMPORT') {
const unexpected = new Set(names);
const expected = ['connectContext', 'htmlEscape', 'track'];
expected.forEach((name) => unexpected.delete(name));
if (unexpected.size === 0) return;
}

throw new Error(message);
},
});

Expand Down
3 changes: 3 additions & 0 deletions packages/@lwc/ssr-compiler/src/compile-js/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { traverse, builders as b, is } from 'estree-toolkit';
import { parseModule } from 'meriyah';

import { transmogrify } from '../transmogrify';
import { optimizeImports } from '../optimize-imports';
import { replaceLwcImport } from './lwc-import';
import { catalogTmplImport } from './catalog-tmpls';
import { catalogStaticStylesheets, catalogAndReplaceStyleImports } from './stylesheets';
Expand Down Expand Up @@ -193,6 +194,8 @@ export default function compileJS(
addGenerateMarkupExport(ast, state, tagName, filename);
assignGenerateMarkupToComponent(ast, state);

ast = optimizeImports(ast);

if (compilationMode === 'async' || compilationMode === 'sync') {
ast = transmogrify(ast, compilationMode);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/@lwc/ssr-compiler/src/compile-template/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { getStylesheetImports } from '../compile-js/stylesheets';
import { addScopeTokenDeclarations } from '../compile-js/stylesheet-scope-token';
import { transmogrify } from '../transmogrify';
import { bImportDeclaration } from '../estree/builders';
import { optimizeImports } from '../optimize-imports';
import { optimizeAdjacentYieldStmts } from './shared';
import { templateIrToEsTree } from './ir-to-es';
import type { ExportDefaultDeclaration as EsExportDefaultDeclaration } from 'estree';
Expand Down Expand Up @@ -110,6 +111,8 @@ export default function compileTemplate(
const stylesheetImports = getStylesheetImports(filename);
program.body.unshift(...stylesheetImports);

program = optimizeImports(program);

if (compilationMode === 'async' || compilationMode === 'sync') {
program = transmogrify(program, compilationMode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ function yieldAttrOrPropLiveValue(
value: IrExpression | BinaryExpression,
cxt: TransformerContext
): EsStatement[] {
cxt.hoist(bImportHtmlEscape(), importHtmlEscapeKey);
const isHtmlBooleanAttr = isBooleanAttribute(name, elementName);
const scopedExpression = getScopedExpression(value as EsExpression, cxt);
return [bConditionalLiveYield(b.literal(name), scopedExpression, b.literal(isHtmlBooleanAttr))];
Expand Down Expand Up @@ -205,12 +204,9 @@ export const Element: Transformer<IrElement | IrExternalComponent | IrSlot> = fu
result = yieldAttrOrPropLiveValue(node.name, name, value, cxt);
}

if (result.length > 0) {
// actually yielded something
cxt.hoist(bImportHtmlEscape(), importHtmlEscapeKey);
if (name === 'class') {
hasClassAttribute = true;
}
if (result.length > 0 && name === 'class') {
// actually yielded a class attribute value
hasClassAttribute = true;
}

return result;
Expand All @@ -235,6 +231,8 @@ export const Element: Transformer<IrElement | IrExternalComponent | IrSlot> = fu
childContent = [];
}

cxt.hoist(bImportHtmlEscape(), importHtmlEscapeKey);

return [
bYield(b.literal(`<${node.name}`)),
// If we haven't already prefixed the scope token to an existing class, add an explicit class here
Expand Down
42 changes: 42 additions & 0 deletions packages/@lwc/ssr-compiler/src/optimize-imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { produce } from 'immer';
import { traverse } from 'estree-toolkit';
import { Visitors } from './transmogrify';
import type { Program as EsProgram } from 'estree';

const visitors: Visitors = {
$: {
scope: true,
},
ImportDeclaration(path) {
const { node, scope } = path;
if (!node || !scope) {
return;
}
if (node.source.type === 'Literal' && node.source.value === '@lwc/ssr-runtime') {
node.specifiers = node.specifiers.filter(
(specifier) =>
// There shouldn't be any default imports anyway
specifier.type === 'ImportSpecifier' &&
// If there are references, then the import is used. Note that an import will _always_
// have a binding (of type "module"), but it may not have references.
scope.getBinding(specifier.local.name)?.references.length
);
}
},
};

/**
* Remove any unused imports from `@lwc/ssr-runtime`.
* This avoids any warnings from Rollup about unused imports, and avoids us needing
* to manually track what's imported during AST generation.
* @param compiledComponentAst
*/
export function optimizeImports(compiledComponentAst: EsProgram): EsProgram {
return produce(compiledComponentAst, (astDraft) => traverse(astDraft, visitors));
}

0 comments on commit b47e18c

Please sign in to comment.