@omnific/react-scripts 0.1.0 → 0.1.1

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.
@@ -0,0 +1,195 @@
1
+ import { t as paths_default } from "./paths-BvJwGeTv.js";
2
+ import { styleText } from "node:util";
3
+ import fs from "node:fs/promises";
4
+ import { exit } from "node:process";
5
+ import { rspack } from "@rspack/core";
6
+ import path from "node:path";
7
+ import fs$1 from "node:fs";
8
+ import prettyBytes from "pretty-bytes";
9
+ import zlib from "node:zlib";
10
+ //#region utils/fs-extra.ts
11
+ async function emptyDirectory(directory) {
12
+ await fs.rm(directory, {
13
+ recursive: true,
14
+ force: true
15
+ });
16
+ await fs.mkdir(directory, { recursive: true });
17
+ }
18
+ /**
19
+ * 读取文件夹下的所有文件
20
+ * @param path
21
+ * @returns
22
+ */
23
+ async function readdir(path$1) {
24
+ let fileList = [];
25
+ const files = await fs.readdir(path$1);
26
+ if (files.length === 0) return [];
27
+ for (const file of files) {
28
+ const filePath = path.join(path$1, file);
29
+ if ((await fs.stat(filePath)).isDirectory()) fileList = [...fileList, ...await readdir(filePath)];
30
+ else fileList.push(filePath);
31
+ }
32
+ return fileList;
33
+ }
34
+ //#endregion
35
+ //#region utils/gzip-size.ts
36
+ function getOptions(options) {
37
+ return {
38
+ level: 9,
39
+ ...options
40
+ };
41
+ }
42
+ function gzipSync(input, options) {
43
+ return zlib.gzipSync(input, getOptions(options)).length;
44
+ }
45
+ //#endregion
46
+ //#region utils/strip-ansi.ts
47
+ function ansiRegex(options = {}) {
48
+ const { onlyFirst } = options;
49
+ const pattern = [String.raw`[\u001B\u009B][[\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\d\/#&.:=?%@~_]+)*|[a-zA-Z\d]+(?:;[-a-zA-Z\d\/#&.:=?%@~_]*)*)?\u0007)`, String.raw`(?:(?:\d{1,4}(?:;\d{0,4})*)?[\dA-PR-TZcf-nq-uy=><~]))`].join("|");
50
+ return new RegExp(pattern, onlyFirst ? void 0 : "g");
51
+ }
52
+ function stripAnsi(string) {
53
+ const regex = ansiRegex();
54
+ return string.replace(regex, "");
55
+ }
56
+ //#endregion
57
+ //#region utils/file-size-reporter.ts
58
+ const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024;
59
+ const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
60
+ /**
61
+ * 是不是可以读取的资源
62
+ * @param asset
63
+ * @returns
64
+ */
65
+ function canReadAsset(asset) {
66
+ return /\.(js|css)$/.test(asset) && !/service-worker\.js/.test(asset) && !/precache-manifest\.[\da-f]+\.js/.test(asset);
67
+ }
68
+ function removeFileNameHash(buildFolder, fileName) {
69
+ return fileName.replace(buildFolder, "").replaceAll("\\", "/").replace(/\/?(.*)(\.[\da-f]+)(\.chunk)?(\.js|\.css)/, (match, p1, p2, p3, p4) => p1 + p4);
70
+ }
71
+ async function measureFileSizesBeforeBuild(buildFolder) {
72
+ const result = {
73
+ root: buildFolder,
74
+ sizes: {}
75
+ };
76
+ try {
77
+ const files = await readdir(buildFolder);
78
+ if (Array.isArray(files) && files.length > 0) {
79
+ const canReadAssetFiles = files.filter((item) => canReadAsset(item));
80
+ for (const fileName of canReadAssetFiles) {
81
+ const stats = fs$1.statSync(fileName);
82
+ const fileKey = removeFileNameHash(buildFolder, fileName);
83
+ result.sizes[fileKey] = stats.size;
84
+ }
85
+ }
86
+ } catch {
87
+ return result;
88
+ }
89
+ return result;
90
+ }
91
+ function getDifferenceLabel(currentSize, previousSize) {
92
+ const FIFTY_KILOBYTES = 1024 * 50;
93
+ const difference = currentSize - previousSize;
94
+ const fileSize = Number.isNaN(difference) ? "0" : prettyBytes(difference);
95
+ if (difference >= FIFTY_KILOBYTES) return styleText("red", "+" + fileSize);
96
+ else if (difference < FIFTY_KILOBYTES && difference > 0) return styleText("yellow", "+" + fileSize);
97
+ else if (difference < 0) return styleText("green", fileSize);
98
+ else return "";
99
+ }
100
+ function printFileSizesAfterBuild(stats, previousSizeMap) {
101
+ let suggestBundleSplitting = false;
102
+ const root = previousSizeMap.root;
103
+ const sizes = previousSizeMap.sizes;
104
+ const statCompilation = stats.toJson({
105
+ all: false,
106
+ assets: true
107
+ });
108
+ if (statCompilation.assets) {
109
+ const assets = [];
110
+ const gzipLabelLengthList = [];
111
+ const sizeLabelLengthList = [];
112
+ for (const asset of statCompilation.assets) {
113
+ if (!canReadAsset(asset.name)) continue;
114
+ const fileContents = fs$1.readFileSync(path.join(root, asset.name));
115
+ const previousSize = sizes[removeFileNameHash(root, asset.name)];
116
+ const difference = getDifferenceLabel(asset.size, previousSize);
117
+ const sizeLabel = prettyBytes(asset.size) + (difference ? " (" + difference + ")" : "");
118
+ const gzipLabel = "gzip : " + prettyBytes(gzipSync(fileContents));
119
+ const sizeLabelLength = stripAnsi(sizeLabel).length;
120
+ const gzipLabelLength = stripAnsi(gzipLabel).length;
121
+ assets.push({
122
+ folder: path.join(path.basename(paths_default.appBuild), path.dirname(asset.name)),
123
+ name: path.basename(asset.name),
124
+ size: asset.size,
125
+ sizeLabel,
126
+ gzipLabel,
127
+ sizeLabelLength,
128
+ gzipLabelLength
129
+ });
130
+ gzipLabelLengthList.push(gzipLabelLength);
131
+ sizeLabelLengthList.push(sizeLabelLength);
132
+ }
133
+ assets.sort((a, b) => b.size - a.size);
134
+ const longestSizeLabelLength = Math.max.apply(void 0, sizeLabelLengthList);
135
+ const longestGzipSizeLabelLength = Math.max.apply(void 0, gzipLabelLengthList);
136
+ for (const asset of assets) {
137
+ let sizeLabel = asset.sizeLabel;
138
+ let gzipLabel = asset.gzipLabel;
139
+ const sizeLabelLength = asset.sizeLabelLength;
140
+ const gzipLabelLength = asset.gzipLabelLength;
141
+ if (sizeLabelLength < longestSizeLabelLength) sizeLabel += " ".repeat(longestSizeLabelLength - sizeLabelLength);
142
+ if (gzipLabelLength < longestGzipSizeLabelLength) gzipLabel += " ".repeat(longestGzipSizeLabelLength - gzipLabelLength);
143
+ const maxRecommendedSize = asset.name.indexOf("main.") === 0 ? WARN_AFTER_BUNDLE_GZIP_SIZE : WARN_AFTER_CHUNK_GZIP_SIZE;
144
+ const isLarge = maxRecommendedSize && asset.size > maxRecommendedSize;
145
+ if (isLarge && path.extname(asset.name) === ".js") suggestBundleSplitting = true;
146
+ console.log(" " + (isLarge ? styleText("yellow", sizeLabel) : sizeLabel) + " " + gzipLabel, " " + styleText("dim", asset.folder + path.sep) + styleText("cyan", asset.name));
147
+ }
148
+ }
149
+ if (suggestBundleSplitting) {
150
+ console.log();
151
+ console.log(styleText("yellow", "The bundle size is significantly larger than recommended."));
152
+ console.log(styleText("yellow", "You can also analyze the project dependencies: https://goo.gl/LeUzfb"));
153
+ }
154
+ }
155
+ //#endregion
156
+ //#region scripts/build.ts
157
+ async function startBuild(context) {
158
+ const { rspackConfig } = context;
159
+ try {
160
+ const previousFileSizes = await measureFileSizesBeforeBuild(paths_default.appBuild);
161
+ await emptyDirectory(paths_default.appBuild);
162
+ await copyPublicFolder();
163
+ const stats = await build(rspackConfig);
164
+ console.log(styleText("green", "Compiled successfully.\n"));
165
+ console.log("File sizes after gzip:\n");
166
+ if (stats) printFileSizesAfterBuild(stats, previousFileSizes);
167
+ console.log();
168
+ } catch (error) {
169
+ console.log(styleText("red", "Failed to compile.\n"));
170
+ if (error && error.message) console.log(error.message);
171
+ exit(1);
172
+ }
173
+ }
174
+ function copyPublicFolder() {
175
+ return fs.cp(paths_default.appPublic, paths_default.appBuild, {
176
+ recursive: true,
177
+ filter: (source) => source !== paths_default.appHtml
178
+ });
179
+ }
180
+ /**
181
+ * Create the production build and print the deployment instructions.
182
+ * @returns
183
+ */
184
+ async function build(rspackConfig) {
185
+ console.log("Creating an optimized production build...");
186
+ const compiler = rspack(rspackConfig);
187
+ return new Promise((resolve, reject) => {
188
+ compiler.run((error, stats) => {
189
+ if (error) return reject(error);
190
+ return resolve(stats);
191
+ });
192
+ });
193
+ }
194
+ //#endregion
195
+ export { startBuild as t };
@@ -0,0 +1,296 @@
1
+ import { t as paths_default } from "./paths-BvJwGeTv.js";
2
+ import { createRequire } from "node:module";
3
+ import { styleText } from "node:util";
4
+ import { exit } from "node:process";
5
+ import { rspack } from "@rspack/core";
6
+ import path from "node:path";
7
+ import { RspackDevServer } from "@rspack/dev-server";
8
+ import url from "node:url";
9
+ import prompts from "prompts";
10
+ import getPort from "get-port";
11
+ import os from "node:os";
12
+ //#region utils/address.ts
13
+ function getDefaultInterfaceName() {
14
+ let value = "eth";
15
+ const platform = os.platform();
16
+ if (platform === "darwin") value = "en";
17
+ else if (platform === "win32") value = void 0;
18
+ return value;
19
+ }
20
+ function matchName(actualFamily, expectedFamily) {
21
+ if (expectedFamily === "IPv4") return actualFamily === "IPv4" || actualFamily === 4;
22
+ if (expectedFamily === "IPv6") return actualFamily === "IPv6" || actualFamily === 6;
23
+ return actualFamily === expectedFamily;
24
+ }
25
+ function findAddressFromInterface(items, expectedFamily, ignoreLoAddress = false) {
26
+ let firstMatchItem;
27
+ for (const item of items) if (matchName(item.family, expectedFamily)) {
28
+ if (ignoreLoAddress && item.address.startsWith("127.")) continue;
29
+ if (expectedFamily === "IPv6") {
30
+ if (item.scopeid === 0) return item;
31
+ if (!firstMatchItem) firstMatchItem = item;
32
+ } else return item;
33
+ }
34
+ return firstMatchItem;
35
+ }
36
+ function getInterfaceAddress(family, name) {
37
+ const interfaces = os.networkInterfaces();
38
+ const noName = !name;
39
+ name = name || getDefaultInterfaceName();
40
+ family = family || "IPv4";
41
+ if (name) for (let index = -1; index < 8; index++) {
42
+ const items = interfaces[name + (index >= 0 ? index : "")];
43
+ if (items) {
44
+ const item = findAddressFromInterface(items, family);
45
+ if (item) return item;
46
+ }
47
+ }
48
+ if (noName) for (const k in interfaces) {
49
+ const items = interfaces[k];
50
+ if (items) {
51
+ const item = findAddressFromInterface(items, family, true);
52
+ if (item) return item;
53
+ }
54
+ }
55
+ }
56
+ /**
57
+ * Get current machine IPv4
58
+ *
59
+ * interfaceName: interface name, default is 'eth' on linux, 'en' on mac os.
60
+ */
61
+ function ip(interfaceName) {
62
+ return getInterfaceAddress("IPv4", interfaceName)?.address;
63
+ }
64
+ //#endregion
65
+ //#region utils/is-root.ts
66
+ /**
67
+ * 检查进程是否以 root 用户身份运行
68
+ */
69
+ function isRoot() {
70
+ return process.getuid && process.getuid() === 0;
71
+ }
72
+ //#endregion
73
+ //#region utils/clear-console.ts
74
+ /**
75
+ * 清除控制台的信息
76
+ */
77
+ function clearConsole() {}
78
+ //#endregion
79
+ //#region utils/dev-server-utils.ts
80
+ const isInteractive$1 = process.stdout.isTTY;
81
+ function printInstructions(appName, urls) {
82
+ console.log();
83
+ console.log(`You can now view ${styleText("bold", appName)} in the browser.`);
84
+ console.log();
85
+ if (urls.lanUrlForTerminal) {
86
+ console.log(` ${styleText("bold", "Local:")} ${urls.localUrlForTerminal}`);
87
+ console.log(` ${styleText("bold", "On Your Network:")} ${urls.lanUrlForTerminal}`);
88
+ } else console.log(` ${urls.localUrlForTerminal}`);
89
+ console.log();
90
+ console.log("Note that the development build is not optimized.");
91
+ }
92
+ /**
93
+ * 准备Url 数据
94
+ */
95
+ function prepareUrls(options) {
96
+ const { protocol, host, port, pathname = "/" } = options;
97
+ function formatUrl(hostname) {
98
+ return url.format({
99
+ protocol,
100
+ hostname,
101
+ port,
102
+ pathname
103
+ });
104
+ }
105
+ function prettyPrintUrl(hostname) {
106
+ return url.format({
107
+ protocol,
108
+ hostname,
109
+ port: styleText("bold", String(port)),
110
+ pathname
111
+ });
112
+ }
113
+ const isUnspecifiedHost = host === "0.0.0.0" || host === "::";
114
+ let prettyHost;
115
+ let lanUrlForConfig;
116
+ let lanUrlForTerminal;
117
+ if (isUnspecifiedHost) {
118
+ prettyHost = "localhost";
119
+ try {
120
+ lanUrlForConfig = ip();
121
+ if (lanUrlForConfig) if (/^10\.|^172\.(1[6-9]|2\d|3[01])\.|^192\.168\./.test(lanUrlForConfig)) lanUrlForTerminal = prettyPrintUrl(lanUrlForConfig);
122
+ else lanUrlForConfig = void 0;
123
+ } catch {}
124
+ } else prettyHost = host;
125
+ const localUrlForTerminal = prettyPrintUrl(prettyHost);
126
+ const localUrlForBrowser = formatUrl(prettyHost);
127
+ return {
128
+ lanUrlForConfig,
129
+ lanUrlForTerminal,
130
+ localUrlForTerminal,
131
+ localUrlForBrowser
132
+ };
133
+ }
134
+ /**
135
+ * 选择端口
136
+ * @param defaultPort 默认端口
137
+ * @param host 域名
138
+ */
139
+ async function choosePort(options) {
140
+ try {
141
+ const port = await getPort(options);
142
+ if (port === options.port) return port;
143
+ const message = process.platform !== "win32" && port < 1024 && !isRoot() ? `Admin permissions are required to run a server on a port below 1024.` : `Something is already running on port ${port}.`;
144
+ if (isInteractive$1) {
145
+ clearConsole();
146
+ return (await prompts({
147
+ type: "confirm",
148
+ name: "shouldChangePort",
149
+ message: styleText("yellow", message) + "\n\nWould you like to run the app on another port instead",
150
+ initial: true
151
+ })).shouldChangePort ? port : void 0;
152
+ } else {
153
+ console.log(styleText("red", message));
154
+ return;
155
+ }
156
+ } catch (error) {
157
+ throw new Error(styleText("red", `Could not find an open port at ${styleText("bold", options.host)}.`) + "\n" + ("Network error message: " + error.message || error) + "\n");
158
+ }
159
+ }
160
+ /**
161
+ * 编辑webpack配置
162
+ */
163
+ function createCompiler(options) {
164
+ const { appName, config, urls } = options;
165
+ let compiler;
166
+ try {
167
+ compiler = rspack(config);
168
+ } catch (error) {
169
+ console.log(styleText("red", "Failed to compile."));
170
+ console.log();
171
+ console.log(error.message || error);
172
+ console.log();
173
+ exit(1);
174
+ }
175
+ compiler.hooks.invalid.tap("invalid", () => {
176
+ if (isInteractive$1) clearConsole();
177
+ console.log("Compiling...");
178
+ });
179
+ let isFirstCompile = true;
180
+ compiler.hooks.done.tap("done", async (stats) => {
181
+ if (isInteractive$1) clearConsole();
182
+ const statsData = stats.toJson({
183
+ all: false,
184
+ warnings: true,
185
+ errors: true
186
+ });
187
+ const errors = statsData.errors ?? [];
188
+ const warnings = statsData.warnings ?? [];
189
+ const isSuccessful = errors.length === 0 && warnings.length === 0;
190
+ if (isSuccessful) console.log(styleText("green", "Compiled successfully!"));
191
+ if (isSuccessful && (isInteractive$1 || isFirstCompile)) printInstructions(appName, urls);
192
+ isFirstCompile = false;
193
+ if (errors.length > 0) {
194
+ if (errors.length > 1) errors.length = 1;
195
+ console.log(styleText("red", "Failed to compile.\n"));
196
+ console.log(errors.join("\n\n"));
197
+ return;
198
+ }
199
+ if (warnings.length > 0) {
200
+ console.log(styleText("yellow", "Compiled with warnings.\n"));
201
+ console.log(warnings.join("\n\n"));
202
+ console.log("\nSearch for the " + styleText("underline", styleText("yellow", "keywords")) + " to learn more about each warning.");
203
+ console.log("To ignore, add " + styleText("cyan", "// eslint-disable-next-line") + " to the line before.\n");
204
+ }
205
+ });
206
+ return compiler;
207
+ }
208
+ //#endregion
209
+ //#region utils/escape-string-regexp.ts
210
+ function escapeStringRegexp(string) {
211
+ return string.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`).replaceAll("-", String.raw`\x2d`);
212
+ }
213
+ //#endregion
214
+ //#region utils/ignored-files.ts
215
+ function ignoredFiles(appSource) {
216
+ return new RegExp(`^(?!${escapeStringRegexp(path.normalize(appSource + "/").replaceAll(/\\+/g, "/"))}).+/node_modules/`, "g");
217
+ }
218
+ //#endregion
219
+ //#region rspack-dev-server.ts
220
+ function createDevelopmentServerConfig() {
221
+ return {
222
+ allowedHosts: "all",
223
+ client: { overlay: true },
224
+ headers: {
225
+ "Access-Control-Allow-Origin": "*",
226
+ "Access-Control-Allow-Methods": "*",
227
+ "Access-Control-Allow-Headers": "*"
228
+ },
229
+ compress: true,
230
+ static: {
231
+ directory: paths_default.appPublic,
232
+ publicPath: [paths_default.publicUrlOrPath],
233
+ watch: { ignored: ignoredFiles(paths_default.appSrc) }
234
+ },
235
+ devMiddleware: { publicPath: paths_default.publicUrlOrPath.slice(0, -1) },
236
+ historyApiFallback: {
237
+ disableDotRule: true,
238
+ index: paths_default.publicUrlOrPath
239
+ }
240
+ };
241
+ }
242
+ //#endregion
243
+ //#region scripts/dev.ts
244
+ const require = createRequire(import.meta.url);
245
+ const isInteractive = process.stdout.isTTY;
246
+ const developmentServerConfig = {
247
+ PORT: 3e3,
248
+ HOST: "0.0.0.0",
249
+ PROTOCOL: "http"
250
+ };
251
+ async function startDev(context) {
252
+ const { rspackConfig } = context;
253
+ try {
254
+ const port = await choosePort({ port: developmentServerConfig.PORT });
255
+ if (port === void 0) return;
256
+ const appName = require(paths_default.appPackageJson).name;
257
+ const urls = prepareUrls({
258
+ protocol: developmentServerConfig.PROTOCOL,
259
+ host: developmentServerConfig.HOST,
260
+ port,
261
+ pathname: paths_default.publicUrlOrPath.slice(0, -1)
262
+ });
263
+ const localUrlForBrowser = new URL(urls.localUrlForBrowser);
264
+ const compiler = createCompiler({
265
+ appName,
266
+ config: rspackConfig,
267
+ urls
268
+ });
269
+ const developmentServer = new RspackDevServer({
270
+ ...createDevelopmentServerConfig(),
271
+ host: localUrlForBrowser.hostname,
272
+ port: localUrlForBrowser.port,
273
+ open: true
274
+ }, compiler);
275
+ developmentServer.startCallback((error) => {
276
+ if (isInteractive) clearConsole();
277
+ console.log(styleText("cyan", "Starting the development server...\n"));
278
+ });
279
+ developmentServer.stopCallback((error) => {
280
+ if (error) console.log("Server stopped.", error);
281
+ });
282
+ for (const signal of ["SIGINT", "SIGTERM"]) process.on(signal, () => {
283
+ developmentServer.stop();
284
+ process.exit();
285
+ });
286
+ if (process.env.CI !== "true") process.stdin.on("end", function() {
287
+ developmentServer.stop();
288
+ exit();
289
+ });
290
+ } catch (error) {
291
+ if (error?.message) console.log(error.message);
292
+ exit(1);
293
+ }
294
+ }
295
+ //#endregion
296
+ export { startDev as t };