Skip to content

Commit

Permalink
fix(@ngtools/webpack): JIT mode CommonJS accessing inexistent `defaul…
Browse files Browse the repository at this point in the history
…t` property

With this change we fix an issue in JIT mode were we try to access an inexistent `default` property of styles modules when emitted in CJS.

Also, we now emit templates modules without the default property when not targeting ES2015 or greater to normalize the how to `require` templates and styles.

Closes #21588

(cherry picked from commit b3f71c5)
  • Loading branch information
alan-agius4 authored and dgp1130 committed Nov 29, 2021
1 parent ded7b5c commit 4d918ef
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import { execute } from '../../index';
import { BASE_OPTIONS, KARMA_BUILDER_INFO, describeBuilder } from '../setup';

describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => {
describe('Behavior: "module commonjs"', () => {
it('should work when module is commonjs', async () => {
harness.useTarget('test', {
...BASE_OPTIONS,
});

await harness.modifyFile('src/tsconfig.spec.json', (content) => {
const tsConfig = JSON.parse(content);
tsConfig.compilerOptions.module = 'commonjs';

return JSON.stringify(tsConfig);
});

const { result } = await harness.executeOnce();

expect(result?.success).toBeTrue();
});
});
});
10 changes: 8 additions & 2 deletions packages/ngtools/webpack/src/loaders/direct-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/

import { LoaderContext } from 'webpack';

export const DirectAngularResourceLoaderPath = __filename;

export default function (content: string) {
return `export default ${JSON.stringify(content)};`;
export default function (this: LoaderContext<{ esModule?: 'true' | 'false' }>, content: string) {
const { esModule } = this.getOptions();

return `${esModule === 'false' ? 'module.exports =' : 'export default'} ${JSON.stringify(
content,
)};`;
}
14 changes: 8 additions & 6 deletions packages/ngtools/webpack/src/transformers/replace_resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function visitComponentMetadata(
styleReplacements: ts.Expression[],
directTemplateLoading: boolean,
resourceImportDeclarations: ts.ImportDeclaration[],
moduleKind?: ts.ModuleKind,
moduleKind: ts.ModuleKind = ts.ModuleKind.ES2015,
inlineStyleFileExtension?: string,
): ts.ObjectLiteralElementLike | undefined {
if (!ts.isPropertyAssignment(node) || ts.isComputedPropertyName(node.name)) {
Expand All @@ -159,9 +159,10 @@ function visitComponentMetadata(
return undefined;

case 'templateUrl':
const loaderOptions = moduleKind < ts.ModuleKind.ES2015 ? '?esModule=false' : '';
const url = getResourceUrl(
node.initializer,
directTemplateLoading ? `!${DirectAngularResourceLoaderPath}!` : '',
directTemplateLoading ? `!${DirectAngularResourceLoaderPath}${loaderOptions}!` : '',
);
if (!url) {
return node;
Expand Down Expand Up @@ -255,14 +256,15 @@ function createResourceImport(
nodeFactory: ts.NodeFactory,
url: string,
resourceImportDeclarations: ts.ImportDeclaration[],
moduleKind = ts.ModuleKind.ES2015,
moduleKind: ts.ModuleKind,
): ts.Identifier | ts.Expression {
const urlLiteral = nodeFactory.createStringLiteral(url);

if (moduleKind < ts.ModuleKind.ES2015) {
return nodeFactory.createPropertyAccessExpression(
nodeFactory.createCallExpression(nodeFactory.createIdentifier('require'), [], [urlLiteral]),
'default',
return nodeFactory.createCallExpression(
nodeFactory.createIdentifier('require'),
[],
[urlLiteral],
);
} else {
const importName = nodeFactory.createIdentifier(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ describe('@ngtools/webpack transformers', () => {
AppComponent = (0, tslib_1.__decorate)([
(0, core_1.Component)({
selector: 'app-root',
template: require("!${DirectAngularResourceLoaderPath}!./app.component.html").default,
styles: [require("./app.component.css").default, require("./app.component.2.css").default] }) ], AppComponent);
template: require("!${DirectAngularResourceLoaderPath}?esModule=false!./app.component.html"),
styles: [require("./app.component.css"), require("./app.component.2.css")] }) ], AppComponent);
exports.AppComponent = AppComponent;
`;

Expand Down

0 comments on commit 4d918ef

Please sign in to comment.