-
Notifications
You must be signed in to change notification settings - Fork 12k
/
Copy pathhelpers.ts
154 lines (133 loc) · 4.5 KB
/
helpers.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
* @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 { basename, normalize } from '@angular-devkit/core';
import * as path from 'path';
import { ScriptTarget } from 'typescript';
import { Options, SourceMapDevToolPlugin } from 'webpack';
import { ExtraEntryPoint, ExtraEntryPointClass } from '../../browser/schema';
import { withWebpackFourOrFive } from '../../utils/webpack-version';
export interface HashFormat {
chunk: string;
extract: string;
file: string;
script: string;
}
export function getOutputHashFormat(option: string, length = 20): HashFormat {
const hashFormats: { [option: string]: HashFormat } = {
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'];
}
export type NormalizedEntryPoint = Required<ExtraEntryPointClass>;
export function normalizeExtraEntryPoints(
extraEntryPoints: ExtraEntryPoint[],
defaultBundleName: string,
): NormalizedEntryPoint[] {
return extraEntryPoints.map(entry => {
if (typeof entry === 'string') {
return { input: entry, inject: true, bundleName: defaultBundleName };
}
const { inject = true, ...newEntry } = entry;
let bundleName;
if (entry.bundleName) {
bundleName = entry.bundleName;
} else if (!inject) {
// Lazy entry points use the file name as bundle name.
bundleName = basename(
normalize(entry.input.replace(/\.(js|css|scss|sass|less|styl)$/i, '')),
);
} else {
bundleName = defaultBundleName;
}
return { ...newEntry, inject, bundleName };
});
}
export function getSourceMapDevTool(
scriptsSourceMap: boolean | undefined,
stylesSourceMap: boolean | undefined,
hiddenSourceMap = false,
inlineSourceMap = false,
): SourceMapDevToolPlugin {
const include = [];
if (scriptsSourceMap) {
include.push(/js$/);
}
if (stylesSourceMap) {
include.push(/css$/);
}
return new 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: 'webpack:///',
moduleFilenameTemplate: '[resource-path]',
append: hiddenSourceMap ? false : undefined,
});
}
/**
* Returns an ES version file suffix to differentiate between various builds.
*/
export function getEsVersionForFileName(
scriptTarget: ScriptTarget | undefined,
esVersionInFileName = false,
): string {
if (!esVersionInFileName || scriptTarget === undefined) {
return '';
}
if (scriptTarget === ScriptTarget.ESNext) {
return '-esnext';
}
return '-' + ScriptTarget[scriptTarget].toLowerCase();
}
export function isPolyfillsEntry(name: string): boolean {
return name === 'polyfills' || name === 'polyfills-es5';
}
export function getWatchOptions(poll: number | undefined): Options.WatchOptions {
return {
poll,
ignored: poll === undefined ? undefined : withWebpackFourOrFive(/[\\\/]node_modules[\\\/]/, 'node_modules/**'),
};
}
export function assetNameTemplateFactory(hashFormat: HashFormat): (resourcePath: string) => string {
const visitedFiles = new Map<string, string>();
return (resourcePath: string) => {
if (hashFormat.file) {
// File names are hashed therefore we don't need to handle files with the same file name.
return `[name]${hashFormat.file}.[ext]`;
}
const filename = path.basename(resourcePath);
// Check if the file with the same name has already been processed.
const visited = visitedFiles.get(filename);
if (!visited) {
// Not visited.
visitedFiles.set(filename, resourcePath);
return filename;
} else if (visited === resourcePath) {
// Same file.
return filename;
}
// File has the same name but it's in a different location.
return '[path][name].[ext]';
};
}