@pinnacle0/webpack-util 0.3.25 → 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 +2 -2
- 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} +18 -16
- 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 -11
- package/src/TypescriptTypeChecker.js +0 -32
- 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,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
|
package/src/WebpackConfigGenerator/Rule/{core-fe-hmr-babel-plugin.js → core-fe-hmr-babel-plugin.ts}
RENAMED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type * as babel from "@babel/core";
|
|
2
|
+
|
|
3
|
+
interface State extends Pick<babel.PluginPass, "file" | "key" | "opts" | "cwd" | "filename"> {
|
|
4
|
+
hasInjectedDeclineWebpackHMRNode: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
/**
|
|
4
8
|
* Injects `if (module.hot) module.hot.decline()` code snippet in files that contains "core-fe" Module classes.
|
|
5
9
|
*
|
|
@@ -7,39 +11,68 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
7
11
|
* otherwise react loses refrence of the MainComponent created by `ModuleProxy` in "core-fe"
|
|
8
12
|
* and throws a runtime error during development (which is bad for developer experience).
|
|
9
13
|
*/
|
|
10
|
-
function
|
|
14
|
+
export default function ({types: t}: typeof babel): babel.PluginObj<State> {
|
|
11
15
|
return {
|
|
12
16
|
visitor: {
|
|
13
17
|
ImportDeclaration(path, state) {
|
|
14
18
|
if (state.hasInjectedDeclineWebpackHMRNode) {
|
|
15
19
|
return;
|
|
16
20
|
}
|
|
17
|
-
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
node: {
|
|
24
|
+
source: {value: importSource},
|
|
25
|
+
specifiers: importSpecifiers,
|
|
26
|
+
},
|
|
27
|
+
} = path;
|
|
28
|
+
|
|
18
29
|
if (importSource !== "core-fe") {
|
|
19
30
|
return;
|
|
20
31
|
}
|
|
32
|
+
|
|
21
33
|
if (!hasImportSpecifierOfIdentifierModule(t, importSpecifiers)) {
|
|
22
34
|
return;
|
|
23
35
|
}
|
|
36
|
+
|
|
24
37
|
// We now know the TS/JS file has included `Module`, inject the code snippet
|
|
25
|
-
const programPath = path.findParent(parentPath => t.isProgram(parentPath.node))
|
|
38
|
+
const programPath = path.findParent(parentPath => t.isProgram(parentPath.node))! as babel.NodePath<babel.types.Program>;
|
|
39
|
+
|
|
26
40
|
// prettier-ignore
|
|
27
|
-
const declineWebpackHMRNode = t.ifStatement(
|
|
41
|
+
const declineWebpackHMRNode = t.ifStatement(
|
|
42
|
+
t.memberExpression(
|
|
43
|
+
t.identifier("module"),
|
|
44
|
+
t.identifier("hot")
|
|
45
|
+
),
|
|
46
|
+
t.expressionStatement(
|
|
47
|
+
t.callExpression(
|
|
48
|
+
t.memberExpression(
|
|
49
|
+
t.memberExpression(
|
|
50
|
+
t.identifier("module"),
|
|
51
|
+
t.identifier("hot"),
|
|
52
|
+
),
|
|
53
|
+
t.identifier("decline"),
|
|
54
|
+
),
|
|
55
|
+
[],
|
|
56
|
+
),
|
|
57
|
+
),
|
|
58
|
+
);
|
|
59
|
+
|
|
28
60
|
// Append `if (module.hot) module.hot.decline()` to end of program body
|
|
29
61
|
programPath.pushContainer("body", declineWebpackHMRNode);
|
|
62
|
+
|
|
30
63
|
// We only need to inject the code snippet once per file, mark as injected
|
|
31
64
|
state.hasInjectedDeclineWebpackHMRNode = true;
|
|
32
65
|
},
|
|
33
66
|
},
|
|
34
67
|
};
|
|
35
68
|
}
|
|
36
|
-
|
|
69
|
+
|
|
37
70
|
/**
|
|
38
71
|
* @param t `babel.types`
|
|
39
72
|
* @param importSpecifiers The "specifier" property of a `babel.types.ImportDeclaration` node
|
|
40
73
|
* @returns true if the import declaration includes the identifier `Module`
|
|
41
74
|
*/
|
|
42
|
-
function hasImportSpecifierOfIdentifierModule(t, importSpecifiers) {
|
|
75
|
+
function hasImportSpecifierOfIdentifierModule(t: typeof babel.types, importSpecifiers: babel.types.ImportDeclaration["specifiers"]): boolean {
|
|
43
76
|
const specifier = importSpecifiers.find(specifier => {
|
|
44
77
|
// Check if it is one of:
|
|
45
78
|
// -> `import { <IMPORT_SPECIFIER_NODE> } from "core-fe";`
|
|
@@ -48,6 +81,7 @@ function hasImportSpecifierOfIdentifierModule(t, importSpecifiers) {
|
|
|
48
81
|
const importedSpecifier = specifier.imported;
|
|
49
82
|
return t.isIdentifier(importedSpecifier) && importedSpecifier.name === "Module";
|
|
50
83
|
}
|
|
84
|
+
|
|
51
85
|
// Check if it is:
|
|
52
86
|
// -> `import * as <IMPORT_NAMESPACE_SPECIFIER_NODE> from "core-fe";`
|
|
53
87
|
if (t.isImportNamespaceSpecifier(specifier)) {
|
|
@@ -55,8 +89,8 @@ function hasImportSpecifierOfIdentifierModule(t, importSpecifiers) {
|
|
|
55
89
|
// Maybe enforce "core-fe" should not be imported with a namespace with an ESLint rule?
|
|
56
90
|
return true;
|
|
57
91
|
}
|
|
92
|
+
|
|
58
93
|
return false;
|
|
59
94
|
});
|
|
60
95
|
return specifier !== undefined;
|
|
61
96
|
}
|
|
62
|
-
//# sourceMappingURL=core-fe-hmr-babel-plugin.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const RegExpUtil_1 = require("./RegExpUtil");
|
|
1
|
+
import type webpack from "webpack";
|
|
2
|
+
import {RegExpUtil} from "./RegExpUtil";
|
|
3
|
+
|
|
5
4
|
/**
|
|
6
5
|
* Handles dependency requests to image assets (".png", ".jpeg", ".jpg", ".gif", ".svg")
|
|
7
6
|
* by inlining as images as DataURL,
|
|
@@ -9,9 +8,9 @@ const RegExpUtil_1 = require("./RegExpUtil");
|
|
|
9
8
|
*
|
|
10
9
|
* @see https://webpack.js.org/guides/asset-modules/
|
|
11
10
|
*/
|
|
12
|
-
function imageRule() {
|
|
11
|
+
export function imageRule(): webpack.RuleSetRule {
|
|
13
12
|
return {
|
|
14
|
-
test:
|
|
13
|
+
test: RegExpUtil.fileExtension(".png", ".jpeg", ".jpg", ".gif", ".svg"),
|
|
15
14
|
type: "asset",
|
|
16
15
|
generator: {
|
|
17
16
|
filename: "static/img/[name].[hash:8][ext][query]",
|
|
@@ -23,5 +22,3 @@ function imageRule() {
|
|
|
23
22
|
},
|
|
24
23
|
};
|
|
25
24
|
}
|
|
26
|
-
exports.imageRule = imageRule;
|
|
27
|
-
//# sourceMappingURL=image.rule.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {imageRule} from "./image.rule";
|
|
2
|
+
import {otherRule} from "./other.rule";
|
|
3
|
+
import {stylesheetRule} from "./stylesheet.rule";
|
|
4
|
+
import {tsRule} from "./ts.rule";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Static factories to create `webpack.config#modules.rules` items.
|
|
8
|
+
*/
|
|
9
|
+
export class Rule {
|
|
10
|
+
static readonly image = imageRule;
|
|
11
|
+
|
|
12
|
+
static readonly other = otherRule;
|
|
13
|
+
|
|
14
|
+
static readonly ts = tsRule;
|
|
15
|
+
|
|
16
|
+
static readonly stylesheet = stylesheetRule;
|
|
17
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type webpack from "webpack";
|
|
2
|
+
import {Constant} from "../../Constant";
|
|
3
|
+
import {RegExpUtil} from "./RegExpUtil";
|
|
4
|
+
|
|
5
|
+
interface OtherRuleDeps {
|
|
6
|
+
extraExtensionsForOtherRule: string[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Handles dependency requests to file assets
|
|
11
|
+
* by emitting as separate files.
|
|
12
|
+
*
|
|
13
|
+
* @see https://webpack.js.org/guides/asset-modules/
|
|
14
|
+
*/
|
|
15
|
+
export function otherRule({extraExtensionsForOtherRule}: OtherRuleDeps): webpack.RuleSetRule {
|
|
16
|
+
return {
|
|
17
|
+
test: RegExpUtil.fileExtension(".ico", ...Constant.mediaExtensions, ...Constant.fontExtensions, ...extraExtensionsForOtherRule),
|
|
18
|
+
type: "asset",
|
|
19
|
+
generator: {
|
|
20
|
+
filename: "static/other/[name].[hash:8][ext][query]",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
}
|