Skip to content

Commit e288847

Browse files
committed
feat(@ngtools/webpack): allow passing in the right ContextElementDependency class
This should allow multiple webpack versions in the workspace dependencies with no weird errors. Fix #6417 for good.
1 parent 4fdc69f commit e288847

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

packages/ngtools/webpack/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The loader works with webpack plugin to compile your TypeScript. It's important
4242
* `skipCodeGeneration`. Optional, defaults to false. Disable code generation and do not refactor the code to bootstrap. This replaces `templateUrl: "string"` with `template: require("string")` (and similar for styles) to allow for webpack to properly link the resources.
4343
* `sourceMap`. Optional. Include sourcemaps.
4444
* `compilerOptions`. Optional. Override options in `tsconfig.json`.
45+
* `contextElementDependencyConstructor`. Optional. Set to `require('webpack/lib/dependencies/ContextElementDependency')` if you are having `No module factory available for dependency type: ContextElementDependency` errors.
4546

4647
## Features
4748
The benefits and ability of using [`@ngtools/webpack`](https://www.npmjs.com/~ngtools) standalone from the Angular CLI as presented in [Stephen Fluin's Angular CLI talk](https://youtu.be/uBRK6cTr4Vk?t=6m45s) at Angular Connect 2016:

packages/ngtools/webpack/src/angular_compiler_plugin.ts

+20-3
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@ import {
5454
VirtualWatchFileSystemDecorator,
5555
} from './virtual_file_system_decorator';
5656

57-
58-
const ContextElementDependency = require('webpack/lib/dependencies/ContextElementDependency');
5957
const treeKill = require('tree-kill');
6058

59+
export interface ContextElementDependency {}
60+
61+
export interface ContextElementDependencyConstructor {
62+
new(modulePath: string, name: string): ContextElementDependency;
63+
}
6164

6265
/**
6366
* Option Constants
@@ -86,6 +89,10 @@ export interface AngularCompilerPluginOptions {
8689
// added to the list of lazy routes
8790
additionalLazyModules?: { [module: string]: string };
8891

92+
// The ContextElementDependency of correct Webpack compilation.
93+
// This is needed when there are multiple Webpack installs.
94+
contextElementDependencyConstructor?: ContextElementDependencyConstructor;
95+
8996
// Use tsconfig to include path globs.
9097
compilerOptions?: ts.CompilerOptions;
9198

@@ -128,6 +135,7 @@ export class AngularCompilerPlugin {
128135
private _normalizedLocale: string | null;
129136
private _warnings: (string | Error)[] = [];
130137
private _errors: (string | Error)[] = [];
138+
private _contextElementDependencyConstructor: ContextElementDependencyConstructor;
131139

132140
// TypeChecker process.
133141
private _forkTypeChecker = true;
@@ -267,6 +275,15 @@ export class AngularCompilerPlugin {
267275
this._platformTransformers = options.platformTransformers;
268276
}
269277

278+
// Default ContextElementDependency to the one we can import from here.
279+
// Failing to use the right ContextElementDependency will throw the error below:
280+
// "No module factory available for dependency type: ContextElementDependency"
281+
// Hoisting together with peer dependencies can make it so the imported
282+
// ContextElementDependency does not come from the same Webpack instance that is used
283+
// in the compilation. In that case, we can pass the right one as an option to the plugin.
284+
this._contextElementDependencyConstructor = options.contextElementDependencyConstructor
285+
|| require('webpack/lib/dependencies/ContextElementDependency');
286+
270287
// Create the webpack compiler host.
271288
const webpackCompilerHost = new WebpackCompilerHost(
272289
this._compilerOptions,
@@ -633,7 +650,7 @@ export class AngularCompilerPlugin {
633650
if (modulePath !== null) {
634651
const name = importPath.replace(/(\.ngfactory)?\.(js|ts)$/, '');
635652

636-
return new ContextElementDependency(modulePath, name);
653+
return new this._contextElementDependencyConstructor(modulePath, name);
637654
} else {
638655
return null;
639656
}

0 commit comments

Comments
 (0)