Skip to content

Commit 47cdf11

Browse files
clydinfilipesilva
authored andcommitted
feat(@ngtools/webpack): support webpack 4 plugin system
BREAKING CHANGE: Webpack ^4.0.0 is now required as a peer dependency.
1 parent 487cb80 commit 47cdf11

File tree

17 files changed

+100
-275
lines changed

17 files changed

+100
-275
lines changed

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@
6868
"license-webpack-plugin": "^1.1.2",
6969
"loader-utils": "^1.1.0",
7070
"lodash": "^4.11.1",
71-
"magic-string": "^0.22.3",
7271
"memory-fs": "^0.4.1",
7372
"minimatch": "^3.0.4",
7473
"node-modules-path": "^1.0.0",
@@ -86,7 +85,6 @@
8685
"sass-loader": "^6.0.6",
8786
"semver": "^5.3.0",
8887
"silent-error": "^1.0.0",
89-
"source-map": "^0.5.6",
9088
"source-map-support": "^0.4.1",
9189
"style-loader": "^0.20.2",
9290
"stylus": "^0.54.5",

packages/@ngtools/webpack/README.md

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Angular Ahead-of-Time Webpack Plugin
22

3-
Webpack plugin that AoT compiles your Angular components and modules.
3+
Webpack 4.0 plugin that AoT compiles your Angular components and modules.
44

55
## Usage
66

@@ -31,31 +31,6 @@ exports = { /* ... */
3131
}
3232
```
3333

34-
Angular version 2 and 4, use `AotPlugin`:
35-
36-
```typescript
37-
import {AotPlugin} from '@ngtools/webpack'
38-
39-
exports = { /* ... */
40-
module: {
41-
rules: [
42-
{
43-
test: /\.ts$/,
44-
loader: '@ngtools/webpack'
45-
}
46-
]
47-
},
48-
49-
plugins: [
50-
new AotPlugin({
51-
tsConfigPath: 'path/to/tsconfig.json',
52-
entryModule: 'path/to/app.module#AppModule',
53-
sourceMap: true
54-
})
55-
]
56-
}
57-
```
58-
5934
The loader works with webpack plugin to compile your TypeScript. It's important to include both, and to not include any other TypeScript compiler loader.
6035

6136
## Options
@@ -65,8 +40,6 @@ The loader works with webpack plugin to compile your TypeScript. It's important
6540
* `entryModule`. Optional if specified in `angularCompilerOptions`. The path and classname of the main application module. This follows the format `path/to/file#ClassName`.
6641
* `mainPath`. Optional if `entryModule` is specified. The `main.ts` file containing the bootstrap code. The plugin will use AST to determine the `entryModule`.
6742
* `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.
68-
* `typeChecking`. Optional, defaults to true. Enable type checking through your application. This will slow down compilation, but show syntactic and semantic errors in webpack. Only available in `AotPlugin`.
69-
* `exclude`. Optional. Extra files to exclude from TypeScript compilation. Not supported with `AngularCompilerPlugin`.
7043
* `sourceMap`. Optional. Include sourcemaps.
7144
* `compilerOptions`. Optional. Override options in `tsconfig.json`.
7245

packages/@ngtools/webpack/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@
2727
"dependencies": {
2828
"tree-kill": "^1.0.0",
2929
"chalk": "~2.2.0",
30-
"magic-string": "^0.22.3",
3130
"semver": "^5.3.0",
32-
"source-map": "^0.5.6",
3331
"webpack-sources": "^1.1.0"
3432
},
3533
"peerDependencies": {
36-
"webpack": "^2.2.0 || ^3.0.0 || ^4.0.0-beta.0 || ^4.0.0"
34+
"webpack": "^4.0.0"
3735
}
3836
}

packages/@ngtools/webpack/src/angular_compiler_plugin.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -547,14 +547,14 @@ export class AngularCompilerPlugin {
547547
apply(compiler: any) {
548548
// Decorate inputFileSystem to serve contents of CompilerHost.
549549
// Use decorated inputFileSystem in watchFileSystem.
550-
compiler.plugin('environment', () => {
550+
compiler.hooks.environment.tap('angular-compiler', () => {
551551
compiler.inputFileSystem = new VirtualFileSystemDecorator(
552552
compiler.inputFileSystem, this._compilerHost);
553553
compiler.watchFileSystem = new VirtualWatchFileSystemDecorator(compiler.inputFileSystem);
554554
});
555555

556556
// Add lazy modules to the context module for @angular/core
557-
compiler.plugin('context-module-factory', (cmf: any) => {
557+
compiler.hooks.contextModuleFactory.tap('angular-compiler', (cmf: any) => {
558558
const angularCorePackagePath = require.resolve('@angular/core/package.json');
559559
const angularCorePackageJson = require(angularCorePackagePath);
560560
const angularCoreModulePath = path.resolve(path.dirname(angularCorePackagePath),
@@ -572,7 +572,8 @@ export class AngularCompilerPlugin {
572572
angularCoreEs2015Dir = path.dirname(angularCoreEs2015Path).split(/node_modules/).pop();
573573
}
574574

575-
cmf.plugin('after-resolve', (result: any, callback: (err?: any, request?: any) => void) => {
575+
cmf.hooks.afterResolve.tapAsync('angular-compiler',
576+
(result: any, callback: (err?: any, request?: any) => void) => {
576577
if (!result) {
577578
return callback();
578579
}
@@ -618,33 +619,36 @@ export class AngularCompilerPlugin {
618619
});
619620

620621
// Create and destroy forked type checker on watch mode.
621-
compiler.plugin('watch-run', (_compiler: any, callback: any) => {
622+
compiler.hooks.watchRun.tapAsync('angular-compiler', (_compiler: any, callback: any) => {
622623
if (this._forkTypeChecker && !this._typeCheckerProcess) {
623624
this._createForkedTypeChecker();
624625
}
625626
callback();
626627
});
627-
compiler.plugin('watch-close', () => this._killForkedTypeChecker());
628+
compiler.hooks.watchClose.tap('angular-compiler', () => this._killForkedTypeChecker());
628629

629630
// Remake the plugin on each compilation.
630-
compiler.plugin('make', (compilation: any, cb: any) => this._make(compilation, cb));
631-
compiler.plugin('invalid', () => this._firstRun = false);
632-
compiler.plugin('after-emit', (compilation: any, cb: any) => {
631+
compiler.hooks.make.tapAsync(
632+
'angular-compiler',
633+
(compilation: any, cb: any) => this._make(compilation, cb),
634+
);
635+
compiler.hooks.invalid.tap('angular-compiler', () => this._firstRun = false);
636+
compiler.hooks.afterEmit.tapAsync('angular-compiler', (compilation: any, cb: any) => {
633637
compilation._ngToolsWebpackPluginInstance = null;
634638
cb();
635639
});
636-
compiler.plugin('done', () => {
640+
compiler.hooks.done.tap('angular-compiler', () => {
637641
this._donePromise = null;
638642
});
639643

640-
compiler.plugin('after-resolvers', (compiler: any) => {
641-
compiler.plugin('normal-module-factory', (nmf: any) => {
644+
compiler.hooks.afterResolvers.tap('angular-compiler', (compiler: any) => {
645+
compiler.hooks.normalModuleFactory.tap('angular-compiler', (nmf: any) => {
642646
// Virtual file system.
643647
// TODO: consider if it's better to remove this plugin and instead make it wait on the
644648
// VirtualFileSystemDecorator.
645649
// Wait for the plugin to be done when requesting `.ts` files directly (entry points), or
646650
// when the issuer is a `.ts` or `.ngfactory.js` file.
647-
nmf.plugin('before-resolve', (request: any, callback: any) => {
651+
nmf.hooks.beforeResolve.tapAsync('angular-compiler', (request: any, callback: any) => {
648652
if (this.done && (request.request.endsWith('.ts')
649653
|| (request.context.issuer && /\.ts|ngfactory\.js$/.test(request.context.issuer)))) {
650654
this.done.then(() => callback(null, request), () => callback(null, request));
@@ -655,8 +659,8 @@ export class AngularCompilerPlugin {
655659
});
656660
});
657661

658-
compiler.plugin('normal-module-factory', (nmf: any) => {
659-
nmf.plugin('before-resolve', (request: any, callback: any) => {
662+
compiler.hooks.normalModuleFactory.tap('angular-compiler', (nmf: any) => {
663+
nmf.hooks.beforeResolve.tapAsync('angular-compiler', (request: any, callback: any) => {
660664
resolveWithPaths(
661665
request,
662666
callback,

packages/@ngtools/webpack/src/extract_i18n_plugin.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ export interface ExtractI18nPluginOptions {
1919
export class ExtractI18nPlugin implements Tapable {
2020
private _resourceLoader: WebpackResourceLoader;
2121

22-
private _compilation: any = null;
23-
2422
private _tsConfigPath: string;
2523
private _basePath: string;
2624
private _rootFilePath: string[];
@@ -137,27 +135,28 @@ export class ExtractI18nPlugin implements Tapable {
137135
}
138136

139137
apply(compiler: any) {
140-
compiler.plugin('make', (compilation: any, cb: any) => this._make(compilation, cb));
138+
compiler.hooks.make.tapAsync(
139+
'extract-i8n',
140+
(compilation: any, cb: any) => this._make(compilation, cb)
141+
);
141142

142-
compiler.plugin('after-emit', (compilation: any, cb: any) => {
143-
this._compilation = null;
143+
compiler.hooks.afterEmit.tapAsync('extract-i8n', (compilation: any, cb: any) => {
144144
compilation._ngToolsWebpackXi18nPluginInstance = null;
145145
cb();
146146
});
147147
}
148148

149149
private _make(compilation: any, cb: (err?: any, request?: any) => void) {
150-
this._compilation = compilation;
151-
if (this._compilation._ngToolsWebpackXi18nPluginInstance) {
150+
if (compilation._ngToolsWebpackXi18nPluginInstance) {
152151
return cb(new Error('An @ngtools/webpack xi18n plugin already exist for ' +
153152
'this compilation.'));
154153
}
155-
if (!this._compilation._ngToolsWebpackPluginInstance) {
154+
if (!compilation._ngToolsWebpackPluginInstance) {
156155
return cb(new Error('An @ngtools/webpack aot plugin does not exists ' +
157156
'for this compilation'));
158157
}
159158

160-
this._compilation._ngToolsWebpackXi18nPluginInstance = this;
159+
compilation._ngToolsWebpackXi18nPluginInstance = this;
161160

162161
this._resourceLoader.update(compilation);
163162

@@ -177,7 +176,7 @@ export class ExtractI18nPlugin implements Tapable {
177176
});
178177
})
179178
.then(() => cb(), (err: any) => {
180-
this._compilation.errors.push(err);
179+
compilation.errors.push(err);
181180
cb(err);
182181
});
183182

packages/@ngtools/webpack/src/lazy_routes.ts

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {dirname, join} from 'path';
22
import * as ts from 'typescript';
3-
4-
import {TypeScriptFileRefactor} from './refactor';
3+
import { findAstNodes, resolve } from './refactor';
54

65

76
function _getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): string | null {
@@ -20,23 +19,41 @@ export interface LazyRouteMap {
2019
}
2120

2221

23-
export function findLazyRoutes(filePath: string,
24-
host: ts.CompilerHost,
25-
program?: ts.Program,
26-
compilerOptions?: ts.CompilerOptions): LazyRouteMap {
27-
const refactor = new TypeScriptFileRefactor(filePath, host, program);
22+
export function findLazyRoutes(
23+
filePath: string,
24+
host: ts.CompilerHost,
25+
program?: ts.Program,
26+
compilerOptions?: ts.CompilerOptions
27+
): LazyRouteMap {
28+
if (!compilerOptions && program) {
29+
compilerOptions = program.getCompilerOptions();
30+
}
31+
const fileName = resolve(filePath, host, compilerOptions).replace(/\\/g, '/');
32+
let sourceFile: ts.SourceFile;
33+
if (program) {
34+
sourceFile = program.getSourceFile(fileName);
35+
}
36+
if (!sourceFile) {
37+
sourceFile = ts.createSourceFile(
38+
fileName,
39+
host.readFile(fileName),
40+
ts.ScriptTarget.Latest,
41+
true,
42+
);
43+
}
44+
if (!sourceFile) {
45+
throw new Error(`Source file not found: '${fileName}'.`);
46+
}
2847

29-
return refactor
30-
// Find all object literals in the file.
31-
.findAstNodes(null, ts.SyntaxKind.ObjectLiteralExpression, true)
48+
return findAstNodes(null, sourceFile, ts.SyntaxKind.ObjectLiteralExpression, true)
3249
// Get all their property assignments.
3350
.map((node: ts.ObjectLiteralExpression) => {
34-
return refactor.findAstNodes(node, ts.SyntaxKind.PropertyAssignment, false);
51+
return findAstNodes(node, sourceFile, ts.SyntaxKind.PropertyAssignment, false);
3552
})
3653
// Take all `loadChildren` elements.
3754
.reduce((acc: ts.PropertyAssignment[], props: ts.PropertyAssignment[]) => {
3855
return acc.concat(props.filter(literal => {
39-
return _getContentOfKeyLiteral(refactor.sourceFile, literal.name) == 'loadChildren';
56+
return _getContentOfKeyLiteral(sourceFile, literal.name) == 'loadChildren';
4057
}));
4158
}, [])
4259
// Get only string values.

0 commit comments

Comments
 (0)