/
webpack-compiler.ts
118 lines (112 loc) · 3.63 KB
/
webpack-compiler.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
import { existsSync } from 'fs';
import { dirname, join, normalize, relative } from 'path';
import { Configuration } from '../configuration';
import { INFO_PREFIX } from '../ui';
import { AssetsManager } from './assets-manager';
import { webpackDefaultsFactory } from './defaults/webpack-defaults';
import { getValueOrDefault } from './helpers/get-value-or-default';
import { PluginsLoader } from './plugins-loader';
import webpack = require('webpack');
export class WebpackCompiler {
constructor(private readonly pluginsLoader: PluginsLoader) {}
public run(
configuration: Required<Configuration>,
webpackConfigFactoryOrConfig: (
config: webpack.Configuration,
webpackRef: typeof webpack,
) => webpack.Configuration,
tsConfigPath: string,
appName: string,
isDebugEnabled = false,
watchMode = false,
assetsManager: AssetsManager,
onSuccess?: () => void,
) {
const cwd = process.cwd();
const configPath = join(cwd, tsConfigPath!);
if (!existsSync(configPath)) {
throw new Error(
`Could not find TypeScript configuration file "${tsConfigPath!}".`,
);
}
const pluginsConfig = getValueOrDefault(
configuration,
'compilerOptions.plugins',
appName,
);
const plugins = this.pluginsLoader.load(pluginsConfig);
const relativeRootPath = dirname(relative(cwd, configPath));
const sourceRoot = getValueOrDefault<string>(
configuration,
'sourceRoot',
appName,
);
const pathToSource =
normalize(sourceRoot).indexOf(normalize(relativeRootPath)) >= 0
? join(cwd, sourceRoot)
: join(cwd, relativeRootPath, sourceRoot);
const entryFile = getValueOrDefault<string>(
configuration,
'entryFile',
appName,
);
const entryFileRoot =
getValueOrDefault<string>(configuration, 'root', appName) || '';
const defaultOptions = webpackDefaultsFactory(
pathToSource,
entryFileRoot,
entryFile,
isDebugEnabled,
tsConfigPath,
plugins,
);
const projectWebpackOptions =
typeof webpackConfigFactoryOrConfig !== 'function'
? webpackConfigFactoryOrConfig
: webpackConfigFactoryOrConfig(defaultOptions, webpack);
const webpackConfiguration = {
...defaultOptions,
mode: watchMode ? 'development' : defaultOptions.mode,
...projectWebpackOptions,
};
const compiler = webpack(webpackConfiguration);
const afterCallback = (
err: Error | undefined,
stats: webpack.Stats | undefined,
) => {
if (err && stats === undefined) {
// Could not complete the compilation
// The error caught is most likely thrown by underlying tasks
console.log(err);
return process.exit(1);
}
const statsOutput = stats!.toString({
chunks: false,
colors: true,
modules: false,
assets: false,
warningsFilter: /^(?!CriticalDependenciesWarning$)/,
});
if (!err && !stats!.hasErrors()) {
if (!onSuccess) {
assetsManager.closeWatchers();
} else {
onSuccess();
}
} else if (!watchMode && !webpackConfiguration.watch) {
console.log(statsOutput);
return process.exit(1);
}
console.log(statsOutput);
};
if (watchMode || webpackConfiguration.watch) {
compiler.hooks.watchRun.tapAsync('Rebuild info', (params, callback) => {
console.log(`\n${INFO_PREFIX} Webpack is building your sources...\n`);
callback();
});
compiler.watch(webpackConfiguration.watchOptions! || {}, afterCallback);
} else {
compiler.run(afterCallback);
}
}
}