Skip to content

Commit 7d9ead4

Browse files
filipesilvaKeen Yee Liau
authored andcommitted
feat(@angular-devkit/build-optimizer): add BuildOptimizerWebpackPlugin
Using this webpack allows determining in advance if files from a package should be skipped by the Build Optimizer loader.
1 parent b48dede commit 7d9ead4

File tree

5 files changed

+69
-3
lines changed

5 files changed

+69
-3
lines changed

etc/api/angular_devkit/build_optimizer/src/_golden-api.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
export declare function buildOptimizer(options: BuildOptimizerOptions): TransformJavascriptOutput;
22

3+
export declare const buildOptimizerLoaderPath: string;
4+
5+
export declare class BuildOptimizerWebpackPlugin {
6+
apply(compiler: Compiler): void;
7+
}
8+
39
export default function buildOptimizerLoader(this: webpack.loader.LoaderContext, content: string, previousSourceMap: RawSourceMap): void;
410

511
export declare function getFoldFileTransformer(program: ts.Program): ts.TransformerFactory<ts.SourceFile>;

packages/angular_devkit/build_optimizer/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,12 @@ export interface BuildOptimizerOptions {
186186
## Webpack loader usage:
187187

188188
```typescript
189+
import { BuildOptimizerWebpackPlugin } from '@angular-devkit/build-optimizer';
190+
189191
module.exports = {
192+
plugins: [
193+
new BuildOptimizerWebpackPlugin(),
194+
]
190195
module: {
191196
rules: [
192197
{

packages/angular_devkit/build_optimizer/src/build-optimizer/webpack-loader.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,31 @@ interface BuildOptimizerLoaderOptions {
1717
sourceMap: boolean;
1818
}
1919

20+
const alwaysProcess = (path: string) =>
21+
// Always process TS files.
22+
path.endsWith('.ts') || path.endsWith('.tsx')
23+
// Always process factory files.
24+
|| path.endsWith('.ngfactory.js') || path.endsWith('.ngstyle.js');
25+
2026
export default function buildOptimizerLoader
2127
(this: webpack.loader.LoaderContext, content: string, previousSourceMap: RawSourceMap) {
2228
this.cacheable();
29+
30+
const skipBuildOptimizer = this._module
31+
&& this._module.factoryMeta
32+
&& this._module.factoryMeta.skipBuildOptimizer;
33+
34+
if (!alwaysProcess(this.resourcePath) && skipBuildOptimizer) {
35+
// Skip loading processing this file with Build Optimizer if we determined in
36+
// BuildOptimizerWebpackPlugin that we shouldn't.
37+
38+
// Webpack typings for previousSourceMap are wrong, they are JSON objects and not strings.
39+
// tslint:disable-next-line:no-any
40+
this.callback(null, content, previousSourceMap as any);
41+
42+
return;
43+
}
44+
2345
const options: BuildOptimizerLoaderOptions = loaderUtils.getOptions(this) || {};
2446

2547
// Make up names of the intermediate files so we can chain the sourcemaps.
@@ -33,12 +55,11 @@ export default function buildOptimizerLoader
3355
outputFilePath,
3456
emitSourceMap: options.sourceMap,
3557
isSideEffectFree: this._module
36-
&& this._module.factoryMeta
37-
&& this._module.factoryMeta.sideEffectFree,
58+
&& this._module.factoryMeta
59+
&& this._module.factoryMeta.sideEffectFree,
3860
});
3961

4062
if (boOutput.emitSkipped || boOutput.content === null) {
41-
// Webpack typings for previousSourceMap are wrong, they are JSON objects and not strings.
4263
// tslint:disable-next-line:no-any
4364
this.callback(null, content, previousSourceMap as any);
4465

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
/**
3+
* @license
4+
* Copyright Google Inc. All Rights Reserved.
5+
*
6+
* Use of this source code is governed by an MIT-style license that can be
7+
* found in the LICENSE file at https://angular.io/license
8+
*/
9+
import { Compiler } from 'webpack'; // tslint:disable-line:no-implicit-dependencies
10+
11+
export class BuildOptimizerWebpackPlugin {
12+
apply(compiler: Compiler) {
13+
compiler.hooks.normalModuleFactory.tap("BuildOptimizerWebpackPlugin", nmf => {
14+
nmf.hooks.module.tap("BuildOptimizerWebpackPlugin", (module, data) => {
15+
const resolveData = data.resourceResolveData;
16+
if (resolveData && resolveData.descriptionFileData) {
17+
// Only TS packages should use Build Optimizer.
18+
const typings = resolveData.descriptionFileData.typings;
19+
// Notes:
20+
// - a TS package might not have defined typings but still use .d.ts files next to their
21+
// .js files. We don't cover that case because the Angular Package Format (APF) calls for
22+
// using the Typings field and Build Optimizer is geared towards APF. Maybe we could
23+
// provide configuration options to the plugin to cover that case if there's demand.
24+
// - a JS-only package that also happens to provides typings will also be flagged by this
25+
// check. Not sure there's a good way to skip those.
26+
module.factoryMeta.skipBuildOptimizer = !typings;
27+
}
28+
29+
return module;
30+
});
31+
});
32+
}
33+
}

packages/angular_devkit/build_optimizer/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88
export { default as buildOptimizerLoader } from './build-optimizer/webpack-loader';
9+
export { BuildOptimizerWebpackPlugin } from './build-optimizer/webpack-plugin';
910
export { buildOptimizer } from './build-optimizer/build-optimizer';
1011

1112
export { transformJavascript } from './helpers/transform-javascript';

0 commit comments

Comments
 (0)