@utoo/pack 1.1.3 → 1.1.4
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/cjs/commands/build.d.ts +3 -0
- package/cjs/commands/build.js +165 -0
- package/cjs/commands/dev.d.ts +44 -0
- package/cjs/commands/dev.js +387 -0
- package/cjs/config/readWebpackConfig.d.ts +1 -0
- package/cjs/config/readWebpackConfig.js +14 -0
- package/cjs/config/types.d.ts +1 -0
- package/cjs/config/types.js +17 -0
- package/cjs/config/webpackCompat.d.ts +2 -0
- package/cjs/config/webpackCompat.js +7 -0
- package/cjs/core/hmr.d.ts +80 -0
- package/cjs/core/hmr.js +341 -0
- package/cjs/core/loaderWorkerPool.d.ts +1 -0
- package/cjs/core/loaderWorkerPool.js +35 -0
- package/cjs/core/project.d.ts +43 -0
- package/cjs/core/project.js +291 -0
- package/cjs/core/types.d.ts +94 -0
- package/cjs/core/types.js +2 -0
- package/cjs/plugins/HtmlPlugin.d.ts +9 -0
- package/cjs/plugins/HtmlPlugin.js +116 -0
- package/cjs/utils/common.d.ts +3 -0
- package/cjs/utils/common.js +32 -0
- package/cjs/utils/find-root.d.ts +4 -0
- package/cjs/utils/find-root.js +75 -0
- package/cjs/utils/html-entry.d.ts +2 -0
- package/cjs/utils/html-entry.js +47 -0
- package/cjs/utils/mkcert.d.ts +7 -0
- package/cjs/utils/mkcert.js +183 -0
- package/cjs/utils/print-server-info.d.ts +1 -0
- package/cjs/utils/print-server-info.js +50 -0
- package/cjs/utils/xcodeProfile.d.ts +1 -0
- package/cjs/utils/xcodeProfile.js +16 -0
- package/esm/commands/build.d.ts +3 -0
- package/esm/commands/build.js +129 -0
- package/esm/commands/dev.d.ts +44 -0
- package/esm/commands/dev.js +371 -0
- package/esm/config/readWebpackConfig.d.ts +1 -0
- package/esm/config/readWebpackConfig.js +8 -0
- package/esm/config/types.d.ts +1 -0
- package/esm/config/types.js +1 -0
- package/esm/config/webpackCompat.d.ts +2 -0
- package/esm/config/webpackCompat.js +2 -0
- package/esm/core/hmr.d.ts +80 -0
- package/esm/core/hmr.js +334 -0
- package/esm/core/loaderWorkerPool.d.ts +1 -0
- package/esm/core/loaderWorkerPool.js +32 -0
- package/esm/core/project.d.ts +43 -0
- package/esm/core/project.js +253 -0
- package/esm/core/types.d.ts +94 -0
- package/esm/core/types.js +1 -0
- package/esm/plugins/HtmlPlugin.d.ts +9 -0
- package/esm/plugins/HtmlPlugin.js +109 -0
- package/esm/utils/common.d.ts +3 -0
- package/esm/utils/common.js +18 -0
- package/esm/utils/find-root.d.ts +4 -0
- package/esm/utils/find-root.js +66 -0
- package/esm/utils/html-entry.d.ts +2 -0
- package/esm/utils/html-entry.js +41 -0
- package/esm/utils/mkcert.d.ts +7 -0
- package/esm/utils/mkcert.js +176 -0
- package/esm/utils/print-server-info.d.ts +1 -0
- package/esm/utils/print-server-info.js +44 -0
- package/esm/utils/xcodeProfile.d.ts +1 -0
- package/esm/utils/xcodeProfile.js +13 -0
- package/package.json +12 -14
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface SelfSignedCertificate {
|
|
2
|
+
key: string;
|
|
3
|
+
cert: string;
|
|
4
|
+
rootCA?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function createSelfSignedCertificate(host?: string, certDir?: string): Promise<SelfSignedCertificate | undefined>;
|
|
7
|
+
export declare function getCacheDirectory(fileDirectory: string, envPath?: string): string;
|
|
@@ -0,0 +1,183 @@
|
|
|
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.createSelfSignedCertificate = createSelfSignedCertificate;
|
|
7
|
+
exports.getCacheDirectory = getCacheDirectory;
|
|
8
|
+
const node_child_process_1 = require("node:child_process");
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
10
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
12
|
+
const os_1 = __importDefault(require("os"));
|
|
13
|
+
const { WritableStream } = require("node:stream/web");
|
|
14
|
+
const MKCERT_VERSION = "v1.4.4";
|
|
15
|
+
function getBinaryName() {
|
|
16
|
+
const platform = process.platform;
|
|
17
|
+
const arch = process.arch === "x64" ? "amd64" : process.arch;
|
|
18
|
+
if (platform === "win32") {
|
|
19
|
+
return `mkcert-${MKCERT_VERSION}-windows-${arch}.exe`;
|
|
20
|
+
}
|
|
21
|
+
if (platform === "darwin") {
|
|
22
|
+
return `mkcert-${MKCERT_VERSION}-darwin-${arch}`;
|
|
23
|
+
}
|
|
24
|
+
if (platform === "linux") {
|
|
25
|
+
return `mkcert-${MKCERT_VERSION}-linux-${arch}`;
|
|
26
|
+
}
|
|
27
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
28
|
+
}
|
|
29
|
+
async function downloadBinary() {
|
|
30
|
+
try {
|
|
31
|
+
const binaryName = getBinaryName();
|
|
32
|
+
const cacheDirectory = getCacheDirectory("mkcert");
|
|
33
|
+
const binaryPath = node_path_1.default.join(cacheDirectory, binaryName);
|
|
34
|
+
if (node_fs_1.default.existsSync(binaryPath)) {
|
|
35
|
+
return binaryPath;
|
|
36
|
+
}
|
|
37
|
+
const downloadUrl = `https://github.com/FiloSottile/mkcert/releases/download/${MKCERT_VERSION}/${binaryName}`;
|
|
38
|
+
await node_fs_1.default.promises.mkdir(cacheDirectory, { recursive: true });
|
|
39
|
+
console.log(`Downloading mkcert package...`);
|
|
40
|
+
const response = await fetch(downloadUrl);
|
|
41
|
+
if (!response.ok || !response.body) {
|
|
42
|
+
throw new Error(`request failed with status ${response.status}`);
|
|
43
|
+
}
|
|
44
|
+
console.log(`Download response was successful, writing to disk`);
|
|
45
|
+
const binaryWriteStream = node_fs_1.default.createWriteStream(binaryPath);
|
|
46
|
+
await response.body.pipeTo(new WritableStream({
|
|
47
|
+
write(chunk) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
binaryWriteStream.write(chunk, (error) => {
|
|
50
|
+
if (error) {
|
|
51
|
+
reject(error);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
resolve();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
close() {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
binaryWriteStream.close((error) => {
|
|
61
|
+
if (error) {
|
|
62
|
+
reject(error);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
resolve();
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
}));
|
|
70
|
+
await node_fs_1.default.promises.chmod(binaryPath, 0o755);
|
|
71
|
+
return binaryPath;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
console.error("Error downloading mkcert:", err);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function createSelfSignedCertificate(host, certDir = "certificates") {
|
|
78
|
+
try {
|
|
79
|
+
const binaryPath = await downloadBinary();
|
|
80
|
+
if (!binaryPath)
|
|
81
|
+
throw new Error("missing mkcert binary");
|
|
82
|
+
const resolvedCertDir = node_path_1.default.resolve(process.cwd(), `./${certDir}`);
|
|
83
|
+
await node_fs_1.default.promises.mkdir(resolvedCertDir, {
|
|
84
|
+
recursive: true,
|
|
85
|
+
});
|
|
86
|
+
const keyPath = node_path_1.default.resolve(resolvedCertDir, "localhost-key.pem");
|
|
87
|
+
const certPath = node_path_1.default.resolve(resolvedCertDir, "localhost.pem");
|
|
88
|
+
if (node_fs_1.default.existsSync(keyPath) && node_fs_1.default.existsSync(certPath)) {
|
|
89
|
+
const cert = new node_crypto_1.X509Certificate(node_fs_1.default.readFileSync(certPath));
|
|
90
|
+
const key = node_fs_1.default.readFileSync(keyPath);
|
|
91
|
+
if (cert.checkHost(host !== null && host !== void 0 ? host : "localhost") &&
|
|
92
|
+
cert.checkPrivateKey((0, node_crypto_1.createPrivateKey)(key))) {
|
|
93
|
+
console.log("Using already generated self signed certificate");
|
|
94
|
+
const caLocation = (0, node_child_process_1.execSync)(`"${binaryPath}" -CAROOT`)
|
|
95
|
+
.toString()
|
|
96
|
+
.trim();
|
|
97
|
+
return {
|
|
98
|
+
key: keyPath,
|
|
99
|
+
cert: certPath,
|
|
100
|
+
rootCA: `${caLocation}/rootCA.pem`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
console.log("Attempting to generate self signed certificate. This may prompt for your password");
|
|
105
|
+
const defaultHosts = ["localhost", "127.0.0.1", "::1"];
|
|
106
|
+
const hosts = host && !defaultHosts.includes(host)
|
|
107
|
+
? [...defaultHosts, host]
|
|
108
|
+
: defaultHosts;
|
|
109
|
+
(0, node_child_process_1.execSync)(`"${binaryPath}" -install -key-file "${keyPath}" -cert-file "${certPath}" ${hosts.join(" ")}`, { stdio: "ignore" });
|
|
110
|
+
const caLocation = (0, node_child_process_1.execSync)(`"${binaryPath}" -CAROOT`).toString().trim();
|
|
111
|
+
if (!node_fs_1.default.existsSync(keyPath) || !node_fs_1.default.existsSync(certPath)) {
|
|
112
|
+
throw new Error("Certificate files not found");
|
|
113
|
+
}
|
|
114
|
+
console.log(`CA Root certificate created in ${caLocation}`);
|
|
115
|
+
console.log(`Certificates created in ${resolvedCertDir}`);
|
|
116
|
+
const gitignorePath = node_path_1.default.resolve(process.cwd(), "./.gitignore");
|
|
117
|
+
if (node_fs_1.default.existsSync(gitignorePath)) {
|
|
118
|
+
const gitignore = await node_fs_1.default.promises.readFile(gitignorePath, "utf8");
|
|
119
|
+
if (!gitignore.includes(certDir)) {
|
|
120
|
+
console.log("Adding certificates to .gitignore");
|
|
121
|
+
await node_fs_1.default.promises.appendFile(gitignorePath, `\n${certDir}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
key: keyPath,
|
|
126
|
+
cert: certPath,
|
|
127
|
+
rootCA: `${caLocation}/rootCA.pem`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error("Failed to generate self-signed certificate. Falling back to http.", err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// get platform specific cache directory adapted from playwright's handling
|
|
135
|
+
// https://github.com/microsoft/playwright/blob/7d924470d397975a74a19184c136b3573a974e13/packages/playwright-core/src/utils/registry.ts#L141
|
|
136
|
+
function getCacheDirectory(fileDirectory, envPath) {
|
|
137
|
+
let result;
|
|
138
|
+
if (envPath) {
|
|
139
|
+
result = envPath;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
let systemCacheDirectory;
|
|
143
|
+
if (process.platform === "linux") {
|
|
144
|
+
systemCacheDirectory =
|
|
145
|
+
process.env.XDG_CACHE_HOME || node_path_1.default.join(os_1.default.homedir(), ".cache");
|
|
146
|
+
}
|
|
147
|
+
else if (process.platform === "darwin") {
|
|
148
|
+
systemCacheDirectory = node_path_1.default.join(os_1.default.homedir(), "Library", "Caches");
|
|
149
|
+
}
|
|
150
|
+
else if (process.platform === "win32") {
|
|
151
|
+
systemCacheDirectory =
|
|
152
|
+
process.env.LOCALAPPDATA || node_path_1.default.join(os_1.default.homedir(), "AppData", "Local");
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
/// Attempt to use generic tmp location for un-handled platform
|
|
156
|
+
if (!systemCacheDirectory) {
|
|
157
|
+
for (const dir of [
|
|
158
|
+
node_path_1.default.join(os_1.default.homedir(), ".cache"),
|
|
159
|
+
node_path_1.default.join(os_1.default.tmpdir()),
|
|
160
|
+
]) {
|
|
161
|
+
if (node_fs_1.default.existsSync(dir)) {
|
|
162
|
+
systemCacheDirectory = dir;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (!systemCacheDirectory) {
|
|
168
|
+
console.error(new Error("Unsupported platform: " + process.platform));
|
|
169
|
+
process.exit(0);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
result = node_path_1.default.join(systemCacheDirectory, fileDirectory);
|
|
173
|
+
}
|
|
174
|
+
if (!node_path_1.default.isAbsolute(result)) {
|
|
175
|
+
// It is important to resolve to the absolute path:
|
|
176
|
+
// - for unzipping to work correctly;
|
|
177
|
+
// - so that registry directory matches between installation and execution.
|
|
178
|
+
// INIT_CWD points to the root of `npm/yarn install` and is probably what
|
|
179
|
+
// the user meant when typing the relative path.
|
|
180
|
+
result = node_path_1.default.resolve(process.env["INIT_CWD"] || process.cwd(), result);
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function printServerInfo(protocol: "http" | "https", hostname: string, port: number): void;
|
|
@@ -0,0 +1,50 @@
|
|
|
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.printServerInfo = printServerInfo;
|
|
7
|
+
const os_1 = __importDefault(require("os"));
|
|
8
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
9
|
+
function printServerInfo(protocol, hostname, port) {
|
|
10
|
+
const localUrl = `${protocol}://localhost:${port}`;
|
|
11
|
+
const networkAddress = getNetworkAddress();
|
|
12
|
+
const networkUrl = networkAddress
|
|
13
|
+
? `${protocol}://${networkAddress}:${port}`
|
|
14
|
+
: null;
|
|
15
|
+
console.log();
|
|
16
|
+
console.log(picocolors_1.default.green(" ┌──────────────────────────────────────────────────┐"));
|
|
17
|
+
console.log(picocolors_1.default.green(" │ │"));
|
|
18
|
+
console.log(picocolors_1.default.green(" │ ") +
|
|
19
|
+
picocolors_1.default.bold("Serving!") +
|
|
20
|
+
picocolors_1.default.green(" │"));
|
|
21
|
+
console.log(picocolors_1.default.green(" │ │"));
|
|
22
|
+
const localLabel = " │ - Local: ";
|
|
23
|
+
const localPadding = 50 - 15 - localUrl.length; // 15 is " - Local: ".length
|
|
24
|
+
console.log(picocolors_1.default.green(localLabel) +
|
|
25
|
+
picocolors_1.default.cyan(localUrl) +
|
|
26
|
+
picocolors_1.default.green(" ".repeat(Math.max(0, localPadding)) + "│"));
|
|
27
|
+
if (networkUrl) {
|
|
28
|
+
const netLabel = " │ - Network: ";
|
|
29
|
+
const netPadding = 50 - 17 - networkUrl.length; // 17 is " - Network: ".length
|
|
30
|
+
console.log(picocolors_1.default.green(netLabel) +
|
|
31
|
+
picocolors_1.default.cyan(networkUrl) +
|
|
32
|
+
picocolors_1.default.green(" ".repeat(Math.max(0, netPadding)) + "│"));
|
|
33
|
+
}
|
|
34
|
+
console.log(picocolors_1.default.green(" │ │"));
|
|
35
|
+
console.log(picocolors_1.default.green(" │ Copied local address to clipboard! │"));
|
|
36
|
+
console.log(picocolors_1.default.green(" │ │"));
|
|
37
|
+
console.log(picocolors_1.default.green(" └──────────────────────────────────────────────────┘"));
|
|
38
|
+
console.log();
|
|
39
|
+
}
|
|
40
|
+
function getNetworkAddress() {
|
|
41
|
+
const interfaces = os_1.default.networkInterfaces();
|
|
42
|
+
for (const name of Object.keys(interfaces)) {
|
|
43
|
+
for (const iface of interfaces[name]) {
|
|
44
|
+
if (iface.family === "IPv4" && !iface.internal) {
|
|
45
|
+
return iface.address;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function xcodeProfilingReady(): Promise<void>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.xcodeProfilingReady = xcodeProfilingReady;
|
|
4
|
+
async function xcodeProfilingReady() {
|
|
5
|
+
await new Promise((resolve) => {
|
|
6
|
+
const readline = require("readline");
|
|
7
|
+
const rl = readline.createInterface({
|
|
8
|
+
input: process.stdin,
|
|
9
|
+
output: process.stdout,
|
|
10
|
+
});
|
|
11
|
+
rl.question(`Xcode profile enabled. Current process ${process.title} (${process.pid}) . Press Enter to continue...\n`, () => {
|
|
12
|
+
rl.close();
|
|
13
|
+
resolve();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { handleIssues } from "@utoo/pack-shared";
|
|
2
|
+
import { spawn } from "child_process";
|
|
3
|
+
import fs, { existsSync } from "fs";
|
|
4
|
+
import { nanoid } from "nanoid";
|
|
5
|
+
import { join } from "path";
|
|
6
|
+
import { compatOptionsFromWebpack, readWebpackConfig, } from "../config/webpackCompat";
|
|
7
|
+
import { projectFactory } from "../core/project";
|
|
8
|
+
import { HtmlPlugin } from "../plugins/HtmlPlugin";
|
|
9
|
+
import { blockStdout, createDefineEnv, getPackPath } from "../utils/common";
|
|
10
|
+
import { findRootDir } from "../utils/find-root";
|
|
11
|
+
import { processHtmlEntry } from "../utils/html-entry";
|
|
12
|
+
import { xcodeProfilingReady } from "../utils/xcodeProfile";
|
|
13
|
+
export function build(options, projectPath, rootPath) {
|
|
14
|
+
let bundleOptions;
|
|
15
|
+
if (options.webpackMode) {
|
|
16
|
+
let webpackConfig = options;
|
|
17
|
+
if (!webpackConfig.entry) {
|
|
18
|
+
const loadedConfig = readWebpackConfig(projectPath, rootPath);
|
|
19
|
+
webpackConfig = { ...webpackConfig, ...loadedConfig };
|
|
20
|
+
}
|
|
21
|
+
bundleOptions = compatOptionsFromWebpack(webpackConfig);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
bundleOptions = options;
|
|
25
|
+
}
|
|
26
|
+
if (!rootPath) {
|
|
27
|
+
// help user to find the rootDir automatically.
|
|
28
|
+
rootPath = findRootDir(projectPath || process.cwd());
|
|
29
|
+
}
|
|
30
|
+
return buildInternal(bundleOptions, projectPath, rootPath);
|
|
31
|
+
}
|
|
32
|
+
async function buildInternal(bundleOptions, projectPath, rootPath) {
|
|
33
|
+
var _a, _b, _c, _d, _e, _f;
|
|
34
|
+
blockStdout();
|
|
35
|
+
if (process.env.XCODE_PROFILE) {
|
|
36
|
+
await xcodeProfilingReady();
|
|
37
|
+
}
|
|
38
|
+
processHtmlEntry(bundleOptions.config, projectPath || process.cwd());
|
|
39
|
+
const createProject = projectFactory();
|
|
40
|
+
const project = await createProject({
|
|
41
|
+
processEnv: (_a = bundleOptions.processEnv) !== null && _a !== void 0 ? _a : {},
|
|
42
|
+
defineEnv: createDefineEnv({
|
|
43
|
+
config: bundleOptions.config,
|
|
44
|
+
dev: (_b = bundleOptions.dev) !== null && _b !== void 0 ? _b : false,
|
|
45
|
+
optionDefineEnv: bundleOptions.defineEnv,
|
|
46
|
+
}),
|
|
47
|
+
watch: {
|
|
48
|
+
enable: false,
|
|
49
|
+
},
|
|
50
|
+
dev: (_c = bundleOptions.dev) !== null && _c !== void 0 ? _c : false,
|
|
51
|
+
buildId: bundleOptions.buildId || nanoid(),
|
|
52
|
+
config: {
|
|
53
|
+
...bundleOptions.config,
|
|
54
|
+
stats: Boolean(process.env.ANALYZE) ||
|
|
55
|
+
bundleOptions.config.stats ||
|
|
56
|
+
bundleOptions.config.entry.some((e) => !!e.html),
|
|
57
|
+
},
|
|
58
|
+
projectPath: projectPath || process.cwd(),
|
|
59
|
+
rootPath: rootPath || projectPath || process.cwd(),
|
|
60
|
+
packPath: getPackPath(),
|
|
61
|
+
}, {
|
|
62
|
+
persistentCaching: false,
|
|
63
|
+
});
|
|
64
|
+
const entrypoints = await project.writeAllEntrypointsToDisk();
|
|
65
|
+
handleIssues(entrypoints.issues);
|
|
66
|
+
const htmlConfigs = [
|
|
67
|
+
...(Array.isArray(bundleOptions.config.html)
|
|
68
|
+
? bundleOptions.config.html
|
|
69
|
+
: bundleOptions.config.html
|
|
70
|
+
? [bundleOptions.config.html]
|
|
71
|
+
: []),
|
|
72
|
+
...bundleOptions.config.entry.filter((e) => !!e.html).map((e) => e.html),
|
|
73
|
+
];
|
|
74
|
+
if (htmlConfigs.length > 0) {
|
|
75
|
+
const assets = { js: [], css: [] };
|
|
76
|
+
const outputDir = ((_d = bundleOptions.config.output) === null || _d === void 0 ? void 0 : _d.path) || join(process.cwd(), "dist");
|
|
77
|
+
if (assets.js.length === 0 && assets.css.length === 0) {
|
|
78
|
+
const statsPath = join(outputDir, "stats.json");
|
|
79
|
+
if (existsSync(statsPath)) {
|
|
80
|
+
try {
|
|
81
|
+
const stats = JSON.parse(fs.readFileSync(statsPath, "utf-8"));
|
|
82
|
+
if (stats.assets) {
|
|
83
|
+
stats.assets.forEach((asset) => {
|
|
84
|
+
if (asset.name.endsWith(".js"))
|
|
85
|
+
assets.js.push(asset.name);
|
|
86
|
+
if (asset.name.endsWith(".css"))
|
|
87
|
+
assets.css.push(asset.name);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
console.warn("Failed to read stats.json for assets discovery", e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const publicPath = (_e = bundleOptions.config.output) === null || _e === void 0 ? void 0 : _e.publicPath;
|
|
97
|
+
for (const config of htmlConfigs) {
|
|
98
|
+
const plugin = new HtmlPlugin(config);
|
|
99
|
+
await plugin.generate(outputDir, assets, publicPath);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (process.env.ANALYZE) {
|
|
103
|
+
await analyzeBundle(((_f = bundleOptions.config.output) === null || _f === void 0 ? void 0 : _f.path) || "dist");
|
|
104
|
+
}
|
|
105
|
+
await project.shutdown();
|
|
106
|
+
// TODO: Maybe run tasks in worker is a better way, see
|
|
107
|
+
// https://github.com/vercel/next.js/blob/512d8283054407ab92b2583ecce3b253c3be7b85/packages/next/src/lib/worker.ts
|
|
108
|
+
}
|
|
109
|
+
async function analyzeBundle(outputPath) {
|
|
110
|
+
const statsPath = join(outputPath, "stats.json");
|
|
111
|
+
if (!existsSync(statsPath)) {
|
|
112
|
+
console.warn(`Stats file not found at ${statsPath}. Make sure to enable stats in your configuration.`);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
return new Promise((resolve, reject) => {
|
|
116
|
+
const analyzer = spawn("npx", ["webpack-bundle-analyzer", statsPath], {
|
|
117
|
+
stdio: "inherit",
|
|
118
|
+
shell: true,
|
|
119
|
+
});
|
|
120
|
+
analyzer.on("error", (error) => {
|
|
121
|
+
reject(new Error(`Failed to start bundle analyzer: ${error.message}`));
|
|
122
|
+
});
|
|
123
|
+
analyzer.on("close", () => {
|
|
124
|
+
// The analyzer process has finished, so we can resolve the promise
|
|
125
|
+
// to allow the build process to exit gracefully.
|
|
126
|
+
resolve();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from "http";
|
|
2
|
+
import send from "send";
|
|
3
|
+
import { Duplex, Writable } from "stream";
|
|
4
|
+
import { WebpackConfig } from "../config/webpackCompat";
|
|
5
|
+
import { BundleOptions } from "../core/types";
|
|
6
|
+
export declare function serve(options: BundleOptions | WebpackConfig, projectPath?: string, rootPath?: string, serverOptions?: StartServerOptions): Promise<void>;
|
|
7
|
+
export interface SelfSignedCertificate {
|
|
8
|
+
key: string;
|
|
9
|
+
cert: string;
|
|
10
|
+
rootCA?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface StartServerOptions {
|
|
13
|
+
port: number;
|
|
14
|
+
https?: boolean;
|
|
15
|
+
hostname?: string;
|
|
16
|
+
logServerInfo?: boolean;
|
|
17
|
+
selfSignedCertificate?: SelfSignedCertificate;
|
|
18
|
+
}
|
|
19
|
+
export type RequestHandler = (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
20
|
+
export type UpgradeHandler = (req: IncomingMessage, socket: Duplex, head: Buffer) => Promise<void>;
|
|
21
|
+
export type ServerInitResult = {
|
|
22
|
+
requestHandler: RequestHandler;
|
|
23
|
+
upgradeHandler: UpgradeHandler;
|
|
24
|
+
closeUpgraded: () => void;
|
|
25
|
+
};
|
|
26
|
+
export declare function startServer(serverOptions: StartServerOptions, bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<void>;
|
|
27
|
+
export declare function initialize(bundleOptions: BundleOptions, projectPath: string, rootPath?: string): Promise<ServerInitResult>;
|
|
28
|
+
export declare function pipeToNodeResponse(readable: ReadableStream<Uint8Array>, res: ServerResponse, waitUntilForEnd?: Promise<unknown>): Promise<void>;
|
|
29
|
+
export declare function createAbortController(response: Writable): AbortController;
|
|
30
|
+
export declare function isAbortError(e: any): e is Error & {
|
|
31
|
+
name: "AbortError";
|
|
32
|
+
};
|
|
33
|
+
export declare const ResponseAbortedName = "ResponseAborted";
|
|
34
|
+
export declare class ResponseAborted extends Error {
|
|
35
|
+
readonly name = "ResponseAborted";
|
|
36
|
+
}
|
|
37
|
+
export declare class DetachedPromise<T = any> {
|
|
38
|
+
readonly resolve: (value: T | PromiseLike<T>) => void;
|
|
39
|
+
readonly reject: (reason: any) => void;
|
|
40
|
+
readonly promise: Promise<T>;
|
|
41
|
+
constructor();
|
|
42
|
+
}
|
|
43
|
+
export declare function serveStatic(req: IncomingMessage, res: ServerResponse, path: string, opts?: Parameters<typeof send>[2]): Promise<void>;
|
|
44
|
+
export declare function formatHostname(hostname: string): string;
|