@pinnacle0/webpack-util 0.3.23 → 0.3.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/jest.config.ts +35 -0
- package/config/tsconfig.script.json +10 -0
- package/config/tsconfig.src.json +12 -0
- package/config/tsconfig.test.json +11 -0
- package/package.json +6 -8
- package/script/build.ts +65 -0
- package/script/format.ts +7 -0
- package/src/CanadyarnRunner.ts +35 -0
- package/src/CodeStyleChecker.ts +44 -0
- package/src/{Constant.js → Constant.ts} +1 -5
- package/src/CoreUtil.ts +24 -0
- package/src/ProjectStructureChecker.ts +119 -0
- package/src/TestRunner.ts +28 -0
- package/src/TypescriptTypeChecker.ts +29 -0
- package/src/{WebpackBuilder.js → WebpackBuilder.ts} +71 -51
- package/src/WebpackConfigGenerator/{ConfigEntryDescriptorsFactory.js → ConfigEntryDescriptorsFactory.ts} +36 -29
- package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.ts +24 -0
- package/src/WebpackConfigGenerator/Plugin/css.plugin.ts +31 -0
- package/src/WebpackConfigGenerator/Plugin/html.plugin.ts +47 -0
- package/src/WebpackConfigGenerator/Plugin/index.ts +33 -0
- package/src/WebpackConfigGenerator/Plugin/{moment.plugin.js → moment.plugin.ts} +5 -12
- package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.ts +22 -0
- package/src/WebpackConfigGenerator/Plugin/ts.plugin.ts +29 -0
- package/src/WebpackConfigGenerator/Plugin/webpack.plugin.ts +21 -0
- package/src/WebpackConfigGenerator/Rule/{RegExpUtil.js → RegExpUtil.ts} +8 -14
- package/src/WebpackConfigGenerator/Rule/{core-fe-hmr-babel-plugin.js → core-fe-hmr-babel-plugin.ts} +43 -9
- package/src/WebpackConfigGenerator/Rule/{image.rule.js → image.rule.ts} +5 -8
- package/src/WebpackConfigGenerator/Rule/index.ts +17 -0
- package/src/WebpackConfigGenerator/Rule/other.rule.ts +23 -0
- package/src/WebpackConfigGenerator/Rule/{stylesheet.rule.js → stylesheet.rule.ts} +34 -30
- package/src/WebpackConfigGenerator/Rule/{ts.rule.js → ts.rule.ts} +19 -17
- package/src/WebpackConfigGenerator/{WebpackConfigSerializationUtil.js → WebpackConfigSerializationUtil.ts} +23 -22
- package/src/WebpackConfigGenerator/WebpackEntryFactory.ts +22 -0
- package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.ts +22 -0
- package/src/WebpackConfigGenerator/{WebpackResolveAliasFactory.js → WebpackResolveAliasFactory.ts} +16 -13
- package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.ts +19 -0
- package/src/WebpackConfigGenerator/{WebpackResolveModulesFactory.js → WebpackResolveModulesFactory.ts} +9 -7
- package/src/WebpackConfigGenerator/index.ts +213 -0
- package/src/WebpackServerStarter.ts +138 -0
- package/src/index.ts +9 -0
- package/src/{type.d.ts → type.ts} +8 -4
- package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/__snapshots__/shouldIgnore.test.ts.snap +21 -0
- package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/__snapshots__/shouldTransform.test.ts.snap +53 -0
- package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/shouldIgnore.test.ts +36 -0
- package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/shouldTransform.test.ts +72 -0
- package/test/WebpackConfigGenerator/plugin/fixture/script.js +2 -0
- package/test/WebpackConfigGenerator/plugin/fixture/script1.js +1 -0
- package/test/WebpackConfigGenerator/plugin/script-tag-crossorigin-plugin.test.ts +58 -0
- package/test/test-project/package.json +5 -0
- package/tsconfig.json +15 -0
- package/src/CanadyarnRunner.d.ts +0 -14
- package/src/CanadyarnRunner.js +0 -38
- package/src/CanadyarnRunner.js.map +0 -1
- package/src/CodeStyleChecker.d.ts +0 -10
- package/src/CodeStyleChecker.js +0 -44
- package/src/CodeStyleChecker.js.map +0 -1
- package/src/Constant.d.ts +0 -21
- package/src/Constant.js.map +0 -1
- package/src/CoreUtil.d.ts +0 -11
- package/src/CoreUtil.js +0 -26
- package/src/CoreUtil.js.map +0 -1
- package/src/ProjectStructureChecker.d.ts +0 -18
- package/src/ProjectStructureChecker.js +0 -113
- package/src/ProjectStructureChecker.js.map +0 -1
- package/src/TestRunner.d.ts +0 -8
- package/src/TestRunner.js +0 -30
- package/src/TestRunner.js.map +0 -1
- package/src/TypescriptTypeChecker.d.ts +0 -8
- package/src/TypescriptTypeChecker.js +0 -25
- package/src/TypescriptTypeChecker.js.map +0 -1
- package/src/WebpackBuilder.d.ts +0 -38
- package/src/WebpackBuilder.js.map +0 -1
- package/src/WebpackConfigGenerator/ConfigEntryDescriptorsFactory.d.ts +0 -13
- package/src/WebpackConfigGenerator/ConfigEntryDescriptorsFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.d.ts +0 -9
- package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.js +0 -20
- package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/css.plugin.d.ts +0 -16
- package/src/WebpackConfigGenerator/Plugin/css.plugin.js +0 -33
- package/src/WebpackConfigGenerator/Plugin/css.plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/html.plugin.d.ts +0 -16
- package/src/WebpackConfigGenerator/Plugin/html.plugin.js +0 -48
- package/src/WebpackConfigGenerator/Plugin/html.plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/index.d.ts +0 -27
- package/src/WebpackConfigGenerator/Plugin/index.js +0 -32
- package/src/WebpackConfigGenerator/Plugin/index.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/moment.plugin.d.ts +0 -10
- package/src/WebpackConfigGenerator/Plugin/moment.plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.d.ts +0 -4
- package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.js +0 -28
- package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/ts.plugin.d.ts +0 -16
- package/src/WebpackConfigGenerator/Plugin/ts.plugin.js +0 -31
- package/src/WebpackConfigGenerator/Plugin/ts.plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Plugin/webpack.plugin.d.ts +0 -14
- package/src/WebpackConfigGenerator/Plugin/webpack.plugin.js +0 -24
- package/src/WebpackConfigGenerator/Plugin/webpack.plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/RegExpUtil.d.ts +0 -4
- package/src/WebpackConfigGenerator/Rule/RegExpUtil.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin.d.ts +0 -13
- package/src/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/image.rule.d.ts +0 -9
- package/src/WebpackConfigGenerator/Rule/image.rule.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/index.d.ts +0 -13
- package/src/WebpackConfigGenerator/Rule/index.js +0 -18
- package/src/WebpackConfigGenerator/Rule/index.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/other.rule.d.ts +0 -12
- package/src/WebpackConfigGenerator/Rule/other.rule.js +0 -22
- package/src/WebpackConfigGenerator/Rule/other.rule.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/stylesheet.rule.d.ts +0 -17
- package/src/WebpackConfigGenerator/Rule/stylesheet.rule.js.map +0 -1
- package/src/WebpackConfigGenerator/Rule/ts.rule.d.ts +0 -18
- package/src/WebpackConfigGenerator/Rule/ts.rule.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackConfigSerializationUtil.d.ts +0 -10
- package/src/WebpackConfigGenerator/WebpackConfigSerializationUtil.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackEntryFactory.d.ts +0 -9
- package/src/WebpackConfigGenerator/WebpackEntryFactory.js +0 -14
- package/src/WebpackConfigGenerator/WebpackEntryFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.d.ts +0 -11
- package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.js +0 -16
- package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackResolveAliasFactory.d.ts +0 -11
- package/src/WebpackConfigGenerator/WebpackResolveAliasFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.d.ts +0 -7
- package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.js +0 -16
- package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/WebpackResolveModulesFactory.d.ts +0 -7
- package/src/WebpackConfigGenerator/WebpackResolveModulesFactory.js.map +0 -1
- package/src/WebpackConfigGenerator/index.d.ts +0 -31
- package/src/WebpackConfigGenerator/index.js +0 -191
- package/src/WebpackConfigGenerator/index.js.map +0 -1
- package/src/WebpackServerStarter.d.ts +0 -28
- package/src/WebpackServerStarter.js +0 -111
- package/src/WebpackServerStarter.js.map +0 -1
- package/src/index.d.ts +0 -10
- package/src/index.js +0 -8
- package/src/index.js.map +0 -1
- package/src/type.js +0 -3
- package/src/type.js.map +0 -1
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
import {Utility} from "@pinnacle0/devtool-util";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import webpack from "webpack";
|
|
5
|
+
import {CoreUtil} from "./CoreUtil";
|
|
6
|
+
import {WebpackConfigGenerator} from "./WebpackConfigGenerator";
|
|
7
|
+
import {CanadyarnRunner} from "./CanadyarnRunner";
|
|
8
|
+
import {ProjectStructureChecker} from "./ProjectStructureChecker";
|
|
9
|
+
import {TypescriptTypeChecker} from "./TypescriptTypeChecker";
|
|
10
|
+
import {TestRunner} from "./TestRunner";
|
|
11
|
+
import {CodeStyleChecker} from "./CodeStyleChecker";
|
|
12
|
+
import type {InternalCheckerOptions} from "./type";
|
|
13
|
+
import type {WebpackConfigGeneratorOptions} from "./WebpackConfigGenerator";
|
|
14
|
+
|
|
15
|
+
export interface WebpackBuilderOptions extends WebpackConfigGeneratorOptions, InternalCheckerOptions {
|
|
16
|
+
onSuccess?: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
18
19
|
/**
|
|
19
20
|
* Build the website by webpack.
|
|
20
21
|
*
|
|
@@ -29,40 +30,55 @@ const CodeStyleChecker_1 = require("./CodeStyleChecker");
|
|
|
29
30
|
*
|
|
30
31
|
* Add "--mode fast" to command line, if you want to skip style and lint checks.
|
|
31
32
|
*/
|
|
32
|
-
class WebpackBuilder {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
export class WebpackBuilder {
|
|
34
|
+
private readonly projectDirectory: string;
|
|
35
|
+
private readonly rootDirectory: string;
|
|
36
|
+
private readonly extraCheckDirectories: string[];
|
|
37
|
+
private readonly projectStaticDirectory: string;
|
|
38
|
+
private readonly projectProfilingJSONOutputPath: string;
|
|
39
|
+
private readonly outputDirectory: string;
|
|
40
|
+
private readonly webpackConfig: webpack.Configuration;
|
|
41
|
+
private readonly isFastMode: boolean;
|
|
42
|
+
private readonly enableProfiling: boolean;
|
|
43
|
+
private readonly onSuccess?: (() => void) | undefined;
|
|
44
|
+
|
|
45
|
+
private readonly logger = Utility.createConsoleLogger("WebpackBuilder");
|
|
46
|
+
|
|
47
|
+
constructor(options: WebpackBuilderOptions) {
|
|
48
|
+
const webpackConfigGenerator = new WebpackConfigGenerator(options);
|
|
49
|
+
|
|
37
50
|
this.projectDirectory = options.projectDirectory;
|
|
38
51
|
this.rootDirectory = options.rootDirectory ? options.rootDirectory : this.projectDirectory;
|
|
39
|
-
this.extraCheckDirectories =
|
|
40
|
-
this.projectStaticDirectory =
|
|
41
|
-
this.projectProfilingJSONOutputPath =
|
|
42
|
-
this.outputDirectory =
|
|
43
|
-
|
|
44
|
-
this.
|
|
52
|
+
this.extraCheckDirectories = options.extraCheckDirectories ?? [];
|
|
53
|
+
this.projectStaticDirectory = path.join(this.projectDirectory, "static");
|
|
54
|
+
this.projectProfilingJSONOutputPath = path.join(this.projectDirectory, "profile.json");
|
|
55
|
+
this.outputDirectory = path.join(this.projectDirectory, "build/dist");
|
|
56
|
+
|
|
57
|
+
this.isFastMode = CoreUtil.isFastMode();
|
|
58
|
+
this.enableProfiling = CoreUtil.profilingEnabled();
|
|
45
59
|
this.onSuccess = options.onSuccess;
|
|
60
|
+
|
|
46
61
|
this.webpackConfig = webpackConfigGenerator.production(this.outputDirectory);
|
|
47
62
|
}
|
|
63
|
+
|
|
48
64
|
run() {
|
|
49
65
|
if (!this.isFastMode) {
|
|
50
|
-
new
|
|
66
|
+
new CanadyarnRunner({
|
|
51
67
|
rootDirectory: this.rootDirectory,
|
|
52
68
|
}).run();
|
|
53
|
-
new
|
|
69
|
+
new ProjectStructureChecker({
|
|
54
70
|
projectDirectory: this.projectDirectory,
|
|
55
71
|
extraCheckDirectories: this.extraCheckDirectories,
|
|
56
72
|
}).run();
|
|
57
|
-
new
|
|
73
|
+
new TypescriptTypeChecker({
|
|
58
74
|
projectDirectory: this.projectDirectory,
|
|
59
75
|
extraCheckDirectories: this.extraCheckDirectories,
|
|
60
76
|
}).run();
|
|
61
|
-
new
|
|
77
|
+
new TestRunner({
|
|
62
78
|
projectDirectory: this.projectDirectory,
|
|
63
79
|
extraCheckDirectories: this.extraCheckDirectories,
|
|
64
80
|
}).run();
|
|
65
|
-
new
|
|
81
|
+
new CodeStyleChecker({
|
|
66
82
|
projectDirectory: this.projectDirectory,
|
|
67
83
|
extraCheckDirectories: this.extraCheckDirectories,
|
|
68
84
|
}).run();
|
|
@@ -71,46 +87,52 @@ class WebpackBuilder {
|
|
|
71
87
|
this.copyStatic();
|
|
72
88
|
this.bundleByWebpack();
|
|
73
89
|
}
|
|
74
|
-
|
|
90
|
+
|
|
91
|
+
private cleanDistFolder() {
|
|
75
92
|
this.logger.task("Cleaning build dist folder");
|
|
76
|
-
|
|
93
|
+
fs.emptyDirSync(this.outputDirectory);
|
|
77
94
|
}
|
|
78
|
-
|
|
95
|
+
|
|
96
|
+
private copyStatic() {
|
|
79
97
|
this.logger.task("Copying static assets to build dist folder");
|
|
80
|
-
|
|
98
|
+
fs.copySync(this.projectStaticDirectory, this.outputDirectory, {dereference: true});
|
|
81
99
|
}
|
|
82
|
-
|
|
100
|
+
|
|
101
|
+
private bundleByWebpack() {
|
|
83
102
|
this.logger.task("Starting webpack");
|
|
84
|
-
|
|
103
|
+
|
|
104
|
+
webpack(this.webpackConfig).run((error?: Error | null, stats?: webpack.Stats) => {
|
|
85
105
|
if (error) {
|
|
86
106
|
throw error;
|
|
87
|
-
}
|
|
88
|
-
else if (stats) {
|
|
107
|
+
} else if (stats) {
|
|
89
108
|
const statsJSON = stats.toJson();
|
|
90
109
|
if (this.enableProfiling) {
|
|
91
110
|
this.logger.task(["Generating profile for analysis", this.projectProfilingJSONOutputPath]);
|
|
92
|
-
|
|
111
|
+
fs.writeFileSync(this.projectProfilingJSONOutputPath, JSON.stringify(statsJSON, null, 2), {encoding: "utf8"});
|
|
93
112
|
}
|
|
113
|
+
|
|
94
114
|
if (stats.hasErrors() || stats.hasWarnings()) {
|
|
95
115
|
this.logger.error("Webpack compiled with the following errors/warnings:");
|
|
96
116
|
console.error(stats.toString("errors-warnings"));
|
|
97
117
|
process.exit(1);
|
|
98
118
|
}
|
|
119
|
+
|
|
99
120
|
this.logger.info("Build successfully");
|
|
121
|
+
|
|
100
122
|
if (this.onSuccess) {
|
|
101
123
|
this.logger.info("Running onSuccess callback");
|
|
102
124
|
this.onSuccess();
|
|
103
125
|
}
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
126
|
+
} else {
|
|
106
127
|
this.logger.error("Webpack compiler `run()` returns no `error` and no `stats`, this is unexpected.");
|
|
107
128
|
process.exit(1);
|
|
108
129
|
}
|
|
109
130
|
});
|
|
110
131
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
132
|
+
|
|
133
|
+
private getRawWarningsAndErrors(info: any): {warnings: any[]; errors: any[]} {
|
|
134
|
+
const warnings: any[] = [];
|
|
135
|
+
const errors: any[] = [];
|
|
114
136
|
if (typeof info === "object" && info !== null) {
|
|
115
137
|
if (Array.isArray(info.warnings)) {
|
|
116
138
|
warnings.push(...info.warnings);
|
|
@@ -119,15 +141,13 @@ class WebpackBuilder {
|
|
|
119
141
|
errors.push(...info.errors);
|
|
120
142
|
}
|
|
121
143
|
if (Array.isArray(info.children)) {
|
|
122
|
-
info.children.forEach((_) => {
|
|
144
|
+
info.children.forEach((_: any) => {
|
|
123
145
|
const childInfo = this.getRawWarningsAndErrors(_);
|
|
124
146
|
warnings.push(...childInfo.warnings);
|
|
125
147
|
errors.push(...childInfo.errors);
|
|
126
148
|
});
|
|
127
149
|
}
|
|
128
150
|
}
|
|
129
|
-
return {
|
|
151
|
+
return {warnings, errors};
|
|
130
152
|
}
|
|
131
153
|
}
|
|
132
|
-
exports.WebpackBuilder = WebpackBuilder;
|
|
133
|
-
//# sourceMappingURL=WebpackBuilder.js.map
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import {Constant} from "../Constant";
|
|
4
|
+
import type {EntryDescriptor} from "../type";
|
|
5
|
+
|
|
6
|
+
interface ConfigEntryDescriptorsFactoryOptions {
|
|
7
|
+
indexName: string;
|
|
8
|
+
projectSrcDirectory: string;
|
|
9
|
+
extraEntries: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class ConfigEntryDescriptorsFactory {
|
|
13
|
+
static generate({indexName, projectSrcDirectory, extraEntries}: ConfigEntryDescriptorsFactoryOptions): EntryDescriptor[] {
|
|
14
|
+
const entryDescriptors: EntryDescriptor[] = [];
|
|
15
|
+
|
|
13
16
|
const mainEntryDescriptor = ConfigEntryDescriptorsFactory.createEntryDescriptor({
|
|
14
17
|
name: indexName,
|
|
15
18
|
directory: projectSrcDirectory,
|
|
16
19
|
});
|
|
17
20
|
entryDescriptors.push(mainEntryDescriptor);
|
|
21
|
+
|
|
18
22
|
for (const [extraEntryName, extraEntryDirectory] of Object.entries(extraEntries)) {
|
|
19
23
|
const extraEntryDescriptor = ConfigEntryDescriptorsFactory.createEntryDescriptor({
|
|
20
24
|
name: extraEntryName,
|
|
@@ -22,52 +26,55 @@ class ConfigEntryDescriptorsFactory {
|
|
|
22
26
|
});
|
|
23
27
|
entryDescriptors.push(extraEntryDescriptor);
|
|
24
28
|
}
|
|
29
|
+
|
|
25
30
|
return entryDescriptors;
|
|
26
31
|
}
|
|
27
|
-
|
|
32
|
+
|
|
33
|
+
private static createEntryDescriptor({name, directory}: {name: string; directory: string}): EntryDescriptor {
|
|
28
34
|
const entryPath = ConfigEntryDescriptorsFactory.findEntryFilepath(directory);
|
|
29
35
|
const htmlPath = ConfigEntryDescriptorsFactory.findEntryHTMLFilepath(directory);
|
|
36
|
+
|
|
30
37
|
if (entryPath === null) {
|
|
31
|
-
throw new Error(`Cannot find entry file for "${name}" in "${directory}", files checked: ${
|
|
38
|
+
throw new Error(`Cannot find entry file for "${name}" in "${directory}", files checked: ${Constant.mainEntryFilenames.join("/")}`);
|
|
32
39
|
}
|
|
40
|
+
|
|
33
41
|
if (htmlPath === null) {
|
|
34
42
|
// Output is a pure js entry (without a companion `index.html` template file)
|
|
35
43
|
// Do not include a hash in the output filenames.
|
|
36
44
|
// One particular use case for this is create a "third-party-error-handler" pure js entry,
|
|
37
45
|
// so this static filename can be hard coded at our backend.
|
|
38
46
|
const outputFilename = "static/js/[name].js";
|
|
39
|
-
return {
|
|
40
|
-
}
|
|
41
|
-
else {
|
|
47
|
+
return {name, entryPath, outputFilename};
|
|
48
|
+
} else {
|
|
42
49
|
// Output is an html entry (with a companion `index.html` template file)
|
|
43
50
|
// We might want to include a hash to the output filenames
|
|
44
51
|
// (don't set the output filename to contain hash for profiling build).
|
|
45
52
|
const outputFilename = "static/js/[chunkhash:8].js";
|
|
46
|
-
return {
|
|
53
|
+
return {name, entryPath, outputFilename, htmlPath};
|
|
47
54
|
}
|
|
48
55
|
}
|
|
49
|
-
|
|
50
|
-
|
|
56
|
+
|
|
57
|
+
private static findEntryFilepath(searchDirectory: string): string | null {
|
|
58
|
+
if (!(fs.existsSync(searchDirectory) && fs.statSync(searchDirectory).isDirectory())) {
|
|
51
59
|
return null;
|
|
52
60
|
}
|
|
53
|
-
for (const filename of
|
|
54
|
-
const filepath =
|
|
55
|
-
if (
|
|
61
|
+
for (const filename of Constant.mainEntryFilenames) {
|
|
62
|
+
const filepath = path.join(searchDirectory, filename);
|
|
63
|
+
if (fs.existsSync(filepath) && fs.statSync(filepath).isFile()) {
|
|
56
64
|
return filepath;
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
return null;
|
|
60
68
|
}
|
|
61
|
-
|
|
62
|
-
|
|
69
|
+
|
|
70
|
+
private static findEntryHTMLFilepath(searchDirectory: string): string | null {
|
|
71
|
+
if (!(fs.existsSync(searchDirectory) && fs.statSync(searchDirectory).isDirectory())) {
|
|
63
72
|
return null;
|
|
64
73
|
}
|
|
65
|
-
const filepath =
|
|
66
|
-
if (
|
|
74
|
+
const filepath = path.join(searchDirectory, "index.html");
|
|
75
|
+
if (fs.existsSync(filepath) && fs.statSync(filepath).isFile()) {
|
|
67
76
|
return filepath;
|
|
68
77
|
}
|
|
69
78
|
return null;
|
|
70
79
|
}
|
|
71
80
|
}
|
|
72
|
-
exports.ConfigEntryDescriptorsFactory = ConfigEntryDescriptorsFactory;
|
|
73
|
-
//# sourceMappingURL=ConfigEntryDescriptorsFactory.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type webpack from "webpack";
|
|
2
|
+
import type {EntryDescriptor} from "../type";
|
|
3
|
+
import {Plugin} from "./Plugin";
|
|
4
|
+
|
|
5
|
+
interface HTMLWebpackPluginsFactoryOptions {
|
|
6
|
+
configEntryDescriptors: EntryDescriptor[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class HTMLWebpackPluginsFactory {
|
|
10
|
+
static generate({configEntryDescriptors}: HTMLWebpackPluginsFactoryOptions): webpack.Plugin[] {
|
|
11
|
+
const htmlPlugins: webpack.Plugin[] = [];
|
|
12
|
+
|
|
13
|
+
for (const {name, entryPath, htmlPath} of configEntryDescriptors) {
|
|
14
|
+
if (htmlPath !== undefined) {
|
|
15
|
+
const plugin = Plugin.fileOutput.html({
|
|
16
|
+
entry: {name, entryPath, htmlPath},
|
|
17
|
+
});
|
|
18
|
+
htmlPlugins.push(plugin);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return htmlPlugins;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
|
2
|
+
import CssMinimizerWebpackPlugin from "css-minimizer-webpack-plugin";
|
|
3
|
+
import type webpack from "webpack";
|
|
4
|
+
import {WebpackConfigSerializationUtil} from "../WebpackConfigSerializationUtil";
|
|
5
|
+
|
|
6
|
+
interface ExtractCssPluginOptions {
|
|
7
|
+
enableProfiling: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Applies CssNano to minimize stylesheets
|
|
12
|
+
* after bundles/chunks are built.
|
|
13
|
+
*/
|
|
14
|
+
export function cssMinimizerPlugin(): webpack.WebpackPluginInstance {
|
|
15
|
+
return WebpackConfigSerializationUtil.serializablePlugin("CssMinimizerWebpackPlugin", CssMinimizerWebpackPlugin);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extract output of css transformation pipeline to standalone css files.
|
|
20
|
+
* Must be used with `MiniCssExtractPlugin.loader`, which is included with
|
|
21
|
+
* `Rule.stylesheet({minimize: true})`.
|
|
22
|
+
*/
|
|
23
|
+
export function miniCssExtractPlugin({enableProfiling}: ExtractCssPluginOptions): webpack.WebpackPluginInstance {
|
|
24
|
+
return WebpackConfigSerializationUtil.serializablePlugin("MiniCssExtractPlugin", MiniCssExtractPlugin, {
|
|
25
|
+
filename: enableProfiling ? "static/css/[name].[contenthash:8].css" : "static/css/[contenthash:8].css",
|
|
26
|
+
// order of css output depends on the order of imports in js,
|
|
27
|
+
// unless all imports in js are sorted (e.g. by alphabetical order),
|
|
28
|
+
// this flag must be set to true to avoid error
|
|
29
|
+
ignoreOrder: true,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import HTMLWebpackPlugin from "html-webpack-plugin";
|
|
2
|
+
import {ScriptTagCrossOriginPlugin} from "./script-tag-crossorigin-plugin";
|
|
3
|
+
import type webpack from "webpack";
|
|
4
|
+
import type {HTMLEntryDescriptor} from "../../type";
|
|
5
|
+
import {WebpackConfigSerializationUtil} from "../WebpackConfigSerializationUtil";
|
|
6
|
+
|
|
7
|
+
interface HTMLPluginOptions {
|
|
8
|
+
entry: HTMLEntryDescriptor;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Creates a html file from a template with <script> and <link> injected
|
|
13
|
+
* with the respective hashed output filenames.
|
|
14
|
+
*/
|
|
15
|
+
export function htmlPlugin({entry}: HTMLPluginOptions): webpack.WebpackPluginInstance {
|
|
16
|
+
return WebpackConfigSerializationUtil.serializablePlugin("HTMLWebpackPlugin", HTMLWebpackPlugin, {
|
|
17
|
+
template: entry.htmlPath,
|
|
18
|
+
filename: `${entry.name}.html`,
|
|
19
|
+
chunks: [entry.name],
|
|
20
|
+
minify: {
|
|
21
|
+
collapseBooleanAttributes: true,
|
|
22
|
+
collapseInlineTagWhitespace: true,
|
|
23
|
+
collapseWhitespace: true,
|
|
24
|
+
includeAutoGeneratedTags: false,
|
|
25
|
+
keepClosingSlash: true,
|
|
26
|
+
minifyCSS: true,
|
|
27
|
+
minifyJS: true,
|
|
28
|
+
minifyURLs: true,
|
|
29
|
+
removeAttributeQuotes: true,
|
|
30
|
+
removeComments: true,
|
|
31
|
+
removeEmptyAttributes: true,
|
|
32
|
+
removeRedundantAttributes: true,
|
|
33
|
+
removeScriptTypeAttributes: true,
|
|
34
|
+
removeStyleLinkTypeAttributes: true,
|
|
35
|
+
removeTagWhitespace: true,
|
|
36
|
+
useShortDoctype: true,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Adds attributes to `<script>` tag inside html file generated by
|
|
43
|
+
* HTMLWebpackPlugin. Used to add `crossorigin="anonymous"`.
|
|
44
|
+
*/
|
|
45
|
+
export function scriptTagCrossOriginPlugin(): webpack.WebpackPluginInstance {
|
|
46
|
+
return WebpackConfigSerializationUtil.serializablePlugin("ScriptTagCrossOriginPlugin", ScriptTagCrossOriginPlugin);
|
|
47
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {cssMinimizerPlugin, miniCssExtractPlugin} from "./css.plugin";
|
|
2
|
+
import {scriptTagCrossOriginPlugin, htmlPlugin} from "./html.plugin";
|
|
3
|
+
import {ignoreMomentLocalePlugin} from "./moment.plugin";
|
|
4
|
+
import {reactRefreshPlugin, terserPlugin} from "./ts.plugin";
|
|
5
|
+
import {webpackDefinePlugin, webpackProgressPlugin} from "./webpack.plugin";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Static factories to create \`webpack.config#plugins\` items.
|
|
9
|
+
*
|
|
10
|
+
* Plugins with similar functionality are grouped under a js object (as a namespace).
|
|
11
|
+
*/
|
|
12
|
+
export class Plugin {
|
|
13
|
+
static readonly scriptTagCrossOriginPlugin = scriptTagCrossOriginPlugin;
|
|
14
|
+
|
|
15
|
+
static readonly ignoreMomentLocale = ignoreMomentLocalePlugin;
|
|
16
|
+
|
|
17
|
+
static readonly reactRefresh = reactRefreshPlugin;
|
|
18
|
+
|
|
19
|
+
static readonly fileOutput = {
|
|
20
|
+
html: htmlPlugin,
|
|
21
|
+
miniCssExtract: miniCssExtractPlugin,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
static readonly minimizer = {
|
|
25
|
+
terser: terserPlugin,
|
|
26
|
+
css: cssMinimizerPlugin,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
static readonly webpack = {
|
|
30
|
+
progress: webpackProgressPlugin,
|
|
31
|
+
define: webpackDefinePlugin,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.ignoreMomentLocalePlugin = void 0;
|
|
7
|
-
const webpack_1 = __importDefault(require("webpack"));
|
|
8
|
-
const WebpackConfigSerializationUtil_1 = require("../WebpackConfigSerializationUtil");
|
|
1
|
+
import webpack from "webpack";
|
|
2
|
+
import {WebpackConfigSerializationUtil} from "../WebpackConfigSerializationUtil";
|
|
3
|
+
|
|
9
4
|
/**
|
|
10
5
|
* Prevents moment locales from being bundled by importing moment
|
|
11
6
|
* (moment by default imports all locales)
|
|
@@ -14,8 +9,8 @@ const WebpackConfigSerializationUtil_1 = require("../WebpackConfigSerializationU
|
|
|
14
9
|
* To include a locale, it must be explicitly imported
|
|
15
10
|
* (preferably at the entry file).
|
|
16
11
|
*/
|
|
17
|
-
function ignoreMomentLocalePlugin() {
|
|
18
|
-
return
|
|
12
|
+
export function ignoreMomentLocalePlugin(): webpack.WebpackPluginInstance {
|
|
13
|
+
return WebpackConfigSerializationUtil.serializablePlugin("webpack.IgnorePlugin", webpack.IgnorePlugin, {
|
|
19
14
|
// check dependency-request against the provided regex,
|
|
20
15
|
// and exclude resource from final bundle if matched;
|
|
21
16
|
// e.g. `/^\.\/locale$/` matches the dependency-request `require("./locale/" + name)`
|
|
@@ -25,5 +20,3 @@ function ignoreMomentLocalePlugin() {
|
|
|
25
20
|
contextRegExp: /moment$/,
|
|
26
21
|
});
|
|
27
22
|
}
|
|
28
|
-
exports.ignoreMomentLocalePlugin = ignoreMomentLocalePlugin;
|
|
29
|
-
//# sourceMappingURL=moment.plugin.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
2
|
+
import type webpack from "webpack";
|
|
3
|
+
|
|
4
|
+
const PLUGIN_NAME = "ScriptTagCrossOriginPlugin";
|
|
5
|
+
|
|
6
|
+
// This plugin adds crossorigin="anonymous" to html-webpack-plugin generated <script> tags, only work with html-webpack-plugin@4.0.0+
|
|
7
|
+
export class ScriptTagCrossOriginPlugin implements webpack.WebpackPluginInstance {
|
|
8
|
+
apply(compiler: webpack.Compiler): void {
|
|
9
|
+
compiler.hooks.compilation.tap(PLUGIN_NAME, compilation => {
|
|
10
|
+
const hook = HtmlWebpackPlugin.getHooks(compilation).alterAssetTags;
|
|
11
|
+
hook.tap(PLUGIN_NAME, result => {
|
|
12
|
+
const {assetTags} = result;
|
|
13
|
+
for (const scriptTag of assetTags.scripts) {
|
|
14
|
+
if (scriptTag.attributes?.src && /.js$/.test(scriptTag.attributes.src.toString())) {
|
|
15
|
+
scriptTag.attributes.crossorigin = "anonymous";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import ReactRefreshWebpackPlugin from "@pmmmwh/react-refresh-webpack-plugin";
|
|
2
|
+
import TerserWebpackPlugin from "terser-webpack-plugin";
|
|
3
|
+
import type webpack from "webpack";
|
|
4
|
+
import {WebpackConfigSerializationUtil} from "../WebpackConfigSerializationUtil";
|
|
5
|
+
|
|
6
|
+
interface TerserPluginOptions {
|
|
7
|
+
sourceMap: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Applies Terser to minimize javascript
|
|
12
|
+
* after bundles/chunks are built.
|
|
13
|
+
*/
|
|
14
|
+
export function terserPlugin({sourceMap}: TerserPluginOptions): webpack.WebpackPluginInstance {
|
|
15
|
+
return WebpackConfigSerializationUtil.serializablePlugin("TerserWebpackPlugin", TerserWebpackPlugin, {
|
|
16
|
+
terserOptions: {
|
|
17
|
+
sourceMap,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Adds react fast refresh functionality.
|
|
24
|
+
* Requires babel plugin "react-refresh/babel".
|
|
25
|
+
* Should not be used in production.
|
|
26
|
+
*/
|
|
27
|
+
export function reactRefreshPlugin(): webpack.WebpackPluginInstance {
|
|
28
|
+
return WebpackConfigSerializationUtil.serializablePlugin("ReactRefreshPlugin", ReactRefreshWebpackPlugin);
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import webpack from "webpack";
|
|
2
|
+
import {WebpackConfigSerializationUtil} from "../WebpackConfigSerializationUtil";
|
|
3
|
+
|
|
4
|
+
interface WebpackProgressPluginOptions {
|
|
5
|
+
enableProfiling: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Reports progress during compilation.
|
|
10
|
+
* Basically the same behavior as running webpack-cli with:
|
|
11
|
+
* `$ webpack --progress`
|
|
12
|
+
*/
|
|
13
|
+
export function webpackProgressPlugin({enableProfiling}: WebpackProgressPluginOptions): webpack.WebpackPluginInstance {
|
|
14
|
+
return WebpackConfigSerializationUtil.serializablePlugin("webpack.ProgressPlugin", webpack.ProgressPlugin, {
|
|
15
|
+
profile: enableProfiling,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function webpackDefinePlugin(map: {[key: string]: string}): webpack.WebpackPluginInstance {
|
|
20
|
+
return WebpackConfigSerializationUtil.serializablePlugin("webpack.DefinePlugin", webpack.DefinePlugin, map);
|
|
21
|
+
}
|
|
@@ -1,26 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class RegExpUtil {
|
|
5
|
-
static fileExtension(...extensions) {
|
|
6
|
-
const escapedExtensions = [];
|
|
1
|
+
export class RegExpUtil {
|
|
2
|
+
static fileExtension(...extensions: [string, ...string[]]): RegExp {
|
|
3
|
+
const escapedExtensions: string[] = [];
|
|
7
4
|
for (const ext of extensions) {
|
|
8
5
|
RegExpUtil.validateFileExtension(ext);
|
|
9
|
-
escapedExtensions.push(ext.replace(/\./g, String.raw
|
|
6
|
+
escapedExtensions.push(ext.replace(/\./g, String.raw`\.`));
|
|
10
7
|
}
|
|
11
8
|
return new RegExp(`(${escapedExtensions.join("|")})$`);
|
|
12
9
|
}
|
|
13
|
-
|
|
10
|
+
|
|
11
|
+
private static validateFileExtension(ext: string): void {
|
|
14
12
|
if (ext.trim() === "") {
|
|
15
13
|
throw new Error("Extension cannot be empty.");
|
|
16
|
-
}
|
|
17
|
-
else if (/\s/.test(ext)) {
|
|
14
|
+
} else if (/\s/.test(ext)) {
|
|
18
15
|
throw new Error(`Extension cannot contain whitespace, received: "${ext}".`);
|
|
19
|
-
}
|
|
20
|
-
else if (!/^(\.[a-z0-9]+)+$/.test(ext)) {
|
|
16
|
+
} else if (!/^(\.[a-z0-9]+)+$/.test(ext)) {
|
|
21
17
|
throw new Error(`Extension should begin with dot, and contains lowercase letters and numbers, received: "${ext}".`);
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
}
|
|
25
|
-
exports.RegExpUtil = RegExpUtil;
|
|
26
|
-
//# sourceMappingURL=RegExpUtil.js.map
|