@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.
Files changed (139) hide show
  1. package/config/jest.config.ts +35 -0
  2. package/config/tsconfig.script.json +10 -0
  3. package/config/tsconfig.src.json +12 -0
  4. package/config/tsconfig.test.json +11 -0
  5. package/package.json +6 -8
  6. package/script/build.ts +65 -0
  7. package/script/format.ts +7 -0
  8. package/src/CanadyarnRunner.ts +35 -0
  9. package/src/CodeStyleChecker.ts +44 -0
  10. package/src/{Constant.js → Constant.ts} +1 -5
  11. package/src/CoreUtil.ts +24 -0
  12. package/src/ProjectStructureChecker.ts +119 -0
  13. package/src/TestRunner.ts +28 -0
  14. package/src/TypescriptTypeChecker.ts +29 -0
  15. package/src/{WebpackBuilder.js → WebpackBuilder.ts} +71 -51
  16. package/src/WebpackConfigGenerator/{ConfigEntryDescriptorsFactory.js → ConfigEntryDescriptorsFactory.ts} +36 -29
  17. package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.ts +24 -0
  18. package/src/WebpackConfigGenerator/Plugin/css.plugin.ts +31 -0
  19. package/src/WebpackConfigGenerator/Plugin/html.plugin.ts +47 -0
  20. package/src/WebpackConfigGenerator/Plugin/index.ts +33 -0
  21. package/src/WebpackConfigGenerator/Plugin/{moment.plugin.js → moment.plugin.ts} +5 -12
  22. package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.ts +22 -0
  23. package/src/WebpackConfigGenerator/Plugin/ts.plugin.ts +29 -0
  24. package/src/WebpackConfigGenerator/Plugin/webpack.plugin.ts +21 -0
  25. package/src/WebpackConfigGenerator/Rule/{RegExpUtil.js → RegExpUtil.ts} +8 -14
  26. package/src/WebpackConfigGenerator/Rule/{core-fe-hmr-babel-plugin.js → core-fe-hmr-babel-plugin.ts} +43 -9
  27. package/src/WebpackConfigGenerator/Rule/{image.rule.js → image.rule.ts} +5 -8
  28. package/src/WebpackConfigGenerator/Rule/index.ts +17 -0
  29. package/src/WebpackConfigGenerator/Rule/other.rule.ts +23 -0
  30. package/src/WebpackConfigGenerator/Rule/{stylesheet.rule.js → stylesheet.rule.ts} +34 -30
  31. package/src/WebpackConfigGenerator/Rule/{ts.rule.js → ts.rule.ts} +19 -17
  32. package/src/WebpackConfigGenerator/{WebpackConfigSerializationUtil.js → WebpackConfigSerializationUtil.ts} +23 -22
  33. package/src/WebpackConfigGenerator/WebpackEntryFactory.ts +22 -0
  34. package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.ts +22 -0
  35. package/src/WebpackConfigGenerator/{WebpackResolveAliasFactory.js → WebpackResolveAliasFactory.ts} +16 -13
  36. package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.ts +19 -0
  37. package/src/WebpackConfigGenerator/{WebpackResolveModulesFactory.js → WebpackResolveModulesFactory.ts} +9 -7
  38. package/src/WebpackConfigGenerator/index.ts +213 -0
  39. package/src/WebpackServerStarter.ts +138 -0
  40. package/src/index.ts +9 -0
  41. package/src/{type.d.ts → type.ts} +8 -4
  42. package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/__snapshots__/shouldIgnore.test.ts.snap +21 -0
  43. package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/__snapshots__/shouldTransform.test.ts.snap +53 -0
  44. package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/shouldIgnore.test.ts +36 -0
  45. package/test/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin/shouldTransform.test.ts +72 -0
  46. package/test/WebpackConfigGenerator/plugin/fixture/script.js +2 -0
  47. package/test/WebpackConfigGenerator/plugin/fixture/script1.js +1 -0
  48. package/test/WebpackConfigGenerator/plugin/script-tag-crossorigin-plugin.test.ts +58 -0
  49. package/test/test-project/package.json +5 -0
  50. package/tsconfig.json +15 -0
  51. package/src/CanadyarnRunner.d.ts +0 -14
  52. package/src/CanadyarnRunner.js +0 -38
  53. package/src/CanadyarnRunner.js.map +0 -1
  54. package/src/CodeStyleChecker.d.ts +0 -10
  55. package/src/CodeStyleChecker.js +0 -44
  56. package/src/CodeStyleChecker.js.map +0 -1
  57. package/src/Constant.d.ts +0 -21
  58. package/src/Constant.js.map +0 -1
  59. package/src/CoreUtil.d.ts +0 -11
  60. package/src/CoreUtil.js +0 -26
  61. package/src/CoreUtil.js.map +0 -1
  62. package/src/ProjectStructureChecker.d.ts +0 -18
  63. package/src/ProjectStructureChecker.js +0 -113
  64. package/src/ProjectStructureChecker.js.map +0 -1
  65. package/src/TestRunner.d.ts +0 -8
  66. package/src/TestRunner.js +0 -30
  67. package/src/TestRunner.js.map +0 -1
  68. package/src/TypescriptTypeChecker.d.ts +0 -8
  69. package/src/TypescriptTypeChecker.js +0 -25
  70. package/src/TypescriptTypeChecker.js.map +0 -1
  71. package/src/WebpackBuilder.d.ts +0 -38
  72. package/src/WebpackBuilder.js.map +0 -1
  73. package/src/WebpackConfigGenerator/ConfigEntryDescriptorsFactory.d.ts +0 -13
  74. package/src/WebpackConfigGenerator/ConfigEntryDescriptorsFactory.js.map +0 -1
  75. package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.d.ts +0 -9
  76. package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.js +0 -20
  77. package/src/WebpackConfigGenerator/HTMLWebpackPluginsFactory.js.map +0 -1
  78. package/src/WebpackConfigGenerator/Plugin/css.plugin.d.ts +0 -16
  79. package/src/WebpackConfigGenerator/Plugin/css.plugin.js +0 -33
  80. package/src/WebpackConfigGenerator/Plugin/css.plugin.js.map +0 -1
  81. package/src/WebpackConfigGenerator/Plugin/html.plugin.d.ts +0 -16
  82. package/src/WebpackConfigGenerator/Plugin/html.plugin.js +0 -48
  83. package/src/WebpackConfigGenerator/Plugin/html.plugin.js.map +0 -1
  84. package/src/WebpackConfigGenerator/Plugin/index.d.ts +0 -27
  85. package/src/WebpackConfigGenerator/Plugin/index.js +0 -32
  86. package/src/WebpackConfigGenerator/Plugin/index.js.map +0 -1
  87. package/src/WebpackConfigGenerator/Plugin/moment.plugin.d.ts +0 -10
  88. package/src/WebpackConfigGenerator/Plugin/moment.plugin.js.map +0 -1
  89. package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.d.ts +0 -4
  90. package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.js +0 -28
  91. package/src/WebpackConfigGenerator/Plugin/script-tag-crossorigin-plugin.js.map +0 -1
  92. package/src/WebpackConfigGenerator/Plugin/ts.plugin.d.ts +0 -16
  93. package/src/WebpackConfigGenerator/Plugin/ts.plugin.js +0 -31
  94. package/src/WebpackConfigGenerator/Plugin/ts.plugin.js.map +0 -1
  95. package/src/WebpackConfigGenerator/Plugin/webpack.plugin.d.ts +0 -14
  96. package/src/WebpackConfigGenerator/Plugin/webpack.plugin.js +0 -24
  97. package/src/WebpackConfigGenerator/Plugin/webpack.plugin.js.map +0 -1
  98. package/src/WebpackConfigGenerator/Rule/RegExpUtil.d.ts +0 -4
  99. package/src/WebpackConfigGenerator/Rule/RegExpUtil.js.map +0 -1
  100. package/src/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin.d.ts +0 -13
  101. package/src/WebpackConfigGenerator/Rule/core-fe-hmr-babel-plugin.js.map +0 -1
  102. package/src/WebpackConfigGenerator/Rule/image.rule.d.ts +0 -9
  103. package/src/WebpackConfigGenerator/Rule/image.rule.js.map +0 -1
  104. package/src/WebpackConfigGenerator/Rule/index.d.ts +0 -13
  105. package/src/WebpackConfigGenerator/Rule/index.js +0 -18
  106. package/src/WebpackConfigGenerator/Rule/index.js.map +0 -1
  107. package/src/WebpackConfigGenerator/Rule/other.rule.d.ts +0 -12
  108. package/src/WebpackConfigGenerator/Rule/other.rule.js +0 -22
  109. package/src/WebpackConfigGenerator/Rule/other.rule.js.map +0 -1
  110. package/src/WebpackConfigGenerator/Rule/stylesheet.rule.d.ts +0 -17
  111. package/src/WebpackConfigGenerator/Rule/stylesheet.rule.js.map +0 -1
  112. package/src/WebpackConfigGenerator/Rule/ts.rule.d.ts +0 -18
  113. package/src/WebpackConfigGenerator/Rule/ts.rule.js.map +0 -1
  114. package/src/WebpackConfigGenerator/WebpackConfigSerializationUtil.d.ts +0 -10
  115. package/src/WebpackConfigGenerator/WebpackConfigSerializationUtil.js.map +0 -1
  116. package/src/WebpackConfigGenerator/WebpackEntryFactory.d.ts +0 -9
  117. package/src/WebpackConfigGenerator/WebpackEntryFactory.js +0 -14
  118. package/src/WebpackConfigGenerator/WebpackEntryFactory.js.map +0 -1
  119. package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.d.ts +0 -11
  120. package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.js +0 -16
  121. package/src/WebpackConfigGenerator/WebpackOutputPublicURLFactory.js.map +0 -1
  122. package/src/WebpackConfigGenerator/WebpackResolveAliasFactory.d.ts +0 -11
  123. package/src/WebpackConfigGenerator/WebpackResolveAliasFactory.js.map +0 -1
  124. package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.d.ts +0 -7
  125. package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.js +0 -16
  126. package/src/WebpackConfigGenerator/WebpackResolveExtensionsFactory.js.map +0 -1
  127. package/src/WebpackConfigGenerator/WebpackResolveModulesFactory.d.ts +0 -7
  128. package/src/WebpackConfigGenerator/WebpackResolveModulesFactory.js.map +0 -1
  129. package/src/WebpackConfigGenerator/index.d.ts +0 -31
  130. package/src/WebpackConfigGenerator/index.js +0 -191
  131. package/src/WebpackConfigGenerator/index.js.map +0 -1
  132. package/src/WebpackServerStarter.d.ts +0 -28
  133. package/src/WebpackServerStarter.js +0 -111
  134. package/src/WebpackServerStarter.js.map +0 -1
  135. package/src/index.d.ts +0 -10
  136. package/src/index.js +0 -8
  137. package/src/index.js.map +0 -1
  138. package/src/type.js +0 -3
  139. package/src/type.js.map +0 -1
@@ -1,20 +1,21 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.WebpackBuilder = void 0;
7
- const devtool_util_1 = require("@pinnacle0/devtool-util");
8
- const fs_extra_1 = __importDefault(require("fs-extra"));
9
- const path_1 = __importDefault(require("path"));
10
- const webpack_1 = __importDefault(require("webpack"));
11
- const CoreUtil_1 = require("./CoreUtil");
12
- const WebpackConfigGenerator_1 = require("./WebpackConfigGenerator");
13
- const CanadyarnRunner_1 = require("./CanadyarnRunner");
14
- const ProjectStructureChecker_1 = require("./ProjectStructureChecker");
15
- const TypescriptTypeChecker_1 = require("./TypescriptTypeChecker");
16
- const TestRunner_1 = require("./TestRunner");
17
- const CodeStyleChecker_1 = require("./CodeStyleChecker");
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
- constructor(options) {
34
- var _a;
35
- this.logger = devtool_util_1.Utility.createConsoleLogger("WebpackBuilder");
36
- const webpackConfigGenerator = new WebpackConfigGenerator_1.WebpackConfigGenerator(options);
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 = (_a = options.extraCheckDirectories) !== null && _a !== void 0 ? _a : [];
40
- this.projectStaticDirectory = path_1.default.join(this.projectDirectory, "static");
41
- this.projectProfilingJSONOutputPath = path_1.default.join(this.projectDirectory, "profile.json");
42
- this.outputDirectory = path_1.default.join(this.projectDirectory, "build/dist");
43
- this.isFastMode = CoreUtil_1.CoreUtil.isFastMode();
44
- this.enableProfiling = CoreUtil_1.CoreUtil.profilingEnabled();
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 CanadyarnRunner_1.CanadyarnRunner({
66
+ new CanadyarnRunner({
51
67
  rootDirectory: this.rootDirectory,
52
68
  }).run();
53
- new ProjectStructureChecker_1.ProjectStructureChecker({
69
+ new ProjectStructureChecker({
54
70
  projectDirectory: this.projectDirectory,
55
71
  extraCheckDirectories: this.extraCheckDirectories,
56
72
  }).run();
57
- new TypescriptTypeChecker_1.TypescriptTypeChecker({
73
+ new TypescriptTypeChecker({
58
74
  projectDirectory: this.projectDirectory,
59
75
  extraCheckDirectories: this.extraCheckDirectories,
60
76
  }).run();
61
- new TestRunner_1.TestRunner({
77
+ new TestRunner({
62
78
  projectDirectory: this.projectDirectory,
63
79
  extraCheckDirectories: this.extraCheckDirectories,
64
80
  }).run();
65
- new CodeStyleChecker_1.CodeStyleChecker({
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
- cleanDistFolder() {
90
+
91
+ private cleanDistFolder() {
75
92
  this.logger.task("Cleaning build dist folder");
76
- fs_extra_1.default.emptyDirSync(this.outputDirectory);
93
+ fs.emptyDirSync(this.outputDirectory);
77
94
  }
78
- copyStatic() {
95
+
96
+ private copyStatic() {
79
97
  this.logger.task("Copying static assets to build dist folder");
80
- fs_extra_1.default.copySync(this.projectStaticDirectory, this.outputDirectory, { dereference: true });
98
+ fs.copySync(this.projectStaticDirectory, this.outputDirectory, {dereference: true});
81
99
  }
82
- bundleByWebpack() {
100
+
101
+ private bundleByWebpack() {
83
102
  this.logger.task("Starting webpack");
84
- (0, webpack_1.default)(this.webpackConfig).run((error, stats) => {
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
- fs_extra_1.default.writeFileSync(this.projectProfilingJSONOutputPath, JSON.stringify(statsJSON, null, 2), { encoding: "utf8" });
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
- getRawWarningsAndErrors(info) {
112
- const warnings = [];
113
- const errors = [];
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 { warnings, errors };
151
+ return {warnings, errors};
130
152
  }
131
153
  }
132
- exports.WebpackBuilder = WebpackBuilder;
133
- //# sourceMappingURL=WebpackBuilder.js.map
@@ -1,20 +1,24 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ConfigEntryDescriptorsFactory = void 0;
7
- const fs_1 = __importDefault(require("fs"));
8
- const path_1 = __importDefault(require("path"));
9
- const Constant_1 = require("../Constant");
10
- class ConfigEntryDescriptorsFactory {
11
- static generate({ indexName, projectSrcDirectory, extraEntries }) {
12
- const entryDescriptors = [];
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
- static createEntryDescriptor({ name, directory }) {
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: ${Constant_1.Constant.mainEntryFilenames.join("/")}`);
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 { name, entryPath, outputFilename };
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 { name, entryPath, outputFilename, htmlPath };
53
+ return {name, entryPath, outputFilename, htmlPath};
47
54
  }
48
55
  }
49
- static findEntryFilepath(searchDirectory) {
50
- if (!(fs_1.default.existsSync(searchDirectory) && fs_1.default.statSync(searchDirectory).isDirectory())) {
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 Constant_1.Constant.mainEntryFilenames) {
54
- const filepath = path_1.default.join(searchDirectory, filename);
55
- if (fs_1.default.existsSync(filepath) && fs_1.default.statSync(filepath).isFile()) {
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
- static findEntryHTMLFilepath(searchDirectory) {
62
- if (!(fs_1.default.existsSync(searchDirectory) && fs_1.default.statSync(searchDirectory).isDirectory())) {
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 = path_1.default.join(searchDirectory, "index.html");
66
- if (fs_1.default.existsSync(filepath) && fs_1.default.statSync(filepath).isFile()) {
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
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
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 WebpackConfigSerializationUtil_1.WebpackConfigSerializationUtil.serializablePlugin("webpack.IgnorePlugin", webpack_1.default.IgnorePlugin, {
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
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RegExpUtil = void 0;
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
- static validateFileExtension(ext) {
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