Skip to content

Commit 2b1722b

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 3e8b0e8 commit 2b1722b

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+
* `contextElementDependencyClass`. 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
@@ -13,6 +13,7 @@ import { ChildProcess, ForkOptions, fork } from 'child_process';
1313
import * as fs from 'fs';
1414
import * as path from 'path';
1515
import * as ts from 'typescript';
16+
import * as webpack from 'webpack';
1617
import { time, timeEnd } from './benchmark';
1718
import { WebpackCompilerHost, workaroundResolve } from './compiler_host';
1819
import { resolveEntryModuleFromMain } from './entry_resolver';
@@ -54,8 +55,6 @@ import {
5455
VirtualWatchFileSystemDecorator,
5556
} from './virtual_file_system_decorator';
5657

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

6160

@@ -86,6 +85,11 @@ export interface AngularCompilerPluginOptions {
8685
// added to the list of lazy routes
8786
additionalLazyModules?: { [module: string]: string };
8887

88+
// The ContextElementDependency of correct Webpack compilation.
89+
// This is needed when there are multiple Webpack installs.
90+
// tslint:disable-next-line:no-any
91+
contextElementDependencyClass?: any;
92+
8993
// Use tsconfig to include path globs.
9094
compilerOptions?: ts.CompilerOptions;
9195

@@ -128,6 +132,8 @@ export class AngularCompilerPlugin {
128132
private _normalizedLocale: string | null;
129133
private _warnings: (string | Error)[] = [];
130134
private _errors: (string | Error)[] = [];
135+
// tslint:disable-next-line:no-any
136+
private _contextElementDependencyClass: any;
131137

132138
// TypeChecker process.
133139
private _forkTypeChecker = true;
@@ -267,6 +273,17 @@ export class AngularCompilerPlugin {
267273
this._platformTransformers = options.platformTransformers;
268274
}
269275

276+
// Default ContextElementDependency to the one we can import from here.
277+
if (options.contextElementDependencyClass === undefined) {
278+
// Failing to use the right ContextElementDependency will throw the error below:
279+
// "No module factory available for dependency type: ContextElementDependency"
280+
// Hoisting together with peer dependencies can make it so the imported
281+
// ContextElementDependency does not come from the same Webpack instance that is used
282+
// in the compilation. In that case, we can pass the right one as an option to the plugin.
283+
this._contextElementDependencyClass =
284+
require('webpack/lib/dependencies/ContextElementDependency');
285+
}
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._contextElementDependencyClass(modulePath, name);
637654
} else {
638655
return null;
639656
}

0 commit comments

Comments
 (0)