Commit fbe81434 by Lutfi

init

parents
The MIT License
Copyright (c) 2017 Google, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
# Snapshot build of @angular-devkit/build-angular
This repository is a snapshot of a commit on the original repository. The original code used to
generate this is located at http://github.com/angular/angular-cli.
We do not accept PRs or Issues opened on this repository. You should not use this over a tested and
released version of this package.
To test this snapshot in your own project, use
```bash
npm install git+https://github.com/angular/angular-devkit-build-angular-builds.git
```
----
# Angular Webpack Build Facade
WIP
\ No newline at end of file
{
"$schema": "../architect/src/builders-schema.json",
"builders": {
"app-shell": {
"implementation": "./src/app-shell",
"schema": "./src/app-shell/schema.json",
"description": "Build a server app and a browser app, then render the index.html and use it for the browser output."
},
"browser": {
"implementation": "./src/browser",
"schema": "./src/browser/schema.json",
"description": "Build a browser app."
},
"dev-server": {
"implementation": "./src/dev-server",
"schema": "./src/dev-server/schema.json",
"description": "Serve a browser app."
},
"extract-i18n": {
"implementation": "./src/extract-i18n",
"schema": "./src/extract-i18n/schema.json",
"description": "Extract i18n strings from a browser app."
},
"karma": {
"implementation": "./src/karma",
"schema": "./src/karma/schema.json",
"description": "Run Karma unit tests."
},
"protractor": {
"implementation": "./src/protractor",
"schema": "./src/protractor/schema.json",
"description": "Run protractor over a dev server."
},
"tslint": {
"implementation": "./src/tslint",
"schema": "./src/tslint/schema.json",
"description": "Run tslint over a TS project."
},
"server": {
"implementation": "./src/server",
"schema": "./src/server/schema.json",
"description": "Build a server Angular application."
}
}
}
{
"name": "@angular-devkit/build-angular",
"version": "0.901.15+5.cff09e4",
"description": "Angular Webpack Build Facade",
"experimental": true,
"main": "src/index.js",
"typings": "src/index.d.ts",
"builders": "builders.json",
"dependencies": {
"@angular-devkit/architect": "github:angular/angular-devkit-architect-builds#cff09e433",
"@angular-devkit/build-optimizer": "github:angular/angular-devkit-build-optimizer-builds#cff09e433",
"@angular-devkit/build-webpack": "github:angular/angular-devkit-build-webpack-builds#cff09e433",
"@angular-devkit/core": "github:angular/angular-devkit-core-builds#cff09e433",
"@babel/core": "7.9.0",
"@babel/generator": "7.9.3",
"@babel/preset-env": "7.9.0",
"@babel/template": "7.8.6",
"@jsdevtools/coverage-istanbul-loader": "3.0.3",
"@ngtools/webpack": "github:angular/ngtools-webpack-builds#cff09e433",
"ajv": "6.12.3",
"autoprefixer": "9.7.4",
"babel-loader": "8.0.6",
"browserslist": "^4.9.1",
"cacache": "15.0.0",
"caniuse-lite": "^1.0.30001032",
"circular-dependency-plugin": "5.2.0",
"copy-webpack-plugin": "6.0.3",
"core-js": "3.6.4",
"css-loader": "3.5.1",
"cssnano": "4.1.10",
"file-loader": "6.0.0",
"find-cache-dir": "3.3.1",
"glob": "7.1.6",
"jest-worker": "25.1.0",
"karma-source-map-support": "1.4.0",
"less": "3.11.3",
"less-loader": "5.0.0",
"license-webpack-plugin": "2.1.4",
"loader-utils": "2.0.0",
"mini-css-extract-plugin": "0.9.0",
"minimatch": "3.0.4",
"parse5": "4.0.0",
"open": "7.0.3",
"postcss": "github:LutfiArdiansyah/postcss",
"postcss-import": "12.0.1",
"postcss-loader": "3.0.0",
"raw-loader": "4.0.0",
"regenerator-runtime": "0.13.5",
"rimraf": "3.0.2",
"rollup": "2.1.0",
"rxjs": "6.5.4",
"sass": "1.26.3",
"sass-loader": "8.0.2",
"semver": "7.1.3",
"source-map": "0.7.3",
"source-map-loader": "0.2.4",
"speed-measure-webpack-plugin": "1.3.1",
"style-loader": "1.1.3",
"stylus": "0.54.7",
"stylus-loader": "3.0.2",
"tree-kill": "1.2.2",
"terser": "4.6.10",
"terser-webpack-plugin": "3.0.3",
"webpack": "4.42.0",
"webpack-dev-middleware": "github:LutfiArdiansyah/webpack-dev-middleware",
"webpack-dev-server": "3.11.0",
"webpack-merge": "4.2.2",
"webpack-sources": "1.4.3",
"webpack-subresource-integrity": "1.4.0",
"worker-plugin": "4.0.3"
},
"peerDependencies": {
"@angular/compiler-cli": ">=9.0.0 < 10",
"typescript": ">=3.6 < 3.9"
},
"peerDependenciesMeta": {
"@angular/localize": {
"optional": true
}
},
"keywords": [
"angular",
"Angular CLI",
"devkit",
"sdk",
"Angular DevKit"
],
"repository": {
"type": "git",
"url": "https://github.com/angular/angular-cli.git"
},
"engines": {
"node": ">= 10.13.0",
"npm": "^6.11.0 || ^7.5.6",
"yarn": ">= 1.13.0"
},
"author": "Angular Authors",
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular-cli/issues"
},
"homepage": "https://github.com/angular/angular-cli",
"husky": {
"hooks": {
"pre-push": "node ./bin/devkit-admin hooks/pre-push"
}
}
}
/**
* @license
* Copyright Google Inc. 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
*/
/**
* @license
* Copyright Google Inc. 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
*/
module.exports = require('../src/angular-cli-files/plugins/karma');
/**
* @license
* Copyright Google Inc. 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 { analytics } from '@angular-devkit/core';
import { Compiler, Module, Stats, compilation } from 'webpack';
import { Source } from 'webpack-sources';
declare const NormalModule: any;
interface NormalModule extends Module {
_source?: Source | null;
resource?: string;
}
/**
* Faster than using a RegExp, so we use this to count occurences in source code.
* @param source The source to look into.
* @param match The match string to look for.
* @param wordBreak Whether to check for word break before and after a match was found.
* @return The number of matches found.
* @private
*/
export declare function countOccurrences(source: string, match: string, wordBreak?: boolean): number;
/**
* Holder of statistics related to the build.
*/
declare class AnalyticsBuildStats {
errors: string[];
numberOfNgOnInit: number;
numberOfComponents: number;
initialChunkSize: number;
totalChunkCount: number;
totalChunkSize: number;
lazyChunkCount: number;
lazyChunkSize: number;
assetCount: number;
assetSize: number;
polyfillSize: number;
cssSize: number;
}
/**
* Analytics plugin that reports the analytics we want from the CLI.
*/
export declare class NgBuildAnalyticsPlugin {
protected _projectRoot: string;
protected _analytics: analytics.Analytics;
protected _category: string;
private _isIvy;
protected _built: boolean;
protected _stats: AnalyticsBuildStats;
constructor(_projectRoot: string, _analytics: analytics.Analytics, _category: string, _isIvy: boolean);
protected _reset(): void;
protected _getMetrics(stats: Stats): (string | number)[];
protected _getDimensions(stats: Stats): import("../../../../../dist-schema/packages/angular/cli/commands/config").Value[];
protected _reportBuildMetrics(stats: Stats): void;
protected _reportRebuildMetrics(stats: Stats): void;
protected _checkTsNormalModule(module: NormalModule): void;
protected _checkNgFactoryNormalModule(module: NormalModule): void;
protected _collectErrors(stats: Stats): void;
protected _collectBundleStats(json: any): void;
/************************************************************************************************
* The next section is all the different Webpack hooks for this plugin.
*/
/**
* Reports a succeed module.
* @private
*/
protected _succeedModule(mod: Module): void;
protected _compilation(compiler: Compiler, compilation: compilation.Compilation): void;
protected _done(stats: Stats): void;
apply(compiler: Compiler): void;
}
export {};
/**
* @license
* Copyright Google Inc. 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 { logging } from '@angular-devkit/core';
import { ParsedConfiguration } from '@angular/compiler-cli';
import { AssetPatternClass, Budget, CrossOrigin, ExtraEntryPoint, I18NMissingTranslation, Localize, OptimizationClass, SourceMapClass } from '../../browser/schema';
import { NormalizedFileReplacement } from '../../utils/normalize-file-replacements';
export interface BuildOptions {
optimization: OptimizationClass;
environment?: string;
outputPath: string;
resourcesOutputPath?: string;
aot?: boolean;
sourceMap: SourceMapClass;
/** @deprecated since version 8. use sourceMap instead. */
vendorSourceMap?: boolean;
/** @deprecated since version 8 */
evalSourceMap?: boolean;
vendorChunk?: boolean;
commonChunk?: boolean;
baseHref?: string;
deployUrl?: string;
verbose?: boolean;
progress?: boolean;
/** @deprecated since version 9. Use 'locales' object in the project metadata instead.*/
i18nFile?: string;
/** @deprecated since version 9. No longer needed as the format will be determined automatically.*/
i18nFormat?: string;
/** @deprecated since version 9. Use 'localize' instead.*/
i18nLocale?: string;
localize?: Localize;
i18nMissingTranslation?: I18NMissingTranslation;
extractCss?: boolean;
bundleDependencies?: boolean;
externalDependencies?: string[];
watch?: boolean;
outputHashing?: string;
poll?: number;
deleteOutputPath?: boolean;
preserveSymlinks?: boolean;
extractLicenses?: boolean;
showCircularDependencies?: boolean;
buildOptimizer?: boolean;
namedChunks?: boolean;
crossOrigin?: CrossOrigin;
subresourceIntegrity?: boolean;
serviceWorker?: boolean;
webWorkerTsConfig?: string;
/** @deprecated since version 8 **/
skipAppShell?: boolean;
statsJson: boolean;
forkTypeChecker: boolean;
profile?: boolean;
/** @deprecated since version 8 **/
es5BrowserSupport?: boolean;
main: string;
polyfills?: string;
budgets: Budget[];
assets: AssetPatternClass[];
scripts: ExtraEntryPoint[];
styles: ExtraEntryPoint[];
stylePreprocessorOptions?: {
includePaths: string[];
};
/** @deprecated SystemJsNgModuleLoader is deprecated, and this is part of its usage. */
lazyModules: string[];
platform?: 'browser' | 'server';
fileReplacements: NormalizedFileReplacement[];
/** @deprecated use only for compatibility in 8.x; will be removed in 9.0 */
rebaseRootRelativeCssUrls?: boolean;
esVersionInFileName?: boolean;
experimentalRollupPass?: boolean;
}
export interface WebpackTestOptions extends BuildOptions {
codeCoverage?: boolean;
codeCoverageExclude?: string[];
}
export interface WebpackConfigOptions<T = BuildOptions> {
root: string;
logger: logging.Logger;
projectRoot: string;
sourceRoot?: string;
buildOptions: T;
tsConfig: ParsedConfiguration;
tsConfigPath: string;
supportES2015: boolean;
differentialLoadingMode?: boolean;
}
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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 'core-js/es/reflect';
/**
* @license
* Copyright Google Inc. 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
*/
// ES2015 symbol capabilities
import 'core-js/es/symbol';
// ES2015 function capabilities
import 'core-js/modules/es.function.bind';
import 'core-js/modules/es.function.name';
import 'core-js/modules/es.function.has-instance';
// ES2015 object capabilities
import 'core-js/modules/es.object.create';
import 'core-js/modules/es.object.define-property';
import 'core-js/modules/es.object.define-properties';
import 'core-js/modules/es.object.get-own-property-descriptor';
import 'core-js/modules/es.object.get-prototype-of';
import 'core-js/modules/es.object.keys';
import 'core-js/modules/es.object.get-own-property-names';
import 'core-js/modules/es.object.freeze';
import 'core-js/modules/es.object.seal';
import 'core-js/modules/es.object.prevent-extensions';
import 'core-js/modules/es.object.is-frozen';
import 'core-js/modules/es.object.is-sealed';
import 'core-js/modules/es.object.is-extensible';
import 'core-js/modules/es.object.assign';
import 'core-js/modules/es.object.is';
import 'core-js/modules/es.object.set-prototype-of';
import 'core-js/modules/es.object.to-string';
// ES2015 array capabilities
import 'core-js/modules/es.array.concat';
import 'core-js/modules/es.array.is-array';
import 'core-js/modules/es.array.from';
import 'core-js/modules/es.array.of';
import 'core-js/modules/es.array.join';
import 'core-js/modules/es.array.slice';
import 'core-js/modules/es.array.splice';
import 'core-js/modules/es.array.sort';
import 'core-js/modules/es.array.for-each';
import 'core-js/modules/es.array.map';
import 'core-js/modules/es.array.filter';
import 'core-js/modules/es.array.some';
import 'core-js/modules/es.array.every';
import 'core-js/modules/es.array.reduce';
import 'core-js/modules/es.array.reduce-right';
import 'core-js/modules/es.array.index-of';
import 'core-js/modules/es.array.last-index-of';
import 'core-js/modules/es.array.copy-within';
import 'core-js/modules/es.array.fill';
import 'core-js/modules/es.array.find';
import 'core-js/modules/es.array.find-index';
import 'core-js/modules/es.array.iterator';
// ES2015 string capabilities
import 'core-js/modules/es.string.from-code-point';
import 'core-js/modules/es.string.raw';
import 'core-js/modules/es.string.trim';
import 'core-js/modules/es.string.iterator';
import 'core-js/modules/es.string.code-point-at';
import 'core-js/modules/es.string.ends-with';
import 'core-js/modules/es.string.includes';
import 'core-js/modules/es.string.repeat';
import 'core-js/modules/es.string.starts-with';
import 'core-js/modules/es.string.anchor';
import 'core-js/modules/es.string.big';
import 'core-js/modules/es.string.blink';
import 'core-js/modules/es.string.bold';
import 'core-js/modules/es.string.fixed';
import 'core-js/modules/es.string.fontcolor';
import 'core-js/modules/es.string.fontsize';
import 'core-js/modules/es.string.italics';
import 'core-js/modules/es.string.link';
import 'core-js/modules/es.string.small';
import 'core-js/modules/es.string.strike';
import 'core-js/modules/es.string.sub';
import 'core-js/modules/es.string.sup';
import 'core-js/modules/es.string.match';
import 'core-js/modules/es.string.replace';
import 'core-js/modules/es.string.search';
import 'core-js/modules/es.string.split';
import 'core-js/modules/es.parse-int';
import 'core-js/modules/es.parse-float';
import 'core-js/es/number';
import 'core-js/es/math';
import 'core-js/es/date';
import 'core-js/modules/es.regexp.constructor';
import 'core-js/modules/es.regexp.to-string';
import 'core-js/modules/es.regexp.flags';
import 'core-js/modules/es.map';
import 'core-js/modules/es.weak-map';
import 'core-js/modules/es.set';
import 'core-js/modules/web.dom-collections.for-each';
import 'core-js/modules/web.dom-collections.iterator';
import 'core-js/modules/es.promise';
import 'core-js/modules/es.json.to-string-tag';
import 'regenerator-runtime/runtime';
\ No newline at end of file
/**
* @license
* Copyright Google Inc. 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 'core-js/proposals/reflect-metadata';
import * as webpack from 'webpack';
import { WebpackConfigOptions } from '../build-options';
export declare function getBrowserConfig(wco: WebpackConfigOptions): webpack.Configuration;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const license_webpack_plugin_1 = require("license-webpack-plugin");
const utils_1 = require("./utils");
const SubresourceIntegrityPlugin = require('webpack-subresource-integrity');
function getBrowserConfig(wco) {
const { buildOptions } = wco;
const { crossOrigin = 'none', subresourceIntegrity, evalSourceMap, extractLicenses, vendorChunk, commonChunk, styles, } = buildOptions;
const extraPlugins = [];
let isEval = false;
const { styles: stylesOptimization, scripts: scriptsOptimization } = buildOptions.optimization;
const { styles: stylesSourceMap, scripts: scriptsSourceMap, hidden: hiddenSourceMap, } = buildOptions.sourceMap;
// See https://webpack.js.org/configuration/devtool/ for sourcemap types.
if ((stylesSourceMap || scriptsSourceMap) &&
evalSourceMap &&
!stylesOptimization &&
!scriptsOptimization) {
// Produce eval sourcemaps for development with serve, which are faster.
isEval = true;
}
if (subresourceIntegrity) {
extraPlugins.push(new SubresourceIntegrityPlugin({
hashFuncNames: ['sha384'],
}));
}
if (extractLicenses) {
extraPlugins.push(new license_webpack_plugin_1.LicenseWebpackPlugin({
stats: {
warnings: false,
errors: false,
},
perChunkOutput: false,
outputFilename: '3rdpartylicenses.txt',
}));
}
if (!isEval && (scriptsSourceMap || stylesSourceMap)) {
extraPlugins.push(utils_1.getSourceMapDevTool(scriptsSourceMap, stylesSourceMap, wco.differentialLoadingMode ? true : hiddenSourceMap));
}
const globalStylesBundleNames = utils_1.normalizeExtraEntryPoints(styles, 'styles')
.map(style => style.bundleName);
let crossOriginLoading = false;
if (subresourceIntegrity && crossOrigin === 'none') {
crossOriginLoading = 'anonymous';
}
else if (crossOrigin !== 'none') {
crossOriginLoading = crossOrigin;
}
return {
devtool: isEval ? 'eval' : false,
resolve: {
mainFields: [
...(wco.supportES2015 ? ['es2015'] : []),
'browser', 'module', 'main',
],
},
output: {
crossOriginLoading,
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
maxAsyncRequests: Infinity,
cacheGroups: {
default: !!commonChunk && {
chunks: 'async',
minChunks: 2,
priority: 10,
},
common: !!commonChunk && {
name: 'common',
chunks: 'async',
minChunks: 2,
enforce: true,
priority: 5,
},
vendors: false,
vendor: !!vendorChunk && {
name: 'vendor',
chunks: 'initial',
enforce: true,
test: (module, chunks) => {
const moduleName = module.nameForCondition ? module.nameForCondition() : '';
return /[\\/]node_modules[\\/]/.test(moduleName)
&& !chunks.some(({ name }) => utils_1.isPolyfillsEntry(name)
|| globalStylesBundleNames.includes(name));
},
},
},
},
},
plugins: extraPlugins,
node: false,
};
}
exports.getBrowserConfig = getBrowserConfig;
import { Configuration } from 'webpack';
import { WebpackConfigOptions } from '../build-options';
export declare function getCommonConfig(wco: WebpackConfigOptions): Configuration;
/**
* @license
* Copyright Google Inc. 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
*/
export * from './browser';
export * from './common';
export * from './server';
export * from './styles';
export * from './test';
export * from './typescript';
export * from './utils';
export * from './stats';
export * from './worker';
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
__export(require("./browser"));
__export(require("./common"));
__export(require("./server"));
__export(require("./styles"));
__export(require("./test"));
__export(require("./typescript"));
__export(require("./utils"));
__export(require("./stats"));
__export(require("./worker"));
import { Configuration } from 'webpack';
import { WebpackConfigOptions } from '../build-options';
/**
* Returns a partial specific to creating a bundle for node
* @param wco Options which are include the build options and app config
*/
export declare function getServerConfig(wco: WebpackConfigOptions): Configuration;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const path_1 = require("path");
const webpack_1 = require("webpack");
const utils_1 = require("./utils");
/**
* Returns a partial specific to creating a bundle for node
* @param wco Options which are include the build options and app config
*/
function getServerConfig(wco) {
const { sourceMap, bundleDependencies, externalDependencies = [], } = wco.buildOptions;
const extraPlugins = [];
if (sourceMap) {
const { scripts, styles, hidden } = sourceMap;
if (scripts || styles) {
extraPlugins.push(utils_1.getSourceMapDevTool(scripts, styles, hidden));
}
}
const config = {
resolve: {
mainFields: [...(wco.supportES2015 ? ['es2015'] : []), 'main', 'module'],
},
target: 'node',
output: {
libraryTarget: 'commonjs',
},
plugins: [
// Fixes Critical dependency: the request of a dependency is an expression
new webpack_1.ContextReplacementPlugin(/@?hapi(\\|\/)/),
new webpack_1.ContextReplacementPlugin(/express(\\|\/)/),
...extraPlugins,
],
node: false,
};
if (bundleDependencies) {
config.externals = [...externalDependencies];
}
else {
config.externals = [
...externalDependencies,
(context, request, callback) => {
// Absolute & Relative paths are not externals
if (request.startsWith('./') || path_1.isAbsolute(request)) {
callback();
return;
}
try {
require.resolve(request);
callback(null, request);
}
catch (_a) {
// Node couldn't find it, so it must be user-aliased
callback();
}
},
];
}
return config;
}
exports.getServerConfig = getServerConfig;
/**
* @license
* Copyright Google Inc. 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 { WebpackConfigOptions } from '../build-options';
export declare function getWebpackStatsConfig(verbose?: boolean): {
colors: boolean;
hash: boolean;
timings: boolean;
chunks: boolean;
chunkModules: boolean;
children: boolean;
modules: boolean;
reasons: boolean;
warnings: boolean;
errors: boolean;
assets: boolean;
version: boolean;
errorDetails: boolean;
moduleTrace: boolean;
};
export declare function getStatsConfig(wco: WebpackConfigOptions): {
stats: {
colors: boolean;
hash: boolean;
timings: boolean;
chunks: boolean;
chunkModules: boolean;
children: boolean;
modules: boolean;
reasons: boolean;
warnings: boolean;
errors: boolean;
assets: boolean;
version: boolean;
errorDetails: boolean;
moduleTrace: boolean;
};
};
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const webpackOutputOptions = {
colors: true,
hash: true,
timings: true,
chunks: true,
chunkModules: false,
children: false,
modules: false,
reasons: false,
warnings: true,
errors: true,
assets: true,
version: false,
errorDetails: false,
moduleTrace: false,
};
const verboseWebpackOutputOptions = {
// The verbose output will most likely be piped to a file, so colors just mess it up.
colors: false,
usedExports: true,
maxModules: Infinity,
optimizationBailout: true,
reasons: true,
children: true,
assets: true,
version: true,
chunkModules: true,
errorDetails: true,
moduleTrace: true,
};
function getWebpackStatsConfig(verbose = false) {
return verbose
? Object.assign(webpackOutputOptions, verboseWebpackOutputOptions)
: webpackOutputOptions;
}
exports.getWebpackStatsConfig = getWebpackStatsConfig;
function getStatsConfig(wco) {
const verbose = !!wco.buildOptions.verbose;
return { stats: getWebpackStatsConfig(verbose) };
}
exports.getStatsConfig = getStatsConfig;
/**
* @license
* Copyright Google Inc. 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 * as webpack from 'webpack';
import { WebpackConfigOptions } from '../build-options';
export declare function getStylesConfig(wco: WebpackConfigOptions): {
entry: {
[key: string]: string[];
};
module: {
rules: webpack.RuleSetRule[];
};
plugins: webpack.Plugin[];
};
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const webpack_1 = require("../../plugins/webpack");
const utils_1 = require("./utils");
const autoprefixer = require('autoprefixer');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const postcssImports = require('postcss-import');
// tslint:disable-next-line:no-big-function
function getStylesConfig(wco) {
const { root, buildOptions } = wco;
const entryPoints = {};
const globalStylePaths = [];
const extraPlugins = [
new webpack_1.AnyComponentStyleBudgetChecker(buildOptions.budgets),
];
const cssSourceMap = buildOptions.sourceMap.styles;
// Determine hashing format.
const hashFormat = utils_1.getOutputHashFormat(buildOptions.outputHashing);
const postcssPluginCreator = function (loader) {
return [
postcssImports({
resolve: (url) => (url.startsWith('~') ? url.substr(1) : url),
load: (filename) => {
return new Promise((resolve, reject) => {
loader.fs.readFile(filename, (err, data) => {
if (err) {
reject(err);
return;
}
const content = data.toString();
resolve(content);
});
});
},
}),
webpack_1.PostcssCliResources({
baseHref: buildOptions.baseHref,
deployUrl: buildOptions.deployUrl,
resourcesOutputPath: buildOptions.resourcesOutputPath,
loader,
rebaseRootRelative: buildOptions.rebaseRootRelativeCssUrls,
filename: `[name]${hashFormat.file}.[ext]`,
emitFile: buildOptions.platform !== 'server',
}),
autoprefixer(),
];
};
// use includePaths from appConfig
const includePaths = [];
let lessPathOptions = {};
if (buildOptions.stylePreprocessorOptions &&
buildOptions.stylePreprocessorOptions.includePaths &&
buildOptions.stylePreprocessorOptions.includePaths.length > 0) {
buildOptions.stylePreprocessorOptions.includePaths.forEach((includePath) => includePaths.push(path.resolve(root, includePath)));
lessPathOptions = {
paths: includePaths,
};
}
// Process global styles.
if (buildOptions.styles.length > 0) {
const chunkNames = [];
utils_1.normalizeExtraEntryPoints(buildOptions.styles, 'styles').forEach(style => {
const resolvedPath = path.resolve(root, style.input);
// Add style entry points.
if (entryPoints[style.bundleName]) {
entryPoints[style.bundleName].push(resolvedPath);
}
else {
entryPoints[style.bundleName] = [resolvedPath];
}
// Add non injected styles to the list.
if (!style.inject) {
chunkNames.push(style.bundleName);
}
// Add global css paths.
globalStylePaths.push(resolvedPath);
});
if (chunkNames.length > 0) {
// Add plugin to remove hashes from lazy styles.
extraPlugins.push(new webpack_1.RemoveHashPlugin({ chunkNames, hashFormat }));
}
}
let sassImplementation;
try {
// tslint:disable-next-line:no-implicit-dependencies
sassImplementation = require('node-sass');
}
catch (_a) {
sassImplementation = require('sass');
}
// set base rules to derive final rules from
const baseRules = [
{ test: /\.css$/, use: [] },
{
test: /\.scss$|\.sass$/,
use: [
{
loader: require.resolve('sass-loader'),
options: {
implementation: sassImplementation,
sourceMap: cssSourceMap,
sassOptions: {
// bootstrap-sass requires a minimum precision of 8
precision: 8,
includePaths,
// Use expanded as otherwise sass will remove comments that are needed for autoprefixer
// Ex: /* autoprefixer grid: autoplace */
// tslint:disable-next-line: max-line-length
// See: https://github.com/webpack-contrib/sass-loader/blob/45ad0be17264ceada5f0b4fb87e9357abe85c4ff/src/getSassOptions.js#L68-L70
outputStyle: 'expanded',
},
},
},
],
},
{
test: /\.less$/,
use: [
{
loader: require.resolve('less-loader'),
options: {
sourceMap: cssSourceMap,
javascriptEnabled: true,
...lessPathOptions,
},
},
],
},
{
test: /\.styl$/,
use: [
{
loader: require.resolve('stylus-loader'),
options: {
sourceMap: cssSourceMap,
paths: includePaths,
},
},
],
},
];
// load component css as raw strings
const rules = baseRules.map(({ test, use }) => ({
exclude: globalStylePaths,
test,
use: [
{ loader: require.resolve('raw-loader') },
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'embedded',
plugins: postcssPluginCreator,
sourceMap: cssSourceMap
// Never use component css sourcemap when style optimizations are on.
// It will just increase bundle size without offering good debug experience.
&& !buildOptions.optimization.styles
// Inline all sourcemap types except hidden ones, which are the same as no sourcemaps
// for component css.
&& !buildOptions.sourceMap.hidden ? 'inline' : false,
},
},
...use,
],
}));
// load global css as css files
if (globalStylePaths.length > 0) {
rules.push(...baseRules.map(({ test, use }) => {
return {
include: globalStylePaths,
test,
use: [
buildOptions.extractCss ? MiniCssExtractPlugin.loader : require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
url: false,
sourceMap: cssSourceMap,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: buildOptions.extractCss ? 'extracted' : 'embedded',
plugins: postcssPluginCreator,
sourceMap: cssSourceMap && !buildOptions.extractCss && !buildOptions.sourceMap.hidden
? 'inline'
: cssSourceMap,
},
},
...use,
],
};
}));
}
if (buildOptions.extractCss) {
extraPlugins.push(
// extract global css from js files into own css file
new MiniCssExtractPlugin({ filename: `[name]${hashFormat.extract}.css` }),
// suppress empty .js files in css only entry points
new webpack_1.SuppressExtractedTextChunksWebpackPlugin());
}
return {
entry: entryPoints,
module: { rules },
plugins: extraPlugins,
};
}
exports.getStylesConfig = getStylesConfig;
/**
* @license
* Copyright Google Inc. 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 * as webpack from 'webpack';
import { WebpackConfigOptions, WebpackTestOptions } from '../build-options';
export declare function getTestConfig(wco: WebpackConfigOptions<WebpackTestOptions>): webpack.Configuration;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const glob = require("glob");
const path = require("path");
const utils_1 = require("./utils");
function getTestConfig(wco) {
const { root, buildOptions, sourceRoot: include } = wco;
const extraRules = [];
const extraPlugins = [];
if (buildOptions.codeCoverage) {
const codeCoverageExclude = buildOptions.codeCoverageExclude;
const exclude = [
/\.(e2e|spec)\.tsx?$/,
/node_modules/,
];
if (codeCoverageExclude) {
codeCoverageExclude.forEach((excludeGlob) => {
const excludeFiles = glob
.sync(path.join(root, excludeGlob), { nodir: true })
.map(file => path.normalize(file));
exclude.push(...excludeFiles);
});
}
extraRules.push({
test: /\.(jsx?|tsx?)$/,
loader: require.resolve('@jsdevtools/coverage-istanbul-loader'),
options: { esModules: true },
enforce: 'post',
exclude,
include,
});
}
if (wco.buildOptions.sourceMap) {
const { styles, scripts } = wco.buildOptions.sourceMap;
if (styles || scripts) {
extraPlugins.push(utils_1.getSourceMapDevTool(scripts, styles, false, true));
}
}
return {
mode: 'development',
resolve: {
mainFields: [
...(wco.supportES2015 ? ['es2015'] : []),
'browser', 'module', 'main',
],
},
devtool: buildOptions.sourceMap ? false : 'eval',
entry: {
main: path.resolve(root, buildOptions.main),
},
module: {
rules: extraRules,
},
plugins: extraPlugins,
optimization: {
splitChunks: {
chunks: ((chunk) => !utils_1.isPolyfillsEntry(chunk.name)),
cacheGroups: {
vendors: false,
vendor: {
name: 'vendor',
chunks: 'initial',
test: (module, chunks) => {
const moduleName = module.nameForCondition ? module.nameForCondition() : '';
return /[\\/]node_modules[\\/]/.test(moduleName)
&& !chunks.some(({ name }) => utils_1.isPolyfillsEntry(name));
},
},
},
},
},
};
}
exports.getTestConfig = getTestConfig;
import { AngularCompilerPlugin } from '@ngtools/webpack';
import { WebpackConfigOptions } from '../build-options';
export declare function getNonAotConfig(wco: WebpackConfigOptions): {
module: {
rules: {
test: RegExp;
loader: string;
}[];
};
plugins: AngularCompilerPlugin[];
};
export declare function getAotConfig(wco: WebpackConfigOptions, i18nExtract?: boolean): {
module: {
rules: {
test: RegExp;
use: any[];
}[];
};
plugins: AngularCompilerPlugin[];
};
export declare function getTypescriptWorkerPlugin(wco: WebpackConfigOptions, workerTsConfigPath: string): AngularCompilerPlugin;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
const build_optimizer_1 = require("@angular-devkit/build-optimizer");
const path = require("path");
const webpack_1 = require("@ngtools/webpack");
function _pluginOptionsOverrides(buildOptions, pluginOptions) {
const compilerOptions = {
...(pluginOptions.compilerOptions || {})
};
const hostReplacementPaths = {};
if (buildOptions.fileReplacements) {
for (const replacement of buildOptions.fileReplacements) {
hostReplacementPaths[replacement.replace] = replacement.with;
}
}
if (buildOptions.preserveSymlinks) {
compilerOptions.preserveSymlinks = true;
}
return {
...pluginOptions,
hostReplacementPaths,
compilerOptions
};
}
function _createAotPlugin(wco, options, i18nExtract = false) {
const { root, buildOptions } = wco;
const i18nInFile = buildOptions.i18nFile
? path.resolve(root, buildOptions.i18nFile)
: undefined;
const i18nFileAndFormat = i18nExtract
? {
i18nOutFile: buildOptions.i18nFile,
i18nOutFormat: buildOptions.i18nFormat,
} : {
i18nInFile: i18nInFile,
i18nInFormat: buildOptions.i18nFormat,
};
const compilerOptions = options.compilerOptions || {};
if (i18nExtract) {
// Extraction of i18n is still using the legacy VE pipeline
compilerOptions.enableIvy = false;
}
const additionalLazyModules = {};
if (buildOptions.lazyModules) {
for (const lazyModule of buildOptions.lazyModules) {
additionalLazyModules[lazyModule] = path.resolve(root, lazyModule);
}
}
let pluginOptions = {
mainPath: path.join(root, buildOptions.main),
...i18nFileAndFormat,
locale: buildOptions.i18nLocale,
platform: buildOptions.platform === 'server' ? webpack_1.PLATFORM.Server : webpack_1.PLATFORM.Browser,
missingTranslation: buildOptions.i18nMissingTranslation,
sourceMap: buildOptions.sourceMap.scripts,
additionalLazyModules,
nameLazyFiles: buildOptions.namedChunks,
forkTypeChecker: buildOptions.forkTypeChecker,
contextElementDependencyConstructor: require('webpack/lib/dependencies/ContextElementDependency'),
logger: wco.logger,
directTemplateLoading: true,
...options,
compilerOptions,
};
pluginOptions = _pluginOptionsOverrides(buildOptions, pluginOptions);
return new webpack_1.AngularCompilerPlugin(pluginOptions);
}
function getNonAotConfig(wco) {
const { tsConfigPath } = wco;
return {
module: { rules: [{ test: /\.tsx?$/, loader: webpack_1.NgToolsLoader }] },
plugins: [_createAotPlugin(wco, { tsConfigPath, skipCodeGeneration: true })]
};
}
exports.getNonAotConfig = getNonAotConfig;
function getAotConfig(wco, i18nExtract = false) {
const { tsConfigPath, buildOptions } = wco;
const loaders = [webpack_1.NgToolsLoader];
if (buildOptions.buildOptimizer) {
loaders.unshift({
loader: build_optimizer_1.buildOptimizerLoaderPath,
options: { sourceMap: buildOptions.sourceMap.scripts }
});
}
const test = /(?:\.ngfactory\.js|\.ngstyle\.js|\.tsx?)$/;
const optimize = wco.buildOptions.optimization.scripts;
return {
module: { rules: [{ test, use: loaders }] },
plugins: [
_createAotPlugin(wco, { tsConfigPath, emitClassMetadata: !optimize, emitNgModuleScope: !optimize }, i18nExtract),
],
};
}
exports.getAotConfig = getAotConfig;
function getTypescriptWorkerPlugin(wco, workerTsConfigPath) {
const { buildOptions } = wco;
let pluginOptions = {
skipCodeGeneration: true,
tsConfigPath: workerTsConfigPath,
mainPath: undefined,
platform: webpack_1.PLATFORM.Browser,
sourceMap: buildOptions.sourceMap.scripts,
forkTypeChecker: buildOptions.forkTypeChecker,
contextElementDependencyConstructor: require('webpack/lib/dependencies/ContextElementDependency'),
logger: wco.logger,
// Run no transformers.
platformTransformers: [],
// Don't attempt lazy route discovery.
discoverLazyRoutes: false,
};
pluginOptions = _pluginOptionsOverrides(buildOptions, pluginOptions);
return new webpack_1.AngularCompilerPlugin(pluginOptions);
}
exports.getTypescriptWorkerPlugin = getTypescriptWorkerPlugin;
/**
* @license
* Copyright Google Inc. 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 { ExtraEntryPoint, ExtraEntryPointClass } from '../../../browser/schema';
import { SourceMapDevToolPlugin } from 'webpack';
import { ScriptTarget } from 'typescript';
export interface HashFormat {
chunk: string;
extract: string;
file: string;
script: string;
}
export declare function getOutputHashFormat(option: string, length?: number): HashFormat;
declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
export declare type NormalizedEntryPoint = Required<Omit<ExtraEntryPointClass, 'lazy'>>;
export declare function normalizeExtraEntryPoints(extraEntryPoints: ExtraEntryPoint[], defaultBundleName: string): NormalizedEntryPoint[];
export declare function getSourceMapDevTool(scriptsSourceMap: boolean | undefined, stylesSourceMap: boolean | undefined, hiddenSourceMap?: boolean, inlineSourceMap?: boolean): SourceMapDevToolPlugin;
/**
* Returns an ES version file suffix to differentiate between various builds.
*/
export declare function getEsVersionForFileName(scriptTargetOverride: ScriptTarget | undefined, esVersionInFileName?: boolean): string;
export declare function isPolyfillsEntry(name: string): boolean;
export {};
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@angular-devkit/core");
const webpack_1 = require("webpack");
const typescript_1 = require("typescript");
function getOutputHashFormat(option, length = 20) {
const hashFormats = {
none: { chunk: '', extract: '', file: '', script: '' },
media: { chunk: '', extract: '', file: `.[hash:${length}]`, script: '' },
bundles: {
chunk: `.[chunkhash:${length}]`,
extract: `.[contenthash:${length}]`,
file: '',
script: `.[hash:${length}]`,
},
all: {
chunk: `.[chunkhash:${length}]`,
extract: `.[contenthash:${length}]`,
file: `.[hash:${length}]`,
script: `.[hash:${length}]`,
},
};
return hashFormats[option] || hashFormats['none'];
}
exports.getOutputHashFormat = getOutputHashFormat;
function normalizeExtraEntryPoints(extraEntryPoints, defaultBundleName) {
return extraEntryPoints.map(entry => {
let normalizedEntry;
if (typeof entry === 'string') {
normalizedEntry = { input: entry, inject: true, bundleName: defaultBundleName };
}
else {
const { lazy, inject = true, ...newEntry } = entry;
const injectNormalized = entry.lazy !== undefined ? !entry.lazy : inject;
let bundleName;
if (entry.bundleName) {
bundleName = entry.bundleName;
}
else if (!injectNormalized) {
// Lazy entry points use the file name as bundle name.
bundleName = core_1.basename(core_1.normalize(entry.input.replace(/\.(js|css|scss|sass|less|styl)$/i, '')));
}
else {
bundleName = defaultBundleName;
}
normalizedEntry = { ...newEntry, inject: injectNormalized, bundleName };
}
return normalizedEntry;
});
}
exports.normalizeExtraEntryPoints = normalizeExtraEntryPoints;
function getSourceMapDevTool(scriptsSourceMap, stylesSourceMap, hiddenSourceMap = false, inlineSourceMap = false) {
const include = [];
if (scriptsSourceMap) {
include.push(/js$/);
}
if (stylesSourceMap) {
include.push(/css$/);
}
return new webpack_1.SourceMapDevToolPlugin({
filename: inlineSourceMap ? undefined : '[file].map',
include,
// We want to set sourceRoot to `webpack:///` for non
// inline sourcemaps as otherwise paths to sourcemaps will be broken in browser
// `webpack:///` is needed for Visual Studio breakpoints to work properly as currently
// there is no way to set the 'webRoot'
sourceRoot: inlineSourceMap ? '' : 'webpack:///',
moduleFilenameTemplate: '[resource-path]',
append: hiddenSourceMap ? false : undefined,
});
}
exports.getSourceMapDevTool = getSourceMapDevTool;
/**
* Returns an ES version file suffix to differentiate between various builds.
*/
function getEsVersionForFileName(scriptTargetOverride, esVersionInFileName = false) {
if (!esVersionInFileName || scriptTargetOverride === undefined) {
return '';
}
if (scriptTargetOverride === typescript_1.ScriptTarget.ESNext) {
return '-esnext';
}
return '-' + typescript_1.ScriptTarget[scriptTargetOverride].toLowerCase();
}
exports.getEsVersionForFileName = getEsVersionForFileName;
function isPolyfillsEntry(name) {
return name === 'polyfills' || name === 'polyfills-es5';
}
exports.isPolyfillsEntry = isPolyfillsEntry;
import { Configuration } from 'webpack';
import { WebpackConfigOptions } from '../build-options';
export declare function getWorkerConfig(wco: WebpackConfigOptions): Configuration;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const path_1 = require("path");
const typescript_1 = require("./typescript");
const WorkerPlugin = require('worker-plugin');
function getWorkerConfig(wco) {
const { buildOptions } = wco;
if (!buildOptions.webWorkerTsConfig) {
return {};
}
if (typeof buildOptions.webWorkerTsConfig != 'string') {
throw new Error('The `webWorkerTsConfig` must be a string.');
}
const workerTsConfigPath = path_1.resolve(wco.root, buildOptions.webWorkerTsConfig);
return {
plugins: [new WorkerPlugin({
globalObject: false,
plugins: [typescript_1.getTypescriptWorkerPlugin(wco, workerTsConfigPath)],
})],
};
}
exports.getWorkerConfig = getWorkerConfig;
/**
* @license
* Copyright Google Inc. 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 { Compiler, Plugin } from 'webpack';
import { Budget } from '../../../src/browser/schema';
/**
* Check budget sizes for component styles by emitting a warning or error if a
* budget is exceeded by a particular component's styles.
*/
export declare class AnyComponentStyleBudgetChecker implements Plugin {
private readonly budgets;
constructor(budgets: Budget[]);
apply(compiler: Compiler): void;
}
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const schema_1 = require("../../../src/browser/schema");
const bundle_calculator_1 = require("../utilities/bundle-calculator");
const PLUGIN_NAME = 'AnyComponentStyleBudgetChecker';
/**
* Check budget sizes for component styles by emitting a warning or error if a
* budget is exceeded by a particular component's styles.
*/
class AnyComponentStyleBudgetChecker {
constructor(budgets) {
this.budgets = budgets.filter((budget) => budget.type === schema_1.Type.AnyComponentStyle);
}
apply(compiler) {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
compilation.hooks.afterOptimizeChunkAssets.tap(PLUGIN_NAME, () => {
// In AOT compilations component styles get processed in child compilations.
// tslint:disable-next-line: no-any
const parentCompilation = compilation.compiler.parentCompilation;
if (!parentCompilation) {
return;
}
const cssExtensions = [
'.css',
'.scss',
'.less',
'.styl',
'.sass',
];
const componentStyles = Object.keys(compilation.assets)
.filter((name) => cssExtensions.includes(path.extname(name)))
.map((name) => ({
size: compilation.assets[name].size(),
label: name,
}));
const thresholds = flatMap(this.budgets, (budget) => bundle_calculator_1.calculateThresholds(budget));
for (const { size, label } of componentStyles) {
for (const { severity, message } of bundle_calculator_1.checkThresholds(thresholds[Symbol.iterator](), size, label)) {
switch (severity) {
case bundle_calculator_1.ThresholdSeverity.Warning:
compilation.warnings.push(message);
break;
case bundle_calculator_1.ThresholdSeverity.Error:
compilation.errors.push(message);
break;
default:
assertNever(severity);
break;
}
}
}
});
});
}
}
exports.AnyComponentStyleBudgetChecker = AnyComponentStyleBudgetChecker;
function assertNever(input) {
throw new Error(`Unexpected call to assertNever() with input: ${JSON.stringify(input, null /* replacer */, 4 /* tabSize */)}`);
}
function flatMap(list, mapper) {
return [].concat(...list.map(mapper).map((iterator) => Array.from(iterator)));
}
/**
* @license
* Copyright Google Inc. 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 { Compiler } from 'webpack';
import { Budget } from '../../browser/schema';
export interface BundleBudgetPluginOptions {
budgets: Budget[];
}
export declare class BundleBudgetPlugin {
private options;
constructor(options: BundleBudgetPluginOptions);
apply(compiler: Compiler): void;
private runChecks;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const bundle_calculator_1 = require("../utilities/bundle-calculator");
class BundleBudgetPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
const { budgets } = this.options;
if (!budgets || budgets.length === 0) {
return;
}
compiler.hooks.afterEmit.tap('BundleBudgetPlugin', (compilation) => {
this.runChecks(budgets, compilation);
});
}
runChecks(budgets, compilation) {
// No process bundle results because this plugin is only used when differential
// builds are disabled.
const processResults = [];
const stats = compilation.getStats().toJson();
for (const { severity, message } of bundle_calculator_1.checkBudgets(budgets, stats, processResults)) {
switch (severity) {
case bundle_calculator_1.ThresholdSeverity.Warning:
compilation.warnings.push(`budgets: ${message}`);
break;
case bundle_calculator_1.ThresholdSeverity.Error:
compilation.errors.push(`budgets: ${message}`);
break;
}
}
}
}
exports.BundleBudgetPlugin = BundleBudgetPlugin;
import { Compiler } from 'webpack';
import { CrossOriginValue } from '../utilities/index-file/augment-index-html';
import { IndexHtmlTransform } from '../utilities/index-file/write-index-html';
export interface IndexHtmlWebpackPluginOptions {
input: string;
output: string;
baseHref?: string;
entrypoints: string[];
deployUrl?: string;
sri: boolean;
noModuleEntrypoints: string[];
moduleEntrypoints: string[];
postTransform?: IndexHtmlTransform;
crossOrigin?: CrossOriginValue;
lang?: string;
}
export declare class IndexHtmlWebpackPlugin {
private _options;
constructor(options?: Partial<IndexHtmlWebpackPluginOptions>);
apply(compiler: Compiler): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const path = require("path");
const webpack_sources_1 = require("webpack-sources");
const augment_index_html_1 = require("../utilities/index-file/augment-index-html");
const strip_bom_1 = require("../utilities/strip-bom");
function readFile(filename, compilation) {
return new Promise((resolve, reject) => {
compilation.inputFileSystem.readFile(filename, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(strip_bom_1.stripBom(data.toString()));
});
});
}
class IndexHtmlWebpackPlugin {
constructor(options) {
this._options = {
input: 'index.html',
output: 'index.html',
entrypoints: ['polyfills', 'main'],
noModuleEntrypoints: [],
moduleEntrypoints: [],
sri: false,
...options,
};
}
apply(compiler) {
compiler.hooks.emit.tapPromise('index-html-webpack-plugin', async (compilation) => {
// Get input html file
const inputContent = await readFile(this._options.input, compilation);
compilation.fileDependencies.add(this._options.input);
// Get all files for selected entrypoints
const files = [];
const noModuleFiles = [];
const moduleFiles = [];
for (const [entryName, entrypoint] of compilation.entrypoints) {
const entryFiles = ((entrypoint && entrypoint.getFiles()) || []).map((f) => ({
name: entryName,
file: f,
extension: path.extname(f),
}));
if (this._options.noModuleEntrypoints.includes(entryName)) {
noModuleFiles.push(...entryFiles);
}
else if (this._options.moduleEntrypoints.includes(entryName)) {
moduleFiles.push(...entryFiles);
}
else {
files.push(...entryFiles);
}
}
const loadOutputFile = (name) => compilation.assets[name].source();
let indexSource = await augment_index_html_1.augmentIndexHtml({
input: this._options.input,
inputContent,
baseHref: this._options.baseHref,
deployUrl: this._options.deployUrl,
sri: this._options.sri,
crossOrigin: this._options.crossOrigin,
files,
noModuleFiles,
loadOutputFile,
moduleFiles,
entrypoints: this._options.entrypoints,
lang: this._options.lang,
});
if (this._options.postTransform) {
indexSource = await this._options.postTransform(indexSource);
}
// Add to compilation assets
compilation.assets[this._options.output] = new webpack_sources_1.RawSource(indexSource);
});
}
}
exports.IndexHtmlWebpackPlugin = IndexHtmlWebpackPlugin;
<!DOCTYPE html>
<!--
This is the execution context.
Loaded within the iframe.
Reloaded before every execution run.
-->
<html>
<head>
<title></title>
<base href="/">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head>
<body>
<!-- The scripts need to be in the body DOM element, as some test running frameworks need the body
to have already been created so they can insert their magic into it. For example, if loaded
before body, Angular Scenario test framework fails to find the body and crashes and burns in
an epic manner. -->
<script src="context.js"></script>
<script type="text/javascript">
// Configure our Karma and set up bindings
%CLIENT_CONFIG%
window.__karma__.setupContext(window);
// All served files with the latest timestamps
%MAPPINGS%
</script>
<script src="_karma_webpack_/runtime.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/polyfills-es5.js" crossorigin="anonymous" nomodule></script>
<script src="_karma_webpack_/polyfills.js" crossorigin="anonymous"></script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<script src="_karma_webpack_/styles.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/scripts.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/vendor.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/main.js" crossorigin="anonymous"></script>
<script type="text/javascript">
window.__karma__.loaded();
</script>
</body>
</html>
<!doctype html>
<!--
This file is almost the same as context.html - loads all source files,
but its purpose is to be loaded in the main frame (not within an iframe),
just for immediate execution, without reporting to Karma server.
-->
<html>
<head>
%X_UA_COMPATIBLE%
<title>Karma DEBUG RUNNER</title>
<link href="favicon.ico" rel="icon" type="image/x-icon" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
</head>
<body>
<!-- The scripts need to be at the end of body, so that some test running frameworks
(Angular Scenario, for example) need the body to be loaded so that it can insert its magic
into it. If it is before body, then it fails to find the body and crashes and burns in an epic
manner. -->
<script src="context.js"></script>
<script src="debug.js"></script>
<script type="text/javascript">
// Configure our Karma
%CLIENT_CONFIG%
// All served files with the latest timestamps
%MAPPINGS%
</script>
<script src="_karma_webpack_/runtime.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/polyfills-es5.js" crossorigin="anonymous" nomodule></script>
<script src="_karma_webpack_/polyfills.js" crossorigin="anonymous"></script>
<!-- Dynamically replaced with <script> tags -->
%SCRIPTS%
<script src="_karma_webpack_/styles.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/scripts.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/vendor.js" crossorigin="anonymous"></script>
<script src="_karma_webpack_/main.js" crossorigin="anonymous"></script>
<script type="text/javascript">
window.__karma__.loaded();
</script>
</body>
</html>
/**
* @license
* Copyright Google Inc. 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
*/
export declare class KarmaWebpackFailureCb {
private callback;
constructor(callback: (error: string | undefined, errors: string[]) => void);
apply(compiler: any): void;
}
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
// Force Webpack to throw compilation errors. Useful with karma-webpack when in single-run mode.
// Workaround for https://github.com/webpack-contrib/karma-webpack/issues/66
class KarmaWebpackFailureCb {
constructor(callback) {
this.callback = callback;
}
apply(compiler) {
compiler.hooks.done.tap('KarmaWebpackFailureCb', (stats) => {
if (stats.compilation.errors.length > 0) {
this.callback(undefined, stats.compilation.errors.map((error) => error.message ? error.message : error.toString()));
}
});
}
}
exports.KarmaWebpackFailureCb = KarmaWebpackFailureCb;
/**
* @license
* Copyright Google Inc. 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
*/
export {};
/**
* @license
* Copyright Google Inc. 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 { Compiler } from 'webpack';
export declare class NamedLazyChunksPlugin {
constructor();
apply(compiler: Compiler): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// Webpack doesn't export these so the deep imports can potentially break.
// There doesn't seem to exist any ergonomic way to alter chunk names for non-context lazy chunks
// (https://github.com/webpack/webpack/issues/9075) so this is the best alternative for now.
const ImportDependency = require('webpack/lib/dependencies/ImportDependency');
const ImportDependenciesBlock = require('webpack/lib/dependencies/ImportDependenciesBlock');
const Template = require('webpack/lib/Template');
class NamedLazyChunksPlugin {
constructor() { }
apply(compiler) {
compiler.hooks.compilation.tap('named-lazy-chunks-plugin', compilation => {
// The dependencyReference hook isn't in the webpack typings so we have to type it as any.
// tslint:disable-next-line: no-any
compilation.hooks.dependencyReference.tap('named-lazy-chunks-plugin',
// tslint:disable-next-line: no-any
(_, dependency) => {
if (
// Check this dependency is from an `import()` statement.
dependency instanceof ImportDependency
&& dependency.block instanceof ImportDependenciesBlock
// Don't rename chunks that already have a name.
&& dependency.block.chunkName === null) {
// Convert the request to a valid chunk name using the same logic used
// in webpack/lib/ContextModule.js
dependency.block.chunkName = Template.toPath(dependency.request);
}
});
});
}
}
exports.NamedLazyChunksPlugin = NamedLazyChunksPlugin;
import { Compiler } from 'webpack';
export interface OptimizeCssWebpackPluginOptions {
sourceMap: boolean;
test: (file: string) => boolean;
}
export declare class OptimizeCssWebpackPlugin {
private readonly _options;
constructor(options: Partial<OptimizeCssWebpackPluginOptions>);
apply(compiler: Compiler): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const cssNano = require("cssnano");
const webpack_sources_1 = require("webpack-sources");
function hook(compiler, action) {
compiler.hooks.compilation.tap('optimize-css-webpack-plugin', (compilation) => {
compilation.hooks.optimizeChunkAssets.tapPromise('optimize-css-webpack-plugin', chunks => action(compilation, chunks));
});
}
class OptimizeCssWebpackPlugin {
constructor(options) {
this._options = {
sourceMap: false,
test: file => file.endsWith('.css'),
...options,
};
}
apply(compiler) {
hook(compiler, (compilation, chunks) => {
const files = [...compilation.additionalChunkAssets];
chunks.forEach(chunk => {
if (chunk.files && chunk.files.length > 0) {
files.push(...chunk.files);
}
});
const actions = files
.filter(file => this._options.test(file))
.map(async (file) => {
const asset = compilation.assets[file];
if (!asset) {
return;
}
let content;
// tslint:disable-next-line: no-any
let map;
if (this._options.sourceMap && asset.sourceAndMap) {
const sourceAndMap = asset.sourceAndMap();
content = sourceAndMap.source;
map = sourceAndMap.map;
}
else {
content = asset.source();
}
if (content.length === 0) {
return;
}
const cssNanoOptions = {
preset: ['default', {
// Disable SVG optimization, as this can cause optimizations which are not compatible in all browsers.
svgo: false,
}],
};
const postCssOptions = {
from: file,
map: map && { annotation: false, prev: map },
};
const output = await new Promise((resolve, reject) => {
// the last parameter is not in the typings
// tslint:disable-next-line: no-any
cssNano.process(content, postCssOptions, cssNanoOptions)
.then(resolve)
.catch(reject);
});
const warnings = output.warnings();
if (warnings.length) {
compilation.warnings.push(...warnings.map(({ text }) => text));
}
let newSource;
if (output.map) {
newSource = new webpack_sources_1.SourceMapSource(output.css, file,
// tslint:disable-next-line: no-any
output.map.toString(), content, map);
}
else {
newSource = new webpack_sources_1.RawSource(output.css);
}
compilation.assets[file] = newSource;
});
return Promise.all(actions);
});
}
}
exports.OptimizeCssWebpackPlugin = OptimizeCssWebpackPlugin;
import * as postcss from 'postcss';
import * as webpack from 'webpack';
export interface PostcssCliResourcesOptions {
baseHref?: string;
deployUrl?: string;
resourcesOutputPath?: string;
rebaseRootRelative?: boolean;
filename: string;
loader: webpack.loader.LoaderContext;
emitFile: boolean;
}
declare const _default: postcss.Plugin<PostcssCliResourcesOptions>;
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const loader_utils_1 = require("loader-utils");
const path = require("path");
const postcss = require("postcss");
const url = require("url");
function wrapUrl(url) {
let wrappedUrl;
const hasSingleQuotes = url.indexOf('\'') >= 0;
if (hasSingleQuotes) {
wrappedUrl = `"${url}"`;
}
else {
wrappedUrl = `'${url}'`;
}
return `url(${wrappedUrl})`;
}
async function resolve(file, base, resolver) {
try {
return await resolver('./' + file, base);
}
catch (_a) {
return resolver(file, base);
}
}
exports.default = postcss.plugin('postcss-cli-resources', (options) => {
const { deployUrl = '', baseHref = '', resourcesOutputPath = '', rebaseRootRelative = false, filename, loader, emitFile, } = options;
const dedupeSlashes = (url) => url.replace(/\/\/+/g, '/');
const process = async (inputUrl, context, resourceCache) => {
// If root-relative, absolute or protocol relative url, leave as is
if (/^((?:\w+:)?\/\/|data:|chrome:|#)/.test(inputUrl)) {
return inputUrl;
}
if (!rebaseRootRelative && /^\//.test(inputUrl)) {
return inputUrl;
}
// If starts with a caret, remove and return remainder
// this supports bypassing asset processing
if (inputUrl.startsWith('^')) {
return inputUrl.substr(1);
}
const cacheKey = path.resolve(context, inputUrl);
const cachedUrl = resourceCache.get(cacheKey);
if (cachedUrl) {
return cachedUrl;
}
if (inputUrl.startsWith('~')) {
inputUrl = inputUrl.substr(1);
}
if (inputUrl.startsWith('/')) {
let outputUrl = '';
if (deployUrl.match(/:\/\//) || deployUrl.startsWith('/')) {
// If deployUrl is absolute or root relative, ignore baseHref & use deployUrl as is.
outputUrl = `${deployUrl.replace(/\/$/, '')}${inputUrl}`;
}
else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
outputUrl = baseHref.replace(/\/$/, '') + dedupeSlashes(`/${deployUrl}/${inputUrl}`);
}
else {
// Join together base-href, deploy-url and the original URL.
outputUrl = dedupeSlashes(`/${baseHref}/${deployUrl}/${inputUrl}`);
}
resourceCache.set(cacheKey, outputUrl);
return outputUrl;
}
const { pathname, hash, search } = url.parse(inputUrl.replace(/\\/g, '/'));
const resolver = (file, base) => new Promise((resolve, reject) => {
loader.resolve(base, decodeURI(file), (err, result) => {
if (err) {
reject(err);
return;
}
resolve(result);
});
});
const result = await resolve(pathname, context, resolver);
return new Promise((resolve, reject) => {
loader.fs.readFile(result, (err, content) => {
if (err) {
reject(err);
return;
}
let outputPath = loader_utils_1.interpolateName({ resourcePath: result }, filename, { content });
if (resourcesOutputPath) {
outputPath = path.posix.join(resourcesOutputPath, outputPath);
}
loader.addDependency(result);
if (emitFile) {
loader.emitFile(outputPath, content, undefined);
}
let outputUrl = outputPath.replace(/\\/g, '/');
if (hash || search) {
outputUrl = url.format({ pathname: outputUrl, hash, search });
}
if (deployUrl && loader.loaders[loader.loaderIndex].options.ident !== 'extracted') {
outputUrl = url.resolve(deployUrl, outputUrl);
}
resourceCache.set(cacheKey, outputUrl);
resolve(outputUrl);
});
});
};
return (root) => {
const urlDeclarations = [];
root.walkDecls(decl => {
if (decl.value && decl.value.includes('url')) {
urlDeclarations.push(decl);
}
});
if (urlDeclarations.length === 0) {
return;
}
const resourceCache = new Map();
return Promise.all(urlDeclarations.map(async (decl) => {
const value = decl.value;
const urlRegex = /url\(\s*(?:"([^"]+)"|'([^']+)'|(.+?))\s*\)/g;
const segments = [];
let match;
let lastIndex = 0;
let modified = false;
// We want to load it relative to the file that imports
const inputFile = decl.source && decl.source.input.file;
const context = inputFile && path.dirname(inputFile) || loader.context;
// tslint:disable-next-line:no-conditional-assignment
while (match = urlRegex.exec(value)) {
const originalUrl = match[1] || match[2] || match[3];
let processedUrl;
try {
processedUrl = await process(originalUrl, context, resourceCache);
}
catch (err) {
loader.emitError(decl.error(err.message, { word: originalUrl }).toString());
continue;
}
if (lastIndex < match.index) {
segments.push(value.slice(lastIndex, match.index));
}
if (!processedUrl || originalUrl === processedUrl) {
segments.push(match[0]);
}
else {
segments.push(wrapUrl(processedUrl));
modified = true;
}
lastIndex = match.index + match[0].length;
}
if (lastIndex < value.length) {
segments.push(value.slice(lastIndex));
}
if (modified) {
decl.value = segments.join('');
}
}));
};
});
/**
* @license
* Copyright Google Inc. 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 { Compiler } from 'webpack';
import { HashFormat } from '../models/webpack-configs/utils';
export interface RemoveHashPluginOptions {
chunkNames: string[];
hashFormat: HashFormat;
}
export declare class RemoveHashPlugin {
private options;
constructor(options: RemoveHashPluginOptions);
apply(compiler: Compiler): void;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class RemoveHashPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.compilation.tap('remove-hash-plugin', compilation => {
const mainTemplate = compilation.mainTemplate;
mainTemplate.hooks.assetPath.tap('remove-hash-plugin', (path, data) => {
const chunkName = data.chunk && data.chunk.name;
const { chunkNames, hashFormat } = this.options;
if (chunkName && chunkNames.includes(chunkName)) {
// Replace hash formats with empty strings.
return path
.replace(hashFormat.chunk, '')
.replace(hashFormat.extract, '');
}
return path;
});
});
}
}
exports.RemoveHashPlugin = RemoveHashPlugin;
/**
* @license
* Copyright Google Inc. 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
*/
/**
* @license
* Copyright Google Inc. 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 { Compiler } from 'webpack';
export interface ScriptsWebpackPluginOptions {
name: string;
sourceMap: boolean;
scripts: string[];
filename: string;
basePath: string;
}
export declare class ScriptsWebpackPlugin {
private options;
private _lastBuildTime?;
private _cachedOutput?;
constructor(options?: Partial<ScriptsWebpackPluginOptions>);
shouldSkip(compilation: any, scripts: string[]): boolean;
private _insertOutput;
apply(compiler: Compiler): void;
}
"use strict";
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
const webpack_sources_1 = require("webpack-sources");
const loader_utils_1 = require("loader-utils");
const path = require("path");
const Chunk = require('webpack/lib/Chunk');
const EntryPoint = require('webpack/lib/Entrypoint');
function addDependencies(compilation, scripts) {
for (const script of scripts) {
compilation.fileDependencies.add(script);
}
}
function hook(compiler, action) {
compiler.hooks.thisCompilation.tap('scripts-webpack-plugin', (compilation) => {
compilation.hooks.additionalAssets.tapAsync('scripts-webpack-plugin', (callback) => action(compilation, callback));
});
}
class ScriptsWebpackPlugin {
constructor(options = {}) {
this.options = options;
}
shouldSkip(compilation, scripts) {
if (this._lastBuildTime == undefined) {
this._lastBuildTime = Date.now();
return false;
}
for (let i = 0; i < scripts.length; i++) {
const scriptTime = compilation.fileTimestamps.get(scripts[i]);
if (!scriptTime || scriptTime > this._lastBuildTime) {
this._lastBuildTime = Date.now();
return false;
}
}
return true;
}
_insertOutput(compilation, { filename, source }, cached = false) {
const chunk = new Chunk(this.options.name);
chunk.rendered = !cached;
chunk.id = this.options.name;
chunk.ids = [chunk.id];
chunk.files.push(filename);
const entrypoint = new EntryPoint(this.options.name);
entrypoint.pushChunk(chunk);
chunk.addGroup(entrypoint);
compilation.entrypoints.set(this.options.name, entrypoint);
compilation.chunks.push(chunk);
compilation.assets[filename] = source;
}
apply(compiler) {
if (!this.options.scripts || this.options.scripts.length === 0) {
return;
}
const scripts = this.options.scripts
.filter(script => !!script)
.map(script => path.resolve(this.options.basePath || '', script));
hook(compiler, (compilation, callback) => {
if (this.shouldSkip(compilation, scripts)) {
if (this._cachedOutput) {
this._insertOutput(compilation, this._cachedOutput, true);
}
addDependencies(compilation, scripts);
callback();
return;
}
const sourceGetters = scripts.map(fullPath => {
return new Promise((resolve, reject) => {
compilation.inputFileSystem.readFile(fullPath, (err, data) => {
if (err) {
reject(err);
return;
}
const content = data.toString();
let source;
if (this.options.sourceMap) {
// TODO: Look for source map file (for '.min' scripts, etc.)
let adjustedPath = fullPath;
if (this.options.basePath) {
adjustedPath = path.relative(this.options.basePath, fullPath);
}
source = new webpack_sources_1.OriginalSource(content, adjustedPath);
}
else {
source = new webpack_sources_1.RawSource(content);
}
resolve(source);
});
});
});
Promise.all(sourceGetters)
.then(sources => {
const concatSource = new webpack_sources_1.ConcatSource();
sources.forEach(source => {
concatSource.add(source);
concatSource.add('\n;');
});
const combinedSource = new webpack_sources_1.CachedSource(concatSource);
const filename = loader_utils_1.interpolateName({ resourcePath: 'scripts.js' }, this.options.filename, { content: combinedSource.source() });
const output = { filename, source: combinedSource };
this._insertOutput(compilation, output);
this._cachedOutput = output;
addDependencies(compilation, scripts);
callback();
})
.catch((err) => callback(err));
});
}
}
exports.ScriptsWebpackPlugin = ScriptsWebpackPlugin;
/**
* @license
* Copyright Google Inc. 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 { logging } from '@angular-devkit/core';
import { loader } from 'webpack';
export interface SingleTestTransformLoaderOptions {
files: string[];
logger: logging.Logger;
}
export declare const SingleTestTransformLoader: string;
/**
* This loader transforms the default test file to only run tests
* for some specs instead of all specs.
* It works by replacing the known content of the auto-generated test file:
* const context = require.context('./', true, /\.spec\.ts$/);
* context.keys().map(context);
* with:
* const context = { keys: () => ({ map: (_a) => { } }) };
* context.keys().map(context);
* So that it does nothing.
* Then it adds import statements for each file in the files options
* array to import them directly, and thus run the tests there.
*/
export default function loader(this: loader.LoaderContext, source: string): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const loader_utils_1 = require("loader-utils");
const path_1 = require("path");
exports.SingleTestTransformLoader = require.resolve(path_1.join(__dirname, 'single-test-transform'));
/**
* This loader transforms the default test file to only run tests
* for some specs instead of all specs.
* It works by replacing the known content of the auto-generated test file:
* const context = require.context('./', true, /\.spec\.ts$/);
* context.keys().map(context);
* with:
* const context = { keys: () => ({ map: (_a) => { } }) };
* context.keys().map(context);
* So that it does nothing.
* Then it adds import statements for each file in the files options
* array to import them directly, and thus run the tests there.
*/
function loader(source) {
const options = loader_utils_1.getOptions(this);
const lineSeparator = process.platform === 'win32' ? '\r\n' : '\n';
const targettedImports = options.files
.map(path => `require('./${path.replace('.' + path_1.extname(path), '')}');`)
.join(lineSeparator);
// TODO: maybe a documented 'marker/comment' inside test.ts would be nicer?
const regex = /require\.context\(.*/;
// signal the user that expected content is not present
if (!regex.test(source)) {
const message = [
`The 'include' option requires that the 'main' file for tests include the line below:`,
`const context = require.context('./', true, /\.spec\.ts$/);`,
`Arguments passed to require.context are not strict and can be changed`,
];
options.logger.error(message.join(lineSeparator));
}
const mockedRequireContext = 'Object.assign(() => { }, { keys: () => [], resolve: () => undefined });' + lineSeparator;
source = source.replace(regex, mockedRequireContext + targettedImports);
return source;
}
exports.default = loader;
/**
* @license
* Copyright Google Inc. 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
*/
export declare class SuppressExtractedTextChunksWebpackPlugin {
constructor();
apply(compiler: any): void;
}
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
// Remove .js files from entry points consisting entirely of .css|scss|sass|less|styl.
// To be used together with ExtractTextPlugin.
class SuppressExtractedTextChunksWebpackPlugin {
constructor() { }
apply(compiler) {
compiler.hooks.compilation.tap('SuppressExtractedTextChunks', (compilation) => {
// find which chunks have css only entry points
const cssOnlyChunks = [];
const entryPoints = compilation.options.entry;
// determine which entry points are composed entirely of css files
for (let entryPoint of Object.keys(entryPoints)) {
let entryFiles = entryPoints[entryPoint];
// when type of entryFiles is not array, make it as an array
entryFiles = entryFiles instanceof Array ? entryFiles : [entryFiles];
if (entryFiles.every((el) => el.match(/\.(css|scss|sass|less|styl)$/) !== null)) {
cssOnlyChunks.push(entryPoint);
}
}
// Remove the js file for supressed chunks
compilation.hooks.afterSeal.tap('SuppressExtractedTextChunks', () => {
compilation.chunks
.filter((chunk) => cssOnlyChunks.indexOf(chunk.name) !== -1)
.forEach((chunk) => {
let newFiles = [];
chunk.files.forEach((file) => {
if (file.match(/\.js(\.map)?$/)) {
// remove js files
delete compilation.assets[file];
}
else {
newFiles.push(file);
}
});
chunk.files = newFiles;
});
});
// Remove scripts tags with a css file as source, because HtmlWebpackPlugin will use
// a css file as a script for chunks without js files.
// TODO: Enable this once HtmlWebpackPlugin supports Webpack 4
// compilation.plugin('html-webpack-plugin-alter-asset-tags',
// (htmlPluginData: any, callback: any) => {
// const filterFn = (tag: any) =>
// !(tag.tagName === 'script' && tag.attributes.src.match(/\.css$/));
// htmlPluginData.head = htmlPluginData.head.filter(filterFn);
// htmlPluginData.body = htmlPluginData.body.filter(filterFn);
// callback(null, htmlPluginData);
// });
});
}
}
exports.SuppressExtractedTextChunksWebpackPlugin = SuppressExtractedTextChunksWebpackPlugin;
/**
* @license
* Copyright Google Inc. 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 { RawSourceMap } from 'source-map';
import webpack = require('webpack');
export default function webpackRollupLoader(this: webpack.loader.LoaderContext, source: string, sourceMap: RawSourceMap): void;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
const rollup_1 = require("rollup");
function splitRequest(request) {
const inx = request.lastIndexOf('!');
if (inx === -1) {
return {
loaders: '',
resource: request,
};
}
else {
return {
loaders: request.slice(0, inx + 1),
resource: request.slice(inx + 1),
};
}
}
// Load resolve paths using Webpack.
function webpackResolutionPlugin(loaderContext, entryId, entryIdCodeAndMap) {
return {
name: 'webpack-resolution-plugin',
resolveId: (id, importerId) => {
if (id === entryId) {
return entryId;
}
else {
return new Promise((resolve, reject) => {
// split apart resource paths because Webpack's this.resolve() can't handle `loader!`
// prefixes
const parts = splitRequest(id);
const importerParts = splitRequest(importerId);
// resolve the full path of the imported file with Webpack's module loader
// this will figure out node_modules imports, Webpack aliases, etc.
loaderContext.resolve(path_1.dirname(importerParts.resource), parts.resource, (err, fullPath) => err ? reject(err) : resolve(parts.loaders + fullPath));
});
}
},
load: (id) => {
if (id === entryId) {
return entryIdCodeAndMap;
}
return new Promise((resolve, reject) => {
// load the module with Webpack
// this will apply all relevant loaders, etc.
loaderContext.loadModule(id, (err, source, map) => err ? reject(err) : resolve({ code: source, map: map }));
});
},
};
}
function webpackRollupLoader(source, sourceMap) {
// Note: this loader isn't cacheable because it will add the lazy chunks to the
// virtual file system on completion.
const callback = this.async();
if (!callback) {
throw new Error('Async loader support is required.');
}
const options = this.query || {};
const entryId = this.resourcePath;
const sourcemap = this.sourceMap;
// Get the VirtualFileSystemDecorator that AngularCompilerPlugin added so we can write to it.
// Since we use webpackRollupLoader as a post loader, this should be there.
// TODO: we should be able to do this in a more elegant way by again decorating webpacks
// input file system inside a custom WebpackRollupPlugin, modelled after AngularCompilerPlugin.
const vfs = this._compiler.inputFileSystem;
const virtualWrite = (path, data) => vfs.getWebpackCompilerHost().writeFile(path, data, false);
// Bundle with Rollup
const rollupOptions = {
...options,
input: entryId,
plugins: [
...(options.plugins || []),
webpackResolutionPlugin(this, entryId, { code: source, map: sourceMap }),
],
};
rollup_1.rollup(rollupOptions)
.then(build => build.generate({ format: 'es', sourcemap }))
.then((result) => {
const [mainChunk, ...otherChunksOrAssets] = result.output;
// Write other chunks and assets to the virtual file system so that webpack can load them.
const resultDir = path_1.dirname(entryId);
otherChunksOrAssets.forEach(chunkOrAsset => {
const { fileName, type } = chunkOrAsset;
if (type == 'chunk') {
const { code, map } = chunkOrAsset;
virtualWrite(path_1.join(resultDir, fileName), code);
if (map) {
// Also write the map if there's one.
// Probably need scriptsSourceMap set on CLI to load it.
virtualWrite(path_1.join(resultDir, `${fileName}.map`), map.toString());
}
}
else if (type == 'asset') {
const { source } = chunkOrAsset;
// Source might be a Buffer. Just assuming it's a string for now.
virtualWrite(path_1.join(resultDir, fileName), source);
}
});
// Always return the main chunk from webpackRollupLoader.
// Cast to any here is needed because of a typings incompatibility between source-map versions.
// tslint:disable-next-line:no-any
callback(null, mainChunk.code, mainChunk.map);
}, (err) => callback(err));
}
exports.default = webpackRollupLoader;
/**
* @license
* Copyright Google Inc. 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
*/
export { AnyComponentStyleBudgetChecker } from './any-component-style-budget-checker';
export { OptimizeCssWebpackPlugin, OptimizeCssWebpackPluginOptions } from './optimize-css-webpack-plugin';
export { BundleBudgetPlugin, BundleBudgetPluginOptions } from './bundle-budget';
export { ScriptsWebpackPlugin, ScriptsWebpackPluginOptions } from './scripts-webpack-plugin';
export { SuppressExtractedTextChunksWebpackPlugin } from './suppress-entry-chunks-webpack-plugin';
export { RemoveHashPlugin, RemoveHashPluginOptions } from './remove-hash-plugin';
export { NamedLazyChunksPlugin as NamedChunksPlugin } from './named-chunks-plugin';
export { default as PostcssCliResources, PostcssCliResourcesOptions, } from './postcss-cli-resources';
export declare const WebpackRollupLoader: string;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
// Exports the webpack plugins we use internally.
var any_component_style_budget_checker_1 = require("./any-component-style-budget-checker");
exports.AnyComponentStyleBudgetChecker = any_component_style_budget_checker_1.AnyComponentStyleBudgetChecker;
var optimize_css_webpack_plugin_1 = require("./optimize-css-webpack-plugin");
exports.OptimizeCssWebpackPlugin = optimize_css_webpack_plugin_1.OptimizeCssWebpackPlugin;
var bundle_budget_1 = require("./bundle-budget");
exports.BundleBudgetPlugin = bundle_budget_1.BundleBudgetPlugin;
var scripts_webpack_plugin_1 = require("./scripts-webpack-plugin");
exports.ScriptsWebpackPlugin = scripts_webpack_plugin_1.ScriptsWebpackPlugin;
var suppress_entry_chunks_webpack_plugin_1 = require("./suppress-entry-chunks-webpack-plugin");
exports.SuppressExtractedTextChunksWebpackPlugin = suppress_entry_chunks_webpack_plugin_1.SuppressExtractedTextChunksWebpackPlugin;
var remove_hash_plugin_1 = require("./remove-hash-plugin");
exports.RemoveHashPlugin = remove_hash_plugin_1.RemoveHashPlugin;
var named_chunks_plugin_1 = require("./named-chunks-plugin");
exports.NamedChunksPlugin = named_chunks_plugin_1.NamedLazyChunksPlugin;
var postcss_cli_resources_1 = require("./postcss-cli-resources");
exports.PostcssCliResources = postcss_cli_resources_1.default;
const path_1 = require("path");
exports.WebpackRollupLoader = require.resolve(path_1.join(__dirname, 'webpack-rollup-loader'));
/**
* @license
* Copyright Google Inc. 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 * as webpack from 'webpack';
import { NormalizedEntryPoint } from '../models/webpack-configs';
/**
* Webpack stats may incorrectly mark extra entry points `initial` chunks, when
* they are actually loaded asynchronously and thus not in the main bundle. This
* function finds extra entry points in Webpack stats and corrects this value
* whereever necessary. Does not modify {@param webpackStats}.
*/
export declare function markAsyncChunksNonInitial(webpackStats: webpack.Stats.ToJsonOutput, extraEntryPoints: NormalizedEntryPoint[]): Exclude<webpack.Stats.ToJsonOutput['chunks'], undefined>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Webpack stats may incorrectly mark extra entry points `initial` chunks, when
* they are actually loaded asynchronously and thus not in the main bundle. This
* function finds extra entry points in Webpack stats and corrects this value
* whereever necessary. Does not modify {@param webpackStats}.
*/
function markAsyncChunksNonInitial(webpackStats, extraEntryPoints) {
const { chunks = [], entrypoints: entryPoints = {} } = webpackStats;
// Find all Webpack chunk IDs not injected into the main bundle. We don't have
// to worry about transitive dependencies because extra entry points cannot be
// depended upon in Webpack, thus any extra entry point with `inject: false`,
// **cannot** be loaded in main bundle.
const asyncEntryPoints = extraEntryPoints.filter((entryPoint) => !entryPoint.inject);
const asyncChunkIds = flatMap(asyncEntryPoints, (entryPoint) => entryPoints[entryPoint.bundleName].chunks);
// Find chunks for each ID.
const asyncChunks = asyncChunkIds.map((chunkId) => {
const chunk = chunks.find((chunk) => chunk.id === chunkId);
if (!chunk) {
throw new Error(`Failed to find chunk (${chunkId}) in set:\n${JSON.stringify(chunks)}`);
}
return chunk;
})
// All Webpack chunks are dependent on `runtime`, which is never an async
// entry point, simply ignore this one.
.filter((chunk) => chunk.names.indexOf('runtime') === -1);
// A chunk is considered `initial` only if Webpack already belives it to be initial
// and the application developer did not mark it async via an extra entry point.
return chunks.map((chunk) => ({
...chunk,
initial: chunk.initial && !asyncChunks.find((asyncChunk) => asyncChunk === chunk),
}));
}
exports.markAsyncChunksNonInitial = markAsyncChunksNonInitial;
function flatMap(list, mapper) {
return [].concat(...list.map(mapper));
}
/**
* @license
* Copyright Google Inc. 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 * as webpack from 'webpack';
import { ProcessBundleResult } from '../../../src/utils/process-bundle';
import { Budget } from '../../browser/schema';
interface Threshold {
limit: number;
type: ThresholdType;
severity: ThresholdSeverity;
}
declare enum ThresholdType {
Max = "maximum",
Min = "minimum"
}
export declare enum ThresholdSeverity {
Warning = "warning",
Error = "error"
}
export declare function calculateThresholds(budget: Budget): IterableIterator<Threshold>;
export declare function checkBudgets(budgets: Budget[], webpackStats: webpack.Stats.ToJsonOutput, processResults: ProcessBundleResult[]): IterableIterator<{
severity: ThresholdSeverity;
message: string;
}>;
export declare function checkThresholds(thresholds: IterableIterator<Threshold>, size: number, label?: string): IterableIterator<{
severity: ThresholdSeverity;
message: string;
}>;
export {};
export declare function checkPort(port: number, host: string, basePort?: number): Promise<number>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const net = require("net");
function checkPort(port, host, basePort = 49152) {
return new Promise((resolve, reject) => {
function _getPort(portNumber) {
if (portNumber > 65535) {
reject(new Error(`There is no port available.`));
}
const server = net.createServer();
server.once('error', (err) => {
if (err.code !== 'EADDRINUSE') {
reject(err);
}
else if (port === 0) {
_getPort(portNumber + 1);
}
else {
// If the port isn't available and we weren't looking for any port, throw error.
reject(new Error(`Port ${port} is already in use. Use '--port' to specify a different port.`));
}
})
.once('listening', () => {
server.close();
resolve(portNumber);
})
.listen(portNumber, host);
}
_getPort(port || basePort);
});
}
exports.checkPort = checkPort;
export declare function findTests(patterns: string[], cwd: string, workspaceRoot: string): string[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const fs_1 = require("fs");
const glob = require("glob");
const path_1 = require("path");
const is_directory_1 = require("./is-directory");
// go through all patterns and find unique list of files
function findTests(patterns, cwd, workspaceRoot) {
return patterns.reduce((files, pattern) => {
const relativePathToMain = cwd.replace(workspaceRoot, '').substr(1); // remove leading slash
const tests = findMatchingTests(pattern, cwd, relativePathToMain);
tests.forEach(file => {
if (!files.includes(file)) {
files.push(file);
}
});
return files;
}, []);
}
exports.findTests = findTests;
function findMatchingTests(pattern, cwd, relativePathToMain) {
// normalize pattern, glob lib only accepts forward slashes
pattern = pattern.replace(/\\/g, '/');
relativePathToMain = relativePathToMain.replace(/\\/g, '/');
// remove relativePathToMain to support relative paths from root
// such paths are easy to get when running scripts via IDEs
if (pattern.startsWith(relativePathToMain + '/')) {
pattern = pattern.substr(relativePathToMain.length + 1); // +1 to include slash
}
// special logic when pattern does not look like a glob
if (!glob.hasMagic(pattern)) {
if (is_directory_1.isDirectory(path_1.join(cwd, pattern))) {
pattern = `${pattern}/**/*.spec.@(ts|tsx)`;
}
else {
// see if matching spec file exists
const extension = path_1.extname(pattern);
const matchingSpec = `${path_1.basename(pattern, extension)}.spec${extension}`;
if (fs_1.existsSync(path_1.join(cwd, path_1.dirname(pattern), matchingSpec))) {
pattern = path_1.join(path_1.dirname(pattern), matchingSpec).replace(/\\/g, '/');
}
}
}
const files = glob.sync(pattern, {
cwd,
});
return files;
}
export declare function findUp(names: string | string[], from: string, stopOnNodeModules?: boolean): string | null;
export declare function findAllNodeModules(from: string, root?: string): string[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const fs_1 = require("fs");
const path = require("path");
const is_directory_1 = require("./is-directory");
function findUp(names, from, stopOnNodeModules = false) {
if (!Array.isArray(names)) {
names = [names];
}
const root = path.parse(from).root;
let currentDir = from;
while (currentDir && currentDir !== root) {
for (const name of names) {
const p = path.join(currentDir, name);
if (fs_1.existsSync(p)) {
return p;
}
}
if (stopOnNodeModules) {
const nodeModuleP = path.join(currentDir, 'node_modules');
if (fs_1.existsSync(nodeModuleP)) {
return null;
}
}
currentDir = path.dirname(currentDir);
}
return null;
}
exports.findUp = findUp;
function findAllNodeModules(from, root) {
const nodeModules = [];
let current = from;
while (current && current !== root) {
const potential = path.join(current, 'node_modules');
if (fs_1.existsSync(potential) && is_directory_1.isDirectory(potential)) {
nodeModules.push(potential);
}
const next = path.dirname(current);
if (next === current) {
break;
}
current = next;
}
return nodeModules;
}
exports.findAllNodeModules = findAllNodeModules;
/**
* @license
* Copyright Google Inc. 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
*/
export declare type LoadOutputFileFunctionType = (file: string) => Promise<string>;
export declare type CrossOriginValue = 'none' | 'anonymous' | 'use-credentials';
export interface AugmentIndexHtmlOptions {
input: string;
inputContent: string;
baseHref?: string;
deployUrl?: string;
sri: boolean;
/** crossorigin attribute setting of elements that provide CORS support */
crossOrigin?: CrossOriginValue;
files: FileInfo[];
/** Files that should be added using 'nomodule'. */
noModuleFiles?: FileInfo[];
/** Files that should be added using 'module'. */
moduleFiles?: FileInfo[];
loadOutputFile: LoadOutputFileFunctionType;
/** Used to sort the inseration of files in the HTML file */
entrypoints: string[];
/** Used to set the document default locale */
lang?: string;
}
export interface FileInfo {
file: string;
name: string;
extension: string;
}
export declare function augmentIndexHtml(params: AugmentIndexHtmlOptions): Promise<string>;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = require("crypto");
const webpack_sources_1 = require("webpack-sources");
const parse5 = require('parse5');
/*
* Helper function used by the IndexHtmlWebpackPlugin.
* Can also be directly used by builder, e. g. in order to generate an index.html
* after processing several configurations in order to build different sets of
* bundles for differential serving.
*/
// tslint:disable-next-line: no-big-function
async function augmentIndexHtml(params) {
const { loadOutputFile, files, noModuleFiles = [], moduleFiles = [], entrypoints } = params;
let { crossOrigin = 'none' } = params;
if (params.sri && crossOrigin === 'none') {
crossOrigin = 'anonymous';
}
const stylesheets = new Set();
const scripts = new Set();
// Sort files in the order we want to insert them by entrypoint and dedupes duplicates
const mergedFiles = [...moduleFiles, ...noModuleFiles, ...files];
for (const entrypoint of entrypoints) {
for (const { extension, file, name } of mergedFiles) {
if (name !== entrypoint) {
continue;
}
switch (extension) {
case '.js':
scripts.add(file);
break;
case '.css':
stylesheets.add(file);
break;
}
}
}
// Find the head and body elements
const treeAdapter = parse5.treeAdapters.default;
const document = parse5.parse(params.inputContent, { treeAdapter, locationInfo: true });
let headElement;
let bodyElement;
let htmlElement;
for (const docChild of document.childNodes) {
if (docChild.tagName === 'html') {
htmlElement = docChild;
for (const htmlChild of docChild.childNodes) {
if (htmlChild.tagName === 'head') {
headElement = htmlChild;
}
else if (htmlChild.tagName === 'body') {
bodyElement = htmlChild;
}
}
}
}
if (!headElement || !bodyElement) {
throw new Error('Missing head and/or body elements');
}
// Determine script insertion point
let scriptInsertionPoint;
if (bodyElement.__location && bodyElement.__location.endTag) {
scriptInsertionPoint = bodyElement.__location.endTag.startOffset;
}
else {
// Less accurate fallback
// parse5 4.x does not provide locations if malformed html is present
scriptInsertionPoint = params.inputContent.indexOf('</body>');
}
let styleInsertionPoint;
if (headElement.__location && headElement.__location.endTag) {
styleInsertionPoint = headElement.__location.endTag.startOffset;
}
else {
// Less accurate fallback
// parse5 4.x does not provide locations if malformed html is present
styleInsertionPoint = params.inputContent.indexOf('</head>');
}
// Inject into the html
const indexSource = new webpack_sources_1.ReplaceSource(new webpack_sources_1.RawSource(params.inputContent), params.input);
let scriptElements = '';
for (const script of scripts) {
const attrs = [
{ name: 'src', value: (params.deployUrl || '') + script },
];
if (crossOrigin !== 'none') {
attrs.push({ name: 'crossorigin', value: crossOrigin });
}
// We want to include nomodule or module when a file is not common amongs all
// such as runtime.js
const scriptPredictor = ({ file }) => file === script;
if (!files.some(scriptPredictor)) {
// in some cases for differential loading file with the same name is available in both
// nomodule and module such as scripts.js
// we shall not add these attributes if that's the case
const isNoModuleType = noModuleFiles.some(scriptPredictor);
const isModuleType = moduleFiles.some(scriptPredictor);
if (isNoModuleType && !isModuleType) {
attrs.push({ name: 'nomodule', value: null }, { name: 'defer', value: null });
}
else if (isModuleType && !isNoModuleType) {
attrs.push({ name: 'type', value: 'module' });
}
else {
attrs.push({ name: 'defer', value: null });
}
}
else {
attrs.push({ name: 'defer', value: null });
}
if (params.sri) {
const content = await loadOutputFile(script);
attrs.push(..._generateSriAttributes(content));
}
const attributes = attrs
.map(attr => (attr.value === null ? attr.name : `${attr.name}="${attr.value}"`))
.join(' ');
scriptElements += `<script ${attributes}></script>`;
}
indexSource.insert(scriptInsertionPoint, scriptElements);
// Adjust base href if specified
if (typeof params.baseHref == 'string') {
let baseElement;
for (const headChild of headElement.childNodes) {
if (headChild.tagName === 'base') {
baseElement = headChild;
}
}
const baseFragment = treeAdapter.createDocumentFragment();
if (!baseElement) {
baseElement = treeAdapter.createElement('base', undefined, [
{ name: 'href', value: params.baseHref },
]);
treeAdapter.appendChild(baseFragment, baseElement);
indexSource.insert(headElement.__location.startTag.endOffset, parse5.serialize(baseFragment, { treeAdapter }));
}
else {
let hrefAttribute;
for (const attribute of baseElement.attrs) {
if (attribute.name === 'href') {
hrefAttribute = attribute;
}
}
if (hrefAttribute) {
hrefAttribute.value = params.baseHref;
}
else {
baseElement.attrs.push({ name: 'href', value: params.baseHref });
}
treeAdapter.appendChild(baseFragment, baseElement);
indexSource.replace(baseElement.__location.startOffset, baseElement.__location.endOffset, parse5.serialize(baseFragment, { treeAdapter }));
}
}
const styleElements = treeAdapter.createDocumentFragment();
for (const stylesheet of stylesheets) {
const attrs = [
{ name: 'rel', value: 'stylesheet' },
{ name: 'href', value: (params.deployUrl || '') + stylesheet },
];
if (crossOrigin !== 'none') {
attrs.push({ name: 'crossorigin', value: crossOrigin });
}
if (params.sri) {
const content = await loadOutputFile(stylesheet);
attrs.push(..._generateSriAttributes(content));
}
const element = treeAdapter.createElement('link', undefined, attrs);
treeAdapter.appendChild(styleElements, element);
}
indexSource.insert(styleInsertionPoint, parse5.serialize(styleElements, { treeAdapter }));
// Adjust document locale if specified
if (typeof params.lang == 'string') {
const htmlFragment = treeAdapter.createDocumentFragment();
let langAttribute;
for (const attribute of htmlElement.attrs) {
if (attribute.name === 'lang') {
langAttribute = attribute;
}
}
if (langAttribute) {
langAttribute.value = params.lang;
}
else {
htmlElement.attrs.push({ name: 'lang', value: params.lang });
}
// we want only openning tag
htmlElement.childNodes = [];
treeAdapter.appendChild(htmlFragment, htmlElement);
indexSource.replace(htmlElement.__location.startTag.startOffset, htmlElement.__location.startTag.endOffset - 1, parse5.serialize(htmlFragment, { treeAdapter }).replace('</html>', ''));
}
return indexSource.source();
}
exports.augmentIndexHtml = augmentIndexHtml;
function _generateSriAttributes(content) {
const algo = 'sha384';
const hash = crypto_1.createHash(algo)
.update(content, 'utf8')
.digest('base64');
return [{ name: 'integrity', value: `${algo}-${hash}` }];
}
/**
* @license
* Copyright Google Inc. 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 { EmittedFiles } from '@angular-devkit/build-webpack';
import { Path, virtualFs } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import { ExtraEntryPoint } from '../../../browser/schema';
import { CrossOriginValue } from './augment-index-html';
export interface WriteIndexHtmlOptions {
host: virtualFs.Host;
outputPath: Path;
indexPath: Path;
files?: EmittedFiles[];
noModuleFiles?: EmittedFiles[];
moduleFiles?: EmittedFiles[];
baseHref?: string;
deployUrl?: string;
sri?: boolean;
scripts?: ExtraEntryPoint[];
styles?: ExtraEntryPoint[];
postTransform?: IndexHtmlTransform;
crossOrigin?: CrossOriginValue;
lang?: string;
}
export declare type IndexHtmlTransform = (content: string) => Promise<string>;
export declare function writeIndexHtml({ host, outputPath, indexPath, files, noModuleFiles, moduleFiles, baseHref, deployUrl, sri, scripts, styles, postTransform, crossOrigin, lang, }: WriteIndexHtmlOptions): Observable<void>;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@angular-devkit/core");
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const package_chunk_sort_1 = require("../package-chunk-sort");
const strip_bom_1 = require("../strip-bom");
const augment_index_html_1 = require("./augment-index-html");
function writeIndexHtml({ host, outputPath, indexPath, files = [], noModuleFiles = [], moduleFiles = [], baseHref, deployUrl, sri = false, scripts = [], styles = [], postTransform, crossOrigin, lang, }) {
return host.read(indexPath).pipe(operators_1.map(content => strip_bom_1.stripBom(core_1.virtualFs.fileBufferToString(content))), operators_1.switchMap(content => augment_index_html_1.augmentIndexHtml({
input: core_1.getSystemPath(outputPath),
inputContent: content,
baseHref,
deployUrl,
crossOrigin,
sri,
entrypoints: package_chunk_sort_1.generateEntryPoints({ scripts, styles }),
files: filterAndMapBuildFiles(files, ['.js', '.css']),
noModuleFiles: filterAndMapBuildFiles(noModuleFiles, '.js'),
moduleFiles: filterAndMapBuildFiles(moduleFiles, '.js'),
loadOutputFile: async (filePath) => {
return host
.read(core_1.join(core_1.dirname(outputPath), filePath))
.pipe(operators_1.map(data => core_1.virtualFs.fileBufferToString(data)))
.toPromise();
},
lang: lang,
})), operators_1.switchMap(content => (postTransform ? postTransform(content) : rxjs_1.of(content))), operators_1.map(content => core_1.virtualFs.stringToFileBuffer(content)), operators_1.switchMap(content => host.write(outputPath, content)));
}
exports.writeIndexHtml = writeIndexHtml;
function filterAndMapBuildFiles(files, extensionFilter) {
const filteredFiles = [];
const validExtensions = Array.isArray(extensionFilter)
? extensionFilter
: [extensionFilter];
for (const { file, name, extension, initial } of files) {
if (name && initial && validExtensions.includes(extension)) {
filteredFiles.push({ file, extension, name });
}
}
return filteredFiles;
}
/**
* @license
* Copyright Google Inc. 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
*/
export declare function isDirectory(path: string): boolean;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
function isDirectory(path) {
try {
return fs.statSync(path).isDirectory();
}
catch (_) {
return false;
}
}
exports.isDirectory = isDirectory;
/**
* @license
* Copyright Google Inc. 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 { ExtraEntryPoint } from '../../browser/schema';
export declare function generateEntryPoints(appConfig: {
styles: ExtraEntryPoint[];
scripts: ExtraEntryPoint[];
}): string[];
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("../models/webpack-configs/utils");
function generateEntryPoints(appConfig) {
// Add all styles/scripts, except lazy-loaded ones.
const extraEntryPoints = (extraEntryPoints, defaultBundleName) => {
const entryPoints = utils_1.normalizeExtraEntryPoints(extraEntryPoints, defaultBundleName)
.filter(entry => entry.inject)
.map(entry => entry.bundleName);
// remove duplicates
return [...new Set(entryPoints)];
};
const entryPoints = [
'runtime',
'polyfills-es5',
'polyfills',
'sw-register',
...extraEntryPoints(appConfig.styles, 'styles'),
...extraEntryPoints(appConfig.scripts, 'scripts'),
'vendor',
'main',
];
const duplicates = [
...new Set(entryPoints.filter(x => entryPoints.indexOf(x) !== entryPoints.lastIndexOf(x))),
];
if (duplicates.length > 0) {
throw new Error(`Multiple bundles have been named the same: '${duplicates.join(`', '`)}'.`);
}
return entryPoints;
}
exports.generateEntryPoints = generateEntryPoints;
/**
* @license
* Copyright Google Inc. 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 { ParsedConfiguration } from '@angular/compiler-cli';
/**
* Reads and parses a given TsConfig file.
*
* @param tsconfigPath - An absolute or relative path from 'workspaceRoot' of the tsconfig file.
* @param workspaceRoot - workspaceRoot root location when provided
* it will resolve 'tsconfigPath' from this path.
*/
export declare function readTsconfig(tsconfigPath: string, workspaceRoot?: string): ParsedConfiguration;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
/**
* Reads and parses a given TsConfig file.
*
* @param tsconfigPath - An absolute or relative path from 'workspaceRoot' of the tsconfig file.
* @param workspaceRoot - workspaceRoot root location when provided
* it will resolve 'tsconfigPath' from this path.
*/
function readTsconfig(tsconfigPath, workspaceRoot) {
const tsConfigFullPath = workspaceRoot
? path.resolve(workspaceRoot, tsconfigPath)
: tsconfigPath;
// We use 'ng' instead of 'ts' here because 'ts' is not aware of 'angularCompilerOptions'
// and will not merged them if they are at un upper level tsconfig file when using `extends`.
const ng = require('@angular/compiler-cli');
const configResult = ng.readConfiguration(tsConfigFullPath);
if (configResult.errors && configResult.errors.length) {
throw new Error(ng.formatDiagnostics(configResult.errors));
}
return configResult;
}
exports.readTsconfig = readTsconfig;
/**
* @license
* Copyright Google Inc. 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 { Path, virtualFs } from '@angular-devkit/core';
export declare function augmentAppWithServiceWorker(host: virtualFs.Host, projectRoot: Path, appRoot: Path, outputPath: Path, baseHref: string, ngswConfigPath?: string): Promise<void>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const core_1 = require("@angular-devkit/core");
const crypto = require("crypto");
class CliFilesystem {
constructor(_host, base) {
this._host = _host;
this.base = base;
}
list(path) {
return this._recursiveList(this._resolve(path), []).catch(() => []);
}
async read(path) {
return core_1.virtualFs.fileBufferToString(await this._readIntoBuffer(path));
}
async hash(path) {
const sha1 = crypto.createHash('sha1');
sha1.update(Buffer.from(await this._readIntoBuffer(path)));
return sha1.digest('hex');
}
write(path, content) {
return this._host.write(this._resolve(path), core_1.virtualFs.stringToFileBuffer(content))
.toPromise();
}
_readIntoBuffer(path) {
return this._host.read(this._resolve(path)).toPromise();
}
_resolve(path) {
return core_1.join(core_1.normalize(this.base), core_1.normalize(path));
}
async _recursiveList(path, items) {
const fragments = await this._host.list(path).toPromise();
for (const fragment of fragments) {
const item = core_1.join(path, fragment);
if (await this._host.isDirectory(item).toPromise()) {
await this._recursiveList(item, items);
}
else {
items.push('/' + core_1.relative(core_1.normalize(this.base), item));
}
}
return items;
}
}
async function augmentAppWithServiceWorker(host, projectRoot, appRoot, outputPath, baseHref, ngswConfigPath) {
const distPath = core_1.normalize(outputPath);
const systemProjectRoot = core_1.getSystemPath(projectRoot);
// Find the service worker package
const workerPath = core_1.normalize(require.resolve('@angular/service-worker/ngsw-worker.js', { paths: [systemProjectRoot] }));
const swConfigPath = require.resolve('@angular/service-worker/config', { paths: [systemProjectRoot] });
// Determine the configuration file path
let configPath;
if (ngswConfigPath) {
configPath = core_1.normalize(ngswConfigPath);
}
else {
configPath = core_1.join(appRoot, 'ngsw-config.json');
}
// Ensure the configuration file exists
const configExists = await host.exists(configPath).toPromise();
if (!configExists) {
throw new Error(core_1.tags.oneLine `
Error: Expected to find an ngsw-config.json configuration
file in the ${core_1.getSystemPath(appRoot)} folder. Either provide one or disable Service Worker
in your angular.json configuration file.
`);
}
// Read the configuration file
const config = JSON.parse(core_1.virtualFs.fileBufferToString(await host.read(configPath).toPromise()));
// Generate the manifest
const GeneratorConstructor = require(swConfigPath).Generator;
const generator = new GeneratorConstructor(new CliFilesystem(host, outputPath), baseHref);
const output = await generator.process(config);
// Write the manifest
const manifest = JSON.stringify(output, null, 2);
await host.write(core_1.join(distPath, 'ngsw.json'), core_1.virtualFs.stringToFileBuffer(manifest)).toPromise();
// Write the worker code
// NOTE: This is inefficient (kernel -> userspace -> kernel).
// `fs.copyFile` would be a better option but breaks the host abstraction
const workerCode = await host.read(workerPath).toPromise();
await host.write(core_1.join(distPath, 'ngsw-worker.js'), workerCode).toPromise();
// If present, write the safety worker code
const safetyPath = core_1.join(core_1.dirname(workerPath), 'safety-worker.js');
if (await host.exists(safetyPath).toPromise()) {
const safetyCode = await host.read(safetyPath).toPromise();
await host.write(core_1.join(distPath, 'worker-basic.min.js'), safetyCode).toPromise();
await host.write(core_1.join(distPath, 'safety-worker.js'), safetyCode).toPromise();
}
}
exports.augmentAppWithServiceWorker = augmentAppWithServiceWorker;
export declare function formatSize(size: number): string;
export declare function generateBundleStats(info: {
id: string | number;
size?: number;
files: string[];
names?: string[];
entry: boolean;
initial: boolean;
rendered?: boolean;
}, colors: boolean): string;
export declare function generateBuildStats(hash: string, time: number, colors: boolean): string;
export declare function statsToString(json: any, statsConfig: any): string;
export declare function statsWarningsToString(json: any, statsConfig: any): string;
export declare function statsErrorsToString(json: any, statsConfig: any): string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
const core_1 = require("@angular-devkit/core");
const path = require("path");
const { bold, green, red, reset, white, yellow } = core_1.terminal;
function formatSize(size) {
if (size <= 0) {
return '0 bytes';
}
const abbreviations = ['bytes', 'kB', 'MB', 'GB'];
const index = Math.floor(Math.log(size) / Math.log(1024));
return `${+(size / Math.pow(1024, index)).toPrecision(3)} ${abbreviations[index]}`;
}
exports.formatSize = formatSize;
function generateBundleStats(info, colors) {
const g = (x) => (colors ? bold(green(x)) : x);
const y = (x) => (colors ? bold(yellow(x)) : x);
const id = info.id ? y(info.id.toString()) : '';
const size = typeof info.size === 'number' ? ` ${formatSize(info.size)}` : '';
const files = info.files.map(f => path.basename(f)).join(', ');
const names = info.names ? ` (${info.names.join(', ')})` : '';
const initial = y(info.entry ? '[entry]' : info.initial ? '[initial]' : '');
const flags = ['rendered', 'recorded']
.map(f => (f && info[f] ? g(` [${f}]`) : ''))
.join('');
return `chunk {${id}} ${g(files)}${names}${size} ${initial}${flags}`;
}
exports.generateBundleStats = generateBundleStats;
function generateBuildStats(hash, time, colors) {
const w = (x) => colors ? bold(white(x)) : x;
return `Date: ${w(new Date().toISOString())} - Hash: ${w(hash)} - Time: ${w('' + time)}ms`;
}
exports.generateBuildStats = generateBuildStats;
function statsToString(json, statsConfig) {
const colors = statsConfig.colors;
const rs = (x) => colors ? reset(x) : x;
const w = (x) => colors ? bold(white(x)) : x;
const changedChunksStats = json.chunks
.filter((chunk) => chunk.rendered)
.map((chunk) => {
const assets = json.assets.filter((asset) => chunk.files.indexOf(asset.name) != -1);
const summedSize = assets.filter((asset) => !asset.name.endsWith(".map")).reduce((total, asset) => { return total + asset.size; }, 0);
return generateBundleStats({ ...chunk, size: summedSize }, colors);
});
const unchangedChunkNumber = json.chunks.length - changedChunksStats.length;
if (unchangedChunkNumber > 0) {
return '\n' + rs(core_1.tags.stripIndents `
Date: ${w(new Date().toISOString())} - Hash: ${w(json.hash)}
${unchangedChunkNumber} unchanged chunks
${changedChunksStats.join('\n')}
Time: ${w('' + json.time)}ms
`);
}
else {
return '\n' + rs(core_1.tags.stripIndents `
${changedChunksStats.join('\n')}
Date: ${w(new Date().toISOString())} - Hash: ${w(json.hash)} - Time: ${w('' + json.time)}ms
`);
}
}
exports.statsToString = statsToString;
// TODO(#16193): Don't emit this warning in the first place rather than just suppressing it.
const ERRONEOUS_WARNINGS = [
/multiple assets emit different content.*3rdpartylicenses\.txt/i,
];
function statsWarningsToString(json, statsConfig) {
const colors = statsConfig.colors;
const rs = (x) => colors ? reset(x) : x;
const y = (x) => colors ? bold(yellow(x)) : x;
return rs('\n' + json.warnings
.map((warning) => `${warning}`)
.filter((warning) => !ERRONEOUS_WARNINGS.some((erroneous) => erroneous.test(warning)))
.map((warning) => y(`WARNING in ${warning}`))
.join('\n\n'));
}
exports.statsWarningsToString = statsWarningsToString;
function statsErrorsToString(json, statsConfig) {
const colors = statsConfig.colors;
const rs = (x) => colors ? reset(x) : x;
const r = (x) => colors ? bold(red(x)) : x;
return rs('\n' + json.errors.map((error) => r(`ERROR in ${error}`)).join('\n'));
}
exports.statsErrorsToString = statsErrorsToString;
/**
* @license
* Copyright Google Inc. 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
*/
export declare function stripBom(data: string): string;
"use strict";
/**
* @license
* Copyright Google Inc. 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
*/
// tslint:disable
// TODO: cleanup this file, it's copied as is from Angular CLI.
Object.defineProperty(exports, "__esModule", { value: true });
// Strip BOM from file data.
// https://stackoverflow.com/questions/24356713
function stripBom(data) {
return data.replace(/^\uFEFF/, '');
}
exports.stripBom = stripBom;
import { JsonObject } from '@angular-devkit/core';
import { Schema as BuildWebpackAppShellSchema } from './schema';
declare const _default: import("@angular-devkit/architect/src/internal").Builder<JsonObject & BuildWebpackAppShellSchema>;
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @license
* Copyright Google Inc. 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
*/
const architect_1 = require("@angular-devkit/architect");
const core_1 = require("@angular-devkit/core");
const node_1 = require("@angular-devkit/core/node");
const fs = require("fs");
const path = require("path");
const service_worker_1 = require("../angular-cli-files/utilities/service-worker");
async function _renderUniversal(options, context, browserResult, serverResult) {
// Get browser target options.
const browserTarget = architect_1.targetFromTargetString(options.browserTarget);
const rawBrowserOptions = await context.getTargetOptions(browserTarget);
const browserBuilderName = await context.getBuilderNameForTarget(browserTarget);
const browserOptions = await context.validateOptions(rawBrowserOptions, browserBuilderName);
// Initialize zone.js
const root = context.workspaceRoot;
const zonePackage = require.resolve('zone.js', { paths: [root] });
await Promise.resolve().then(() => require(zonePackage));
const host = new node_1.NodeJsSyncHost();
const projectName = context.target && context.target.project;
if (!projectName) {
throw new Error('The builder requires a target.');
}
const projectMetadata = await context.getProjectMetadata(projectName);
const projectRoot = core_1.resolve(core_1.normalize(root), core_1.normalize(projectMetadata.root || ''));
for (const outputPath of browserResult.outputPaths) {
const localeDirectory = path.relative(browserResult.baseOutputPath, outputPath);
const browserIndexOutputPath = path.join(outputPath, 'index.html');
const indexHtml = fs.readFileSync(browserIndexOutputPath, 'utf8');
const serverBundlePath = await _getServerModuleBundlePath(options, context, serverResult, localeDirectory);
const { AppServerModule, AppServerModuleNgFactory, renderModule, renderModuleFactory, } = await Promise.resolve().then(() => require(serverBundlePath));
let renderModuleFn;
let AppServerModuleDef;
if (renderModuleFactory && AppServerModuleNgFactory) {
renderModuleFn = renderModuleFactory;
AppServerModuleDef = AppServerModuleNgFactory;
}
else if (renderModule && AppServerModule) {
renderModuleFn = renderModule;
AppServerModuleDef = AppServerModule;
}
else {
throw new Error(`renderModule method and/or AppServerModule were not exported from: ${serverBundlePath}.`);
}
// Load platform server module renderer
const renderOpts = {
document: indexHtml,
url: options.route,
};
const html = await renderModuleFn(AppServerModuleDef, renderOpts);
// Overwrite the client index file.
const outputIndexPath = options.outputIndexPath
? path.join(root, options.outputIndexPath)
: browserIndexOutputPath;
fs.writeFileSync(outputIndexPath, html);
if (browserOptions.serviceWorker) {
await service_worker_1.augmentAppWithServiceWorker(host, core_1.normalize(root), projectRoot, core_1.normalize(outputPath), browserOptions.baseHref || '/', browserOptions.ngswConfigPath);
}
}
return browserResult;
}
async function _getServerModuleBundlePath(options, context, serverResult, browserLocaleDirectory) {
if (options.appModuleBundle) {
return path.join(context.workspaceRoot, options.appModuleBundle);
}
else {
const { baseOutputPath = '' } = serverResult;
const outputPath = path.join(baseOutputPath, browserLocaleDirectory);
if (!fs.existsSync(outputPath)) {
throw new Error(`Could not find server output directory: ${outputPath}.`);
}
const files = fs.readdirSync(outputPath, 'utf8');
const re = /^main\.(?:[a-zA-Z0-9]{20}\.)?(?:bundle\.)?js$/;
const maybeMain = files.filter(x => re.test(x))[0];
if (!maybeMain) {
throw new Error('Could not find the main bundle.');
}
else {
return path.join(outputPath, maybeMain);
}
}
}
async function _appShellBuilder(options, context) {
const browserTarget = architect_1.targetFromTargetString(options.browserTarget);
const serverTarget = architect_1.targetFromTargetString(options.serverTarget);
// Never run the browser target in watch mode.
// If service worker is needed, it will be added in _renderUniversal();
const browserTargetRun = await context.scheduleTarget(browserTarget, {
watch: false,
serviceWorker: false,
});
const serverTargetRun = await context.scheduleTarget(serverTarget, {
watch: false,
});
try {
const [browserResult, serverResult] = await Promise.all([
browserTargetRun.result,
serverTargetRun.result,
]);
if (browserResult.success === false || browserResult.baseOutputPath === undefined) {
return browserResult;
}
else if (serverResult.success === false) {
return serverResult;
}
return await _renderUniversal(options, context, browserResult, serverResult);
}
catch (err) {
return { success: false, error: err.message };
}
finally {
// Just be good citizens and stop those jobs.
await Promise.all([browserTargetRun.stop(), serverTargetRun.stop()]);
}
}
exports.default = architect_1.createBuilder(_appShellBuilder);
/**
* App Shell target options for Build Facade.
*/
export interface Schema {
/**
* Script that exports the Server AppModule to render. This should be the main JavaScript
* outputted by the server target. By default we will resolve the outputPath of the
* serverTarget and find a bundle named 'main' in it (whether or not there's a hash tag).
*/
appModuleBundle?: string;
/**
* Target to build.
*/
browserTarget: string;
/**
* The input path for the index.html file. By default uses the output index.html of the
* browser target.
*/
inputIndexPath?: string;
/**
* The output path of the index.html file. By default will overwrite the input file.
*/
outputIndexPath?: string;
/**
* The route to render.
*/
route?: string;
/**
* Server target to use for rendering the app shell.
*/
serverTarget: string;
}
"use strict";
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
Object.defineProperty(exports, "__esModule", { value: true });
{
"$schema": "http://json-schema.org/draft-07/schema",
"title": "App Shell Target",
"description": "App Shell target options for Build Facade.",
"type": "object",
"properties": {
"browserTarget": {
"type": "string",
"description": "Target to build.",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
},
"serverTarget": {
"type": "string",
"description": "Server target to use for rendering the app shell.",
"pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$"
},
"appModuleBundle": {
"type": "string",
"description": "Script that exports the Server AppModule to render. This should be the main JavaScript outputted by the server target. By default we will resolve the outputPath of the serverTarget and find a bundle named 'main' in it (whether or not there's a hash tag)."
},
"route": {
"type": "string",
"description": "The route to render.",
"default": "/"
},
"inputIndexPath": {
"type": "string",
"description": "The input path for the index.html file. By default uses the output index.html of the browser target."
},
"outputIndexPath": {
"type": "string",
"description": "The output path of the index.html file. By default will overwrite the input file."
}
},
"additionalProperties": false,
"required": [
"browserTarget",
"serverTarget"
]
}
/// <reference types="node" />
/**
* @license
* Copyright Google Inc. 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 { BuilderContext, BuilderOutput } from '@angular-devkit/architect';
import { WebpackLoggingCallback } from '@angular-devkit/build-webpack';
import { json, logging, virtualFs } from '@angular-devkit/core';
import * as fs from 'fs';
import { Observable } from 'rxjs';
import * as webpack from 'webpack';
import { IndexHtmlTransform } from '../angular-cli-files/utilities/index-file/write-index-html';
import { ExecutionTransformer } from '../transforms';
import { I18nOptions } from '../utils/i18n-options';
import { Schema as BrowserBuilderSchema } from './schema';
export declare type BrowserBuilderOutput = json.JsonObject & BuilderOutput & {
baseOutputPath: string;
outputPaths: string[];
/**
* @deprecated in version 9. Use 'outputPaths' instead.
*/
outputPath: string;
};
export declare function createBrowserLoggingCallback(verbose: boolean, logger: logging.LoggerApi): WebpackLoggingCallback;
interface ConfigFromContextReturn {
config: webpack.Configuration;
projectRoot: string;
projectSourceRoot?: string;
}
export declare function buildBrowserWebpackConfigFromContext(options: BrowserBuilderSchema, context: BuilderContext, host: virtualFs.Host<fs.Stats>, i18n: boolean): Promise<ConfigFromContextReturn & {
i18n: I18nOptions;
}>;
export declare function buildBrowserWebpackConfigFromContext(options: BrowserBuilderSchema, context: BuilderContext, host?: virtualFs.Host<fs.Stats>): Promise<ConfigFromContextReturn>;
export declare function buildWebpackBrowser(options: BrowserBuilderSchema, context: BuilderContext, transforms?: {
webpackConfiguration?: ExecutionTransformer<webpack.Configuration>;
logging?: WebpackLoggingCallback;
indexHtml?: IndexHtmlTransform;
}): Observable<BrowserBuilderOutput>;
declare const _default: import("@angular-devkit/architect/src/internal").Builder<json.JsonObject & BrowserBuilderSchema>;
export default _default;
"use strict";
// THIS FILE IS AUTOMATICALLY GENERATED. TO UPDATE THIS FILE YOU NEED TO CHANGE THE
// CORRESPONDING JSON SCHEMA FILE, THEN RUN devkit-admin build (or bazel build ...).
Object.defineProperty(exports, "__esModule", { value: true });
/**
* The type of budget.
*/
var Type;
(function (Type) {
Type["All"] = "all";
Type["AllScript"] = "allScript";
Type["Any"] = "any";
Type["AnyComponentStyle"] = "anyComponentStyle";
Type["AnyScript"] = "anyScript";
Type["Bundle"] = "bundle";
Type["Initial"] = "initial";
})(Type = exports.Type || (exports.Type = {}));
/**
* Define the crossorigin attribute setting of elements that provide CORS support.
*/
var CrossOrigin;
(function (CrossOrigin) {
CrossOrigin["Anonymous"] = "anonymous";
CrossOrigin["None"] = "none";
CrossOrigin["UseCredentials"] = "use-credentials";
})(CrossOrigin = exports.CrossOrigin || (exports.CrossOrigin = {}));
/**
* How to handle missing translations for i18n.
*/
var I18NMissingTranslation;
(function (I18NMissingTranslation) {
I18NMissingTranslation["Error"] = "error";
I18NMissingTranslation["Ignore"] = "ignore";
I18NMissingTranslation["Warning"] = "warning";
})(I18NMissingTranslation = exports.I18NMissingTranslation || (exports.I18NMissingTranslation = {}));
/**
* Define the output filename cache-busting hashing mode.
*/
var OutputHashing;
(function (OutputHashing) {
OutputHashing["All"] = "all";
OutputHashing["Bundles"] = "bundles";
OutputHashing["Media"] = "media";
OutputHashing["None"] = "none";
})(OutputHashing = exports.OutputHashing || (exports.OutputHashing = {}));
/**
* @license
* Copyright Google Inc. 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 { BuilderContext } from '@angular-devkit/architect';
import { DevServerBuildOutput, WebpackLoggingCallback } from '@angular-devkit/build-webpack';
import { json, logging } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import * as webpack from 'webpack';
import * as WebpackDevServer from 'webpack-dev-server';
import { IndexHtmlTransform } from '../angular-cli-files/utilities/index-file/write-index-html';
import { Schema as BrowserBuilderSchema } from '../browser/schema';
import { ExecutionTransformer } from '../transforms';
import { Schema } from './schema';
export declare type DevServerBuilderOptions = Schema & json.JsonObject;
export declare type DevServerBuilderOutput = DevServerBuildOutput & {
baseUrl: string;
};
/**
* Reusable implementation of the build angular webpack dev server builder.
* @param options Dev Server options.
* @param context The build context.
* @param transforms A map of transforms that can be used to hook into some logic (such as
* transforming webpack configuration before passing it to webpack).
*/
export declare function serveWebpackBrowser(options: DevServerBuilderOptions, context: BuilderContext, transforms?: {
webpackConfiguration?: ExecutionTransformer<webpack.Configuration>;
logging?: WebpackLoggingCallback;
indexHtml?: IndexHtmlTransform;
}): Observable<DevServerBuilderOutput>;
/**
* Create a webpack configuration for the dev server.
* @param workspaceRoot The root of the workspace. This comes from the context.
* @param serverOptions DevServer options, based on the dev server input schema.
* @param browserOptions Browser builder options. See the browser builder from this package.
* @param logger A generic logger to use for showing warnings.
* @returns A webpack dev-server configuration.
*/
export declare function buildServerConfig(workspaceRoot: string, serverOptions: DevServerBuilderOptions, browserOptions: BrowserBuilderSchema, logger: logging.LoggerApi): WebpackDevServer.Configuration;
/**
* Resolve and build a URL _path_ that will be the root of the server. This resolved base href and
* deploy URL from the browser options and returns a path from the root.
* @param serverOptions The server options that were passed to the server builder.
* @param browserOptions The browser options that were passed to the browser builder.
* @param logger A generic logger to use for showing warnings.
*/
export declare function buildServePath(serverOptions: DevServerBuilderOptions, browserOptions: BrowserBuilderSchema, logger: logging.LoggerApi): string;
declare const _default: import("@angular-devkit/architect/src/internal").Builder<DevServerBuilderOptions>;
export default _default;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment