@addfox/rsbuild-plugin-extension-entry 0.1.1-beta.2
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/LICENSE +21 -0
- package/README.md +12 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +346 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 addfox
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# @addfox/rsbuild-plugin-extension-entry
|
|
2
|
+
|
|
3
|
+
[中文](README-zh_CN.md) | English
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Rsbuild plugin: configures multi-entry, HTML templates and public copy from addfox’s resolved entry list. Injected by CLI pipeline; users do not configure it directly.
|
|
8
|
+
|
|
9
|
+
- Multi-entry: popup, options, content, background, sidepanel, devtools and custom entry
|
|
10
|
+
- HTML templates: JS/TS is the real entry; HTML is template only and must include one `<script data-addfox-entry src="...">`
|
|
11
|
+
- Entry config supports `string` or `{ src, html }` (html can be `true` or template path)
|
|
12
|
+
- Copies `public/` to dist when present
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { RsbuildPluginAPI } from "@rsbuild/core";
|
|
2
|
+
import type { AddfoxResolvedConfig, EntryInfo, BrowserTarget } from "@addfox/core";
|
|
3
|
+
/** Chunk name for shared vendor (react, react-dom, webextension-polyfill) to avoid duplicate in popup/options. */
|
|
4
|
+
export declare const SHARED_VENDOR_CHUNK_NAME = "shared-vendor";
|
|
5
|
+
interface ChunkFilenamePathData {
|
|
6
|
+
chunk?: {
|
|
7
|
+
name?: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
type ChunkFilenameFn = (pathData: ChunkFilenamePathData) => string;
|
|
12
|
+
interface EntryOutputMap {
|
|
13
|
+
html: Record<string, string>;
|
|
14
|
+
js: Record<string, string>;
|
|
15
|
+
css: Record<string, string>;
|
|
16
|
+
}
|
|
17
|
+
/** Build JS chunk filename function for output. */
|
|
18
|
+
export declare function buildJsChunkFilenameFn(outputMap: Pick<EntryOutputMap, "js">, entryNames: Set<string>): ChunkFilenameFn;
|
|
19
|
+
/** Build CSS chunk filename function for output. */
|
|
20
|
+
export declare function buildCssChunkFilenameFn(outputMap: Pick<EntryOutputMap, "css">, entryNames: Set<string>): ChunkFilenameFn;
|
|
21
|
+
/**
|
|
22
|
+
* Main entry plugin function.
|
|
23
|
+
* @param resolvedConfig - Resolved Addfox configuration
|
|
24
|
+
* @param entries - Discovered entries
|
|
25
|
+
* @param distPath - Output directory path (browser-specific, e.g., .addfox/extension/extension-chromium)
|
|
26
|
+
*/
|
|
27
|
+
export type EntryPluginDevOptions = {
|
|
28
|
+
/** When Firefox and hot reload is on, disable Rspack HMR (use web-ext reload instead). */
|
|
29
|
+
browser?: BrowserTarget;
|
|
30
|
+
};
|
|
31
|
+
export declare function entryPlugin(resolvedConfig: AddfoxResolvedConfig, entries: EntryInfo[], distPath: string, devOptions?: EntryPluginDevOptions): {
|
|
32
|
+
name: string;
|
|
33
|
+
setup(api: RsbuildPluginAPI): void;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { basename, dirname, extname, relative, resolve } from "path";
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { parseAddfoxEntryFromHtml } from "@addfox/core";
|
|
4
|
+
function isHotReloadDisabled(value) {
|
|
5
|
+
return false === value;
|
|
6
|
+
}
|
|
7
|
+
const NO_HTML_ENTRIES = new Set([
|
|
8
|
+
"background",
|
|
9
|
+
"content"
|
|
10
|
+
]);
|
|
11
|
+
const SHARED_VENDOR_CHUNK_NAME = "shared-vendor";
|
|
12
|
+
const SHARED_VENDOR_TEST = /[\\/]node_modules[\\/]/;
|
|
13
|
+
const toWebPath = (p)=>p.replace(/\\/g, "/");
|
|
14
|
+
function isHmrPlugin(p) {
|
|
15
|
+
if (!p || "object" != typeof p) return false;
|
|
16
|
+
const obj = p;
|
|
17
|
+
return obj.constructor?.name === "HotModuleReplacementPlugin" || "HotModuleReplacementPlugin" === obj.name;
|
|
18
|
+
}
|
|
19
|
+
function disableRspackHmrInPlace(config) {
|
|
20
|
+
const devServer = config.devServer;
|
|
21
|
+
if (devServer) devServer.hot = false;
|
|
22
|
+
else config.devServer = {
|
|
23
|
+
hot: false
|
|
24
|
+
};
|
|
25
|
+
const plugins = config.plugins;
|
|
26
|
+
if (Array.isArray(plugins)) config.plugins = plugins.filter((p)=>!isHmrPlugin(p));
|
|
27
|
+
}
|
|
28
|
+
function getStrippedTemplateContent(htmlPath) {
|
|
29
|
+
const parsed = parseAddfoxEntryFromHtml(htmlPath);
|
|
30
|
+
return parsed?.strippedHtml;
|
|
31
|
+
}
|
|
32
|
+
function buildScriptFollowingPaths(entry, appDir) {
|
|
33
|
+
const relScript = toWebPath(relative(appDir, entry.scriptPath));
|
|
34
|
+
const scriptExt = extname(entry.scriptPath);
|
|
35
|
+
const scriptBase = scriptExt ? relScript.slice(0, -scriptExt.length) : relScript;
|
|
36
|
+
return {
|
|
37
|
+
js: `${scriptBase}.js`,
|
|
38
|
+
css: `${scriptBase}.css`,
|
|
39
|
+
html: entry.htmlPath ? toWebPath(relative(appDir, entry.htmlPath)) : void 0
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function buildStandardPaths(entry) {
|
|
43
|
+
const scriptStem = basename(entry.scriptPath, extname(entry.scriptPath));
|
|
44
|
+
const isSingleScript = scriptStem === entry.name;
|
|
45
|
+
const jsPath = isSingleScript ? `${entry.name}.js` : `${entry.name}/index.js`;
|
|
46
|
+
const cssPath = isSingleScript ? `${entry.name}.css` : `${entry.name}/index.css`;
|
|
47
|
+
let htmlPath;
|
|
48
|
+
if (entry.htmlPath) {
|
|
49
|
+
const htmlFile = basename(entry.htmlPath).toLowerCase();
|
|
50
|
+
const entryDir = basename(dirname(entry.htmlPath)).toLowerCase();
|
|
51
|
+
const isEntryDir = entryDir === entry.name.toLowerCase();
|
|
52
|
+
const isSingleHtml = htmlFile === `${entry.name}.html`;
|
|
53
|
+
htmlPath = isEntryDir ? `${entry.name}/${htmlFile}` : isSingleHtml ? `${entry.name}.html` : `${entry.name}/${htmlFile}`;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
js: jsPath,
|
|
57
|
+
css: cssPath,
|
|
58
|
+
html: htmlPath
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function buildEntryOutputMap(entries, appDir) {
|
|
62
|
+
const html = {};
|
|
63
|
+
const js = {};
|
|
64
|
+
const css = {};
|
|
65
|
+
for (const entry of entries){
|
|
66
|
+
const paths = entry.outputFollowsScriptPath ? buildScriptFollowingPaths(entry, appDir) : buildStandardPaths(entry);
|
|
67
|
+
js[entry.name] = paths.js;
|
|
68
|
+
css[entry.name] = paths.css;
|
|
69
|
+
if (paths.html) html[entry.name] = paths.html;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
html,
|
|
73
|
+
js,
|
|
74
|
+
css
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function buildJsChunkFilenameFn(outputMap, entryNames) {
|
|
78
|
+
return (pathData)=>{
|
|
79
|
+
const name = pathData.chunk?.name ?? pathData.chunk?.id ?? "chunk";
|
|
80
|
+
const nameStr = String(name);
|
|
81
|
+
if (nameStr === SHARED_VENDOR_CHUNK_NAME) return "static/js/shared-vendor.js";
|
|
82
|
+
if (entryNames.has(nameStr)) return outputMap.js[nameStr] ?? `${nameStr}/index.js`;
|
|
83
|
+
return `static/js/${nameStr}.js`;
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function buildCssChunkFilenameFn(outputMap, entryNames) {
|
|
87
|
+
return (pathData)=>{
|
|
88
|
+
const name = pathData.chunk?.name ?? pathData.chunk?.id ?? "chunk";
|
|
89
|
+
const nameStr = String(name);
|
|
90
|
+
if (entryNames.has(nameStr)) return outputMap.css[nameStr] ?? `${nameStr}/index.css`;
|
|
91
|
+
return `static/css/${nameStr}.css`;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function createTemplateMap(entries) {
|
|
95
|
+
const map = {};
|
|
96
|
+
for (const entry of entries)if (entry.htmlPath) map[entry.name] = entry.htmlPath;
|
|
97
|
+
return map;
|
|
98
|
+
}
|
|
99
|
+
function createScriptInjectMap(entries) {
|
|
100
|
+
const map = {};
|
|
101
|
+
for (const entry of entries)if (entry.scriptInject) map[entry.name] = entry.scriptInject;
|
|
102
|
+
return map;
|
|
103
|
+
}
|
|
104
|
+
function needsHtmlGeneration(entry) {
|
|
105
|
+
if (NO_HTML_ENTRIES.has(entry.name)) return false;
|
|
106
|
+
return true === entry.html || null != entry.htmlPath;
|
|
107
|
+
}
|
|
108
|
+
function buildSourceEntry(entries) {
|
|
109
|
+
const entry = {};
|
|
110
|
+
for (const e of entries)entry[e.name] = needsHtmlGeneration(e) ? e.scriptPath : {
|
|
111
|
+
import: e.scriptPath,
|
|
112
|
+
html: false
|
|
113
|
+
};
|
|
114
|
+
return entry;
|
|
115
|
+
}
|
|
116
|
+
function ensurePerformanceConfig(config) {
|
|
117
|
+
const cfg = config;
|
|
118
|
+
if (!cfg.performance) cfg.performance = {};
|
|
119
|
+
const perf = cfg.performance;
|
|
120
|
+
if (!perf.chunkSplit) perf.chunkSplit = {};
|
|
121
|
+
return perf;
|
|
122
|
+
}
|
|
123
|
+
function setupChunkSplit(config) {
|
|
124
|
+
const performance = ensurePerformanceConfig(config);
|
|
125
|
+
const chunkSplit = performance.chunkSplit;
|
|
126
|
+
const prevOverride = chunkSplit.override;
|
|
127
|
+
chunkSplit.override = {
|
|
128
|
+
...prevOverride,
|
|
129
|
+
chunks: "all",
|
|
130
|
+
cacheGroups: {
|
|
131
|
+
...prevOverride?.cacheGroups,
|
|
132
|
+
[SHARED_VENDOR_CHUNK_NAME]: {
|
|
133
|
+
test: SHARED_VENDOR_TEST,
|
|
134
|
+
name: SHARED_VENDOR_CHUNK_NAME,
|
|
135
|
+
priority: 30,
|
|
136
|
+
enforce: true,
|
|
137
|
+
reuseExistingChunk: true
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function ensureDevConfig(config) {
|
|
143
|
+
const cfg = config;
|
|
144
|
+
if (!cfg.dev) cfg.dev = {};
|
|
145
|
+
return cfg.dev;
|
|
146
|
+
}
|
|
147
|
+
function setupWatchFiles(config, htmlPaths) {
|
|
148
|
+
if (0 === htmlPaths.length) return;
|
|
149
|
+
const dev = ensureDevConfig(config);
|
|
150
|
+
const prevWatch = dev.watchFiles;
|
|
151
|
+
const existingPaths = Array.isArray(prevWatch?.paths) ? prevWatch.paths : "string" == typeof prevWatch?.paths ? [
|
|
152
|
+
prevWatch.paths
|
|
153
|
+
] : [];
|
|
154
|
+
dev.watchFiles = {
|
|
155
|
+
...prevWatch && "object" == typeof prevWatch ? prevWatch : {},
|
|
156
|
+
paths: [
|
|
157
|
+
...existingPaths,
|
|
158
|
+
...htmlPaths
|
|
159
|
+
]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function ensureOutputConfig(config) {
|
|
163
|
+
const cfg = config;
|
|
164
|
+
if (!cfg.output) cfg.output = {};
|
|
165
|
+
return cfg.output;
|
|
166
|
+
}
|
|
167
|
+
function setupOutputConfig(config, resolvedConfig, publicDir, distPath) {
|
|
168
|
+
const output = ensureOutputConfig(config);
|
|
169
|
+
const existingDistPath = output.distPath && "object" == typeof output.distPath ? output.distPath : {};
|
|
170
|
+
output.distPath = {
|
|
171
|
+
...existingDistPath,
|
|
172
|
+
root: distPath
|
|
173
|
+
};
|
|
174
|
+
output.cleanDistPath = output.cleanDistPath ?? true;
|
|
175
|
+
output.assetPrefix = output.assetPrefix ?? "/";
|
|
176
|
+
if (existsSync(publicDir)) {
|
|
177
|
+
const copyRules = Array.isArray(output.copy) ? output.copy : [];
|
|
178
|
+
output.copy = [
|
|
179
|
+
...copyRules,
|
|
180
|
+
{
|
|
181
|
+
from: publicDir
|
|
182
|
+
}
|
|
183
|
+
];
|
|
184
|
+
}
|
|
185
|
+
setupChunkSplit(config);
|
|
186
|
+
}
|
|
187
|
+
function createTemplateHandler(templateMap, prevTemplate) {
|
|
188
|
+
return (ctx)=>{
|
|
189
|
+
if (templateMap[ctx.entryName]) return templateMap[ctx.entryName];
|
|
190
|
+
if ("function" == typeof prevTemplate) return prevTemplate(ctx);
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function createInjectHandler(scriptInjectMap) {
|
|
194
|
+
const hasInjectMap = Object.keys(scriptInjectMap).length > 0;
|
|
195
|
+
return hasInjectMap ? ({ entryName })=>scriptInjectMap[entryName] ?? "head" : "head";
|
|
196
|
+
}
|
|
197
|
+
function createHtmlPluginHandler(outputMap, entryByName, prevHtmlPlugin) {
|
|
198
|
+
return (htmlConfig, ctx)=>{
|
|
199
|
+
if (prevHtmlPlugin && "function" == typeof prevHtmlPlugin) prevHtmlPlugin(htmlConfig, ctx);
|
|
200
|
+
if (outputMap.html[ctx.entryName]) htmlConfig.filename = outputMap.html[ctx.entryName];
|
|
201
|
+
const entry = entryByName.get(ctx.entryName);
|
|
202
|
+
if (entry?.scriptInject && entry.htmlPath && existsSync(entry.htmlPath)) {
|
|
203
|
+
const content = getStrippedTemplateContent(entry.htmlPath);
|
|
204
|
+
if (content) htmlConfig.templateContent = content;
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function createWatchTemplatesPlugin(htmlPaths) {
|
|
209
|
+
return {
|
|
210
|
+
name: "rsbuild-plugin-extension-entry:watch-templates",
|
|
211
|
+
apply (compiler) {
|
|
212
|
+
compiler.hooks.compilation.tap("rsbuild-plugin-extension-entry:watch-templates", (compilation)=>{
|
|
213
|
+
for (const p of htmlPaths)if (existsSync(p)) compilation.fileDependencies.add(p);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function setupRspackConfig(bundlerConfig, context) {
|
|
219
|
+
const { root, outputRoot, outDir, htmlPaths, outputMap, entryNames, hotReloadDisabled } = context;
|
|
220
|
+
const distPath = resolve(root, outputRoot, outDir);
|
|
221
|
+
if (hotReloadDisabled) disableRspackHmrInPlace(bundlerConfig);
|
|
222
|
+
if (htmlPaths.length > 0) {
|
|
223
|
+
const rspackConfig = bundlerConfig;
|
|
224
|
+
rspackConfig.plugins = rspackConfig.plugins ?? [];
|
|
225
|
+
rspackConfig.plugins.push(createWatchTemplatesPlugin(htmlPaths));
|
|
226
|
+
}
|
|
227
|
+
const watchOpts = bundlerConfig.watchOptions ?? {};
|
|
228
|
+
const existingIgnored = watchOpts.ignored;
|
|
229
|
+
const ignoredList = Array.isArray(existingIgnored) ? [
|
|
230
|
+
...existingIgnored,
|
|
231
|
+
distPath
|
|
232
|
+
] : null != existingIgnored ? [
|
|
233
|
+
existingIgnored,
|
|
234
|
+
distPath
|
|
235
|
+
] : [
|
|
236
|
+
distPath
|
|
237
|
+
];
|
|
238
|
+
bundlerConfig.watchOptions = {
|
|
239
|
+
...watchOpts,
|
|
240
|
+
ignored: ignoredList
|
|
241
|
+
};
|
|
242
|
+
if (bundlerConfig.output) {
|
|
243
|
+
const output = bundlerConfig.output;
|
|
244
|
+
output.path = distPath;
|
|
245
|
+
const jsChunkName = buildJsChunkFilenameFn(outputMap, entryNames);
|
|
246
|
+
const cssChunkName = buildCssChunkFilenameFn(outputMap, entryNames);
|
|
247
|
+
output.filename = jsChunkName;
|
|
248
|
+
output.chunkFilename = output.chunkFilename ?? jsChunkName;
|
|
249
|
+
output.cssFilename = cssChunkName;
|
|
250
|
+
output.cssChunkFilename = output.cssChunkFilename ?? cssChunkName;
|
|
251
|
+
output.publicPath = "/";
|
|
252
|
+
}
|
|
253
|
+
if (bundlerConfig.optimization) {
|
|
254
|
+
const optimization = bundlerConfig.optimization;
|
|
255
|
+
optimization.runtimeChunk = false;
|
|
256
|
+
optimization.splitChunks = optimization.splitChunks ?? {};
|
|
257
|
+
const split = optimization.splitChunks;
|
|
258
|
+
split.chunks = "function" == typeof split.chunks ? split.chunks : (chunk)=>chunk.name ? !NO_HTML_ENTRIES.has(chunk.name) : true;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function ensureSourceConfig(config) {
|
|
262
|
+
const cfg = config;
|
|
263
|
+
if (!cfg.source) cfg.source = {};
|
|
264
|
+
return cfg.source;
|
|
265
|
+
}
|
|
266
|
+
function ensureHtmlConfig(config) {
|
|
267
|
+
const cfg = config;
|
|
268
|
+
if (!cfg.html) cfg.html = {};
|
|
269
|
+
return cfg.html;
|
|
270
|
+
}
|
|
271
|
+
function ensureToolsConfig(config) {
|
|
272
|
+
const cfg = config;
|
|
273
|
+
if (!cfg.tools) cfg.tools = {};
|
|
274
|
+
return cfg.tools;
|
|
275
|
+
}
|
|
276
|
+
function modifyRsbuildConfig(config, context) {
|
|
277
|
+
const { entry, templateMap, scriptInjectMap, outputMap, entryByName, htmlPaths, resolvedConfig, publicDir, distPath } = context;
|
|
278
|
+
const source = ensureSourceConfig(config);
|
|
279
|
+
source.entry = {
|
|
280
|
+
...source.entry ?? {},
|
|
281
|
+
...entry
|
|
282
|
+
};
|
|
283
|
+
const html = ensureHtmlConfig(config);
|
|
284
|
+
const prevTemplate = html.template;
|
|
285
|
+
html.template = createTemplateHandler(templateMap, prevTemplate);
|
|
286
|
+
html.inject = createInjectHandler(scriptInjectMap);
|
|
287
|
+
html.outputStructure = html.outputStructure ?? "nested";
|
|
288
|
+
const tools = ensureToolsConfig(config);
|
|
289
|
+
const prevHtmlPlugin = tools.htmlPlugin;
|
|
290
|
+
tools.htmlPlugin = createHtmlPluginHandler(outputMap, entryByName, prevHtmlPlugin);
|
|
291
|
+
setupWatchFiles(config, htmlPaths);
|
|
292
|
+
setupOutputConfig(config, resolvedConfig, publicDir, distPath);
|
|
293
|
+
}
|
|
294
|
+
function shouldDisableRspackHmrForFirefox(browser, hotReload) {
|
|
295
|
+
if ("firefox" !== browser) return false;
|
|
296
|
+
return false !== hotReload;
|
|
297
|
+
}
|
|
298
|
+
function entryPlugin(resolvedConfig, entries, distPath, devOptions) {
|
|
299
|
+
const { outputRoot, root, appDir } = resolvedConfig;
|
|
300
|
+
const publicDir = resolve(root, "public");
|
|
301
|
+
const entry = buildSourceEntry(entries);
|
|
302
|
+
const entryNames = new Set(Object.keys(entry));
|
|
303
|
+
const templateMap = createTemplateMap(entries);
|
|
304
|
+
const scriptInjectMap = createScriptInjectMap(entries);
|
|
305
|
+
const outputMap = buildEntryOutputMap(entries, appDir);
|
|
306
|
+
const entryByName = new Map(entries.map((e)=>[
|
|
307
|
+
e.name,
|
|
308
|
+
e
|
|
309
|
+
]));
|
|
310
|
+
const htmlPaths = entries.filter((e)=>e.htmlPath).map((e)=>e.htmlPath);
|
|
311
|
+
const modifyConfigContext = {
|
|
312
|
+
entry,
|
|
313
|
+
templateMap,
|
|
314
|
+
scriptInjectMap,
|
|
315
|
+
outputMap,
|
|
316
|
+
entryByName,
|
|
317
|
+
htmlPaths,
|
|
318
|
+
resolvedConfig,
|
|
319
|
+
publicDir,
|
|
320
|
+
distPath
|
|
321
|
+
};
|
|
322
|
+
return {
|
|
323
|
+
name: "rsbuild-plugin-extension-entry",
|
|
324
|
+
setup (api) {
|
|
325
|
+
api.modifyRsbuildConfig((config)=>{
|
|
326
|
+
modifyRsbuildConfig(config, modifyConfigContext);
|
|
327
|
+
});
|
|
328
|
+
api.onBeforeCreateCompiler(async ({ bundlerConfigs })=>{
|
|
329
|
+
const bundlerConfig = bundlerConfigs[0];
|
|
330
|
+
if (!bundlerConfig) return;
|
|
331
|
+
setupRspackConfig(bundlerConfig, {
|
|
332
|
+
root,
|
|
333
|
+
outputRoot,
|
|
334
|
+
outDir: distPath,
|
|
335
|
+
htmlPaths,
|
|
336
|
+
outputMap,
|
|
337
|
+
entryNames,
|
|
338
|
+
hotReloadDisabled: isHotReloadDisabled(resolvedConfig.hotReload) || shouldDisableRspackHmrForFirefox(devOptions?.browser, resolvedConfig.hotReload)
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
export { SHARED_VENDOR_CHUNK_NAME, buildCssChunkFilenameFn, buildJsChunkFilenameFn, entryPlugin };
|
|
345
|
+
|
|
346
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { resolve, basename, extname, dirname, relative } from \"path\";\r\nimport { existsSync } from \"fs\";\r\nimport type { RsbuildConfig, RsbuildPluginAPI } from \"@rsbuild/core\";\r\nimport type { AddfoxResolvedConfig, EntryInfo, ScriptInjectPosition, BrowserTarget } from \"@addfox/core\";\r\nimport { parseAddfoxEntryFromHtml } from \"@addfox/core\";\r\n\r\n/** hotReload: undefined = not set, object = enabled, false = explicitly disabled. Only when false do we disable Rspack HMR. */\r\ntype HotReloadConfig = AddfoxResolvedConfig[\"hotReload\"];\r\n\r\nfunction isHotReloadDisabled(value: HotReloadConfig): boolean {\r\n return value === false;\r\n}\r\n\r\nconst NO_HTML_ENTRIES = new Set([\"background\", \"content\"]);\r\n\r\n/** Chunk name for shared vendor (react, react-dom, webextension-polyfill) to avoid duplicate in popup/options. */\r\nexport const SHARED_VENDOR_CHUNK_NAME = \"shared-vendor\";\r\n\r\n/** Matches node_modules used by HTML entries for a single shared chunk (WXT-style). */\r\nconst SHARED_VENDOR_TEST = /[\\\\/]node_modules[\\\\/]/;\r\n\r\nconst toWebPath = (p: string): string => p.replace(/\\\\/g, \"/\");\r\n\r\ninterface ChunkFilenamePathData {\r\n chunk?: { name?: string; id?: string };\r\n}\r\n\r\ntype ChunkFilenameFn = (pathData: ChunkFilenamePathData) => string;\r\n\r\ninterface EntryOutputMap {\r\n html: Record<string, string>;\r\n js: Record<string, string>;\r\n css: Record<string, string>;\r\n}\r\n\r\ninterface PerformanceConfig {\r\n chunkSplit?: Record<string, unknown>;\r\n}\r\n\r\ninterface WatchFilesOption {\r\n paths?: string | string[];\r\n options?: unknown;\r\n}\r\n\r\ninterface DevConfig {\r\n watchFiles?: WatchFilesOption;\r\n}\r\n\r\ninterface SourceConfig {\r\n entry?: Record<string, unknown>;\r\n}\r\n\r\ninterface HtmlConfig {\r\n template?: unknown;\r\n inject?: unknown;\r\n outputStructure?: string;\r\n}\r\n\r\ninterface ToolsConfig {\r\n htmlPlugin?: unknown;\r\n}\r\n\r\ninterface OutputConfig {\r\n distPath?: Record<string, unknown>;\r\n cleanDistPath?: boolean;\r\n assetPrefix?: string;\r\n copy?: unknown;\r\n}\r\n\r\ninterface TemplateContext {\r\n value: string;\r\n entryName: string;\r\n}\r\n\r\ninterface HtmlPluginContext {\r\n entryName: string;\r\n entryValue: unknown;\r\n}\r\n\r\ninterface Compilation {\r\n fileDependencies: { add: (p: string) => void };\r\n}\r\n\r\ninterface Compiler {\r\n hooks: {\r\n compilation: {\r\n tap: (name: string, fn: (compilation: Compilation) => void) => void;\r\n };\r\n };\r\n}\r\n\r\n/** Check if a plugin is HMR plugin. */\r\nfunction isHmrPlugin(p: unknown): boolean {\r\n if (!p || typeof p !== \"object\") return false;\r\n const obj = p as { constructor?: { name?: string }; name?: string };\r\n return (\r\n obj.constructor?.name === \"HotModuleReplacementPlugin\" ||\r\n obj.name === \"HotModuleReplacementPlugin\"\r\n );\r\n}\r\n\r\n/** Disable Rspack HMR so dist is not filled with *.hot-update.js (extension build watch). */\r\nfunction disableRspackHmrInPlace(config: Record<string, unknown>): void {\r\n const devServer = config.devServer as Record<string, unknown> | undefined;\r\n if (devServer) {\r\n devServer.hot = false;\r\n } else {\r\n config.devServer = { hot: false };\r\n }\r\n\r\n const plugins = config.plugins;\r\n if (Array.isArray(plugins)) {\r\n config.plugins = plugins.filter((p: unknown) => !isHmrPlugin(p));\r\n }\r\n}\r\n\r\n/** For entries with scriptInject: read htmlPath, strip data-addfox-entry script, return content to use as template. */\r\nfunction getStrippedTemplateContent(htmlPath: string): string | undefined {\r\n const parsed = parseAddfoxEntryFromHtml(htmlPath);\r\n return parsed?.strippedHtml;\r\n}\r\n\r\n/** Build output paths for an entry that follows script path. */\r\nfunction buildScriptFollowingPaths(\r\n entry: EntryInfo,\r\n appDir: string\r\n): { js: string; css: string; html?: string } {\r\n const relScript = toWebPath(relative(appDir, entry.scriptPath));\r\n const scriptExt = extname(entry.scriptPath);\r\n const scriptBase = scriptExt ? relScript.slice(0, -scriptExt.length) : relScript;\r\n\r\n return {\r\n js: `${scriptBase}.js`,\r\n css: `${scriptBase}.css`,\r\n html: entry.htmlPath ? toWebPath(relative(appDir, entry.htmlPath)) : undefined,\r\n };\r\n}\r\n\r\n/** Build output paths for a standard entry. */\r\nfunction buildStandardPaths(entry: EntryInfo): { js: string; css: string; html?: string } {\r\n const scriptStem = basename(entry.scriptPath, extname(entry.scriptPath));\r\n const isSingleScript = scriptStem === entry.name;\r\n\r\n const jsPath = isSingleScript ? `${entry.name}.js` : `${entry.name}/index.js`;\r\n const cssPath = isSingleScript ? `${entry.name}.css` : `${entry.name}/index.css`;\r\n\r\n let htmlPath: string | undefined;\r\n if (entry.htmlPath) {\r\n const htmlFile = basename(entry.htmlPath).toLowerCase();\r\n const entryDir = basename(dirname(entry.htmlPath)).toLowerCase();\r\n const isEntryDir = entryDir === entry.name.toLowerCase();\r\n const isSingleHtml = htmlFile === `${entry.name}.html`;\r\n\r\n htmlPath = isEntryDir\r\n ? `${entry.name}/${htmlFile}`\r\n : isSingleHtml\r\n ? `${entry.name}.html`\r\n : `${entry.name}/${htmlFile}`;\r\n }\r\n\r\n return { js: jsPath, css: cssPath, html: htmlPath };\r\n}\r\n\r\n/** Build output path mappings for all entries. */\r\nfunction buildEntryOutputMap(entries: EntryInfo[], appDir: string): EntryOutputMap {\r\n const html: Record<string, string> = {};\r\n const js: Record<string, string> = {};\r\n const css: Record<string, string> = {};\r\n\r\n for (const entry of entries) {\r\n const paths = entry.outputFollowsScriptPath\r\n ? buildScriptFollowingPaths(entry, appDir)\r\n : buildStandardPaths(entry);\r\n\r\n js[entry.name] = paths.js;\r\n css[entry.name] = paths.css;\r\n if (paths.html) {\r\n html[entry.name] = paths.html;\r\n }\r\n }\r\n\r\n return { html, js, css };\r\n}\r\n\r\n/** Build JS chunk filename function for output. */\r\nexport function buildJsChunkFilenameFn(\r\n outputMap: Pick<EntryOutputMap, \"js\">,\r\n entryNames: Set<string>\r\n): ChunkFilenameFn {\r\n return (pathData) => {\r\n const name = pathData.chunk?.name ?? pathData.chunk?.id ?? \"chunk\";\r\n const nameStr = String(name);\r\n\r\n if (nameStr === SHARED_VENDOR_CHUNK_NAME) {\r\n return \"static/js/shared-vendor.js\";\r\n }\r\n if (entryNames.has(nameStr)) {\r\n return outputMap.js[nameStr] ?? `${nameStr}/index.js`;\r\n }\r\n return `static/js/${nameStr}.js`;\r\n };\r\n}\r\n\r\n/** Build CSS chunk filename function for output. */\r\nexport function buildCssChunkFilenameFn(\r\n outputMap: Pick<EntryOutputMap, \"css\">,\r\n entryNames: Set<string>\r\n): ChunkFilenameFn {\r\n return (pathData) => {\r\n const name = pathData.chunk?.name ?? pathData.chunk?.id ?? \"chunk\";\r\n const nameStr = String(name);\r\n\r\n if (entryNames.has(nameStr)) {\r\n return outputMap.css[nameStr] ?? `${nameStr}/index.css`;\r\n }\r\n return `static/css/${nameStr}.css`;\r\n };\r\n}\r\n\r\n/** Create a map of entry names to their HTML template paths. */\r\nfunction createTemplateMap(entries: EntryInfo[]): Record<string, string> {\r\n const map: Record<string, string> = {};\r\n for (const entry of entries) {\r\n if (entry.htmlPath) {\r\n map[entry.name] = entry.htmlPath;\r\n }\r\n }\r\n return map;\r\n}\r\n\r\n/** Create a map of entry names to their script inject positions. */\r\nfunction createScriptInjectMap(entries: EntryInfo[]): Record<string, ScriptInjectPosition> {\r\n const map: Record<string, ScriptInjectPosition> = {};\r\n for (const entry of entries) {\r\n if (entry.scriptInject) {\r\n map[entry.name] = entry.scriptInject;\r\n }\r\n }\r\n return map;\r\n}\r\n\r\n/** Determine if an entry needs HTML generation. */\r\nfunction needsHtmlGeneration(entry: EntryInfo): boolean {\r\n if (NO_HTML_ENTRIES.has(entry.name)) return false;\r\n return entry.html === true || entry.htmlPath != null;\r\n}\r\n\r\n/** Build the source entry configuration. */\r\nfunction buildSourceEntry(entries: EntryInfo[]): Record<string, string | { import: string; html?: boolean }> {\r\n const entry: Record<string, string | { import: string; html?: boolean }> = {};\r\n\r\n for (const e of entries) {\r\n entry[e.name] = needsHtmlGeneration(e)\r\n ? e.scriptPath\r\n : { import: e.scriptPath, html: false };\r\n }\r\n\r\n return entry;\r\n}\r\n\r\nfunction ensurePerformanceConfig(config: RsbuildConfig): PerformanceConfig {\r\n const cfg = config as RsbuildConfig & { performance?: PerformanceConfig };\r\n if (!cfg.performance) {\r\n cfg.performance = {};\r\n }\r\n const perf = cfg.performance;\r\n if (!perf.chunkSplit) {\r\n perf.chunkSplit = {};\r\n }\r\n return perf;\r\n}\r\n\r\n/** Setup chunk split configuration for shared vendor. */\r\nfunction setupChunkSplit(config: RsbuildConfig): void {\r\n const performance = ensurePerformanceConfig(config);\r\n const chunkSplit = performance.chunkSplit as Record<string, unknown>;\r\n const prevOverride = chunkSplit.override as Record<string, unknown> | undefined;\r\n\r\n chunkSplit.override = {\r\n ...prevOverride,\r\n chunks: \"all\",\r\n cacheGroups: {\r\n ...(prevOverride?.cacheGroups as Record<string, unknown> | undefined),\r\n [SHARED_VENDOR_CHUNK_NAME]: {\r\n test: SHARED_VENDOR_TEST,\r\n name: SHARED_VENDOR_CHUNK_NAME,\r\n priority: 30,\r\n enforce: true,\r\n reuseExistingChunk: true,\r\n },\r\n },\r\n };\r\n}\r\n\r\nfunction ensureDevConfig(config: RsbuildConfig): DevConfig {\r\n const cfg = config as RsbuildConfig & { dev?: DevConfig };\r\n if (!cfg.dev) {\r\n cfg.dev = {};\r\n }\r\n return cfg.dev;\r\n}\r\n\r\n/** Setup watch files for HTML templates. */\r\nfunction setupWatchFiles(config: RsbuildConfig, htmlPaths: string[]): void {\r\n if (htmlPaths.length === 0) return;\r\n\r\n const dev = ensureDevConfig(config);\r\n const prevWatch = dev.watchFiles;\r\n const existingPaths = Array.isArray(prevWatch?.paths)\r\n ? prevWatch.paths\r\n : typeof prevWatch?.paths === \"string\"\r\n ? [prevWatch.paths]\r\n : [];\r\n\r\n dev.watchFiles = {\r\n ...(prevWatch && typeof prevWatch === \"object\" ? prevWatch : {}),\r\n paths: [...existingPaths, ...htmlPaths],\r\n };\r\n}\r\n\r\nfunction ensureOutputConfig(config: RsbuildConfig): OutputConfig {\r\n const cfg = config as RsbuildConfig & { output?: OutputConfig };\r\n if (!cfg.output) {\r\n cfg.output = {};\r\n }\r\n return cfg.output;\r\n}\r\n\r\n/** Setup output configuration including dist path and copy rules. */\r\nfunction setupOutputConfig(\r\n config: RsbuildConfig,\r\n resolvedConfig: AddfoxResolvedConfig,\r\n publicDir: string,\r\n distPath: string\r\n): void {\r\n\r\n const output = ensureOutputConfig(config);\r\n\r\n // Use provided distPath (browser-specific, e.g., .addfox/extension/extension-chromium)\r\n const existingDistPath = output.distPath && typeof output.distPath === \"object\"\r\n ? output.distPath\r\n : {};\r\n output.distPath = { ...existingDistPath, root: distPath };\r\n\r\n output.cleanDistPath = output.cleanDistPath ?? true;\r\n output.assetPrefix = output.assetPrefix ?? \"/\";\r\n\r\n // Add public dir copy rule if it exists\r\n if (existsSync(publicDir)) {\r\n const copyRules = Array.isArray(output.copy) ? output.copy : [];\r\n output.copy = [...copyRules, { from: publicDir }];\r\n }\r\n\r\n setupChunkSplit(config);\r\n}\r\n\r\n/** Create the HTML template handler function. */\r\nfunction createTemplateHandler(\r\n templateMap: Record<string, string>,\r\n prevTemplate: unknown\r\n): (ctx: TemplateContext) => string | void {\r\n return (ctx: TemplateContext): string | void => {\r\n if (templateMap[ctx.entryName]) {\r\n return templateMap[ctx.entryName];\r\n }\r\n if (typeof prevTemplate === \"function\") {\r\n return prevTemplate(ctx);\r\n }\r\n return undefined;\r\n };\r\n}\r\n\r\n/** Create the HTML inject position handler. */\r\nfunction createInjectHandler(\r\n scriptInjectMap: Record<string, ScriptInjectPosition>\r\n): ScriptInjectPosition | ((ctx: { entryName: string }) => ScriptInjectPosition) {\r\n const hasInjectMap = Object.keys(scriptInjectMap).length > 0;\r\n\r\n return hasInjectMap\r\n ? ({ entryName }: { entryName: string }) => scriptInjectMap[entryName] ?? \"head\"\r\n : \"head\";\r\n}\r\n\r\n/** Create the HTML plugin configuration handler. */\r\nfunction createHtmlPluginHandler(\r\n outputMap: EntryOutputMap,\r\n entryByName: Map<string, EntryInfo>,\r\n prevHtmlPlugin: unknown\r\n): (htmlConfig: Record<string, unknown>, ctx: HtmlPluginContext) => void {\r\n return (htmlConfig: Record<string, unknown>, ctx: HtmlPluginContext): void => {\r\n // Call previous handler if exists\r\n if (prevHtmlPlugin && typeof prevHtmlPlugin === \"function\") {\r\n prevHtmlPlugin(htmlConfig, ctx);\r\n }\r\n\r\n // Set output filename\r\n if (outputMap.html[ctx.entryName]) {\r\n htmlConfig.filename = outputMap.html[ctx.entryName];\r\n }\r\n\r\n // Apply stripped template content for scriptInject entries\r\n const entry = entryByName.get(ctx.entryName);\r\n if (entry?.scriptInject && entry.htmlPath && existsSync(entry.htmlPath)) {\r\n const content = getStrippedTemplateContent(entry.htmlPath);\r\n if (content) {\r\n htmlConfig.templateContent = content;\r\n }\r\n }\r\n };\r\n}\r\n\r\n/** Create rspack plugin for watching HTML template files. */\r\nfunction createWatchTemplatesPlugin(htmlPaths: string[]): {\r\n name: string;\r\n apply: (compiler: Compiler) => void;\r\n} {\r\n return {\r\n name: \"rsbuild-plugin-extension-entry:watch-templates\",\r\n apply(compiler: Compiler): void {\r\n compiler.hooks.compilation.tap(\"rsbuild-plugin-extension-entry:watch-templates\", (compilation) => {\r\n for (const p of htmlPaths) {\r\n if (existsSync(p)) {\r\n compilation.fileDependencies.add(p);\r\n }\r\n }\r\n });\r\n },\r\n };\r\n}\r\n\r\ninterface WatchOptionsLike {\r\n ignored?: string | RegExp | Array<string | RegExp>;\r\n}\r\n\r\n/** Setup rspack configuration before compiler creation. */\r\nfunction setupRspackConfig(\r\n bundlerConfig: Record<string, unknown>,\r\n context: {\r\n root: string;\r\n outputRoot: string;\r\n outDir: string;\r\n htmlPaths: string[];\r\n outputMap: EntryOutputMap;\r\n entryNames: Set<string>;\r\n /** When true, Rspack HMR is disabled (only when addfox hotReload config is off). */\r\n hotReloadDisabled: boolean;\r\n }\r\n): void {\r\n const { root, outputRoot, outDir, htmlPaths, outputMap, entryNames, hotReloadDisabled } = context;\r\n const distPath = resolve(root, outputRoot, outDir);\r\n\r\n if (hotReloadDisabled) {\r\n disableRspackHmrInPlace(bundlerConfig);\r\n }\r\n\r\n // Add watch templates plugin\r\n if (htmlPaths.length > 0) {\r\n const rspackConfig = bundlerConfig as { plugins?: unknown[] };\r\n rspackConfig.plugins = rspackConfig.plugins ?? [];\r\n rspackConfig.plugins.push(createWatchTemplatesPlugin(htmlPaths));\r\n }\r\n\r\n // Setup watch options to ignore dist path\r\n const watchOpts = (bundlerConfig.watchOptions as WatchOptionsLike | undefined) ?? {};\r\n const existingIgnored = watchOpts.ignored;\r\n const ignoredList: (string | RegExp)[] = Array.isArray(existingIgnored)\r\n ? [...existingIgnored, distPath]\r\n : existingIgnored != null\r\n ? [existingIgnored, distPath]\r\n : [distPath];\r\n bundlerConfig.watchOptions = { ...watchOpts, ignored: ignoredList as string[] };\r\n\r\n // Setup output configuration\r\n if (bundlerConfig.output) {\r\n const output = bundlerConfig.output as Record<string, unknown>;\r\n output.path = distPath;\r\n\r\n const jsChunkName = buildJsChunkFilenameFn(outputMap, entryNames);\r\n const cssChunkName = buildCssChunkFilenameFn(outputMap, entryNames);\r\n\r\n output.filename = jsChunkName as unknown as string;\r\n output.chunkFilename = output.chunkFilename ?? jsChunkName;\r\n output.cssFilename = cssChunkName as unknown as string;\r\n output.cssChunkFilename = output.cssChunkFilename ?? cssChunkName;\r\n output.publicPath = \"/\";\r\n }\r\n\r\n // Setup optimization\r\n if (bundlerConfig.optimization) {\r\n const optimization = bundlerConfig.optimization as Record<string, unknown>;\r\n optimization.runtimeChunk = false;\r\n optimization.splitChunks = optimization.splitChunks ?? {};\r\n\r\n const split = optimization.splitChunks as Record<string, unknown>;\r\n // Only HTML entries participate in splitting so background/content vendor stays in their chunks\r\n split.chunks = typeof split.chunks === \"function\"\r\n ? split.chunks\r\n : (chunk: { name?: string }) => (chunk.name ? !NO_HTML_ENTRIES.has(chunk.name) : true);\r\n }\r\n}\r\n\r\nfunction ensureSourceConfig(config: RsbuildConfig): SourceConfig {\r\n const cfg = config as RsbuildConfig & { source?: SourceConfig };\r\n if (!cfg.source) {\r\n cfg.source = {};\r\n }\r\n return cfg.source;\r\n}\r\n\r\nfunction ensureHtmlConfig(config: RsbuildConfig): HtmlConfig {\r\n const cfg = config as RsbuildConfig & { html?: HtmlConfig };\r\n if (!cfg.html) {\r\n cfg.html = {};\r\n }\r\n return cfg.html;\r\n}\r\n\r\nfunction ensureToolsConfig(config: RsbuildConfig): ToolsConfig {\r\n const cfg = config as RsbuildConfig & { tools?: ToolsConfig };\r\n if (!cfg.tools) {\r\n cfg.tools = {};\r\n }\r\n return cfg.tools;\r\n}\r\n\r\n/** Modify Rsbuild configuration for extension entries. */\r\nfunction modifyRsbuildConfig(\r\n config: RsbuildConfig,\r\n context: {\r\n entry: Record<string, string | { import: string; html?: boolean }>;\r\n templateMap: Record<string, string>;\r\n scriptInjectMap: Record<string, ScriptInjectPosition>;\r\n outputMap: EntryOutputMap;\r\n entryByName: Map<string, EntryInfo>;\r\n htmlPaths: string[];\r\n resolvedConfig: AddfoxResolvedConfig;\r\n publicDir: string;\r\n distPath: string;\r\n }\r\n): void {\r\n const { entry, templateMap, scriptInjectMap, outputMap, entryByName, htmlPaths, resolvedConfig, publicDir, distPath } = context;\r\n\r\n // Setup source entry\r\n const source = ensureSourceConfig(config);\r\n source.entry = { ...(source.entry ?? {}), ...entry };\r\n\r\n // Setup HTML\r\n const html = ensureHtmlConfig(config);\r\n const prevTemplate = html.template;\r\n html.template = createTemplateHandler(templateMap, prevTemplate);\r\n html.inject = createInjectHandler(scriptInjectMap);\r\n html.outputStructure = html.outputStructure ?? \"nested\";\r\n\r\n // Setup HTML plugin\r\n const tools = ensureToolsConfig(config);\r\n const prevHtmlPlugin = tools.htmlPlugin;\r\n tools.htmlPlugin = createHtmlPluginHandler(outputMap, entryByName, prevHtmlPlugin);\r\n\r\n // Watch HTML templates\r\n setupWatchFiles(config, htmlPaths);\r\n\r\n // Setup output (use distPath for browser-specific output)\r\n setupOutputConfig(config, resolvedConfig, publicDir, distPath);\r\n}\r\n\r\n/**\r\n * Main entry plugin function.\r\n * @param resolvedConfig - Resolved Addfox configuration\r\n * @param entries - Discovered entries\r\n * @param distPath - Output directory path (browser-specific, e.g., .addfox/extension/extension-chromium)\r\n */\r\nexport type EntryPluginDevOptions = {\r\n /** When Firefox and hot reload is on, disable Rspack HMR (use web-ext reload instead). */\r\n browser?: BrowserTarget;\r\n};\r\n\r\nfunction shouldDisableRspackHmrForFirefox(\r\n browser: BrowserTarget | undefined,\r\n hotReload: AddfoxResolvedConfig[\"hotReload\"]\r\n): boolean {\r\n if (browser !== \"firefox\") return false;\r\n return hotReload !== false;\r\n}\r\n\r\nexport function entryPlugin(\r\n resolvedConfig: AddfoxResolvedConfig,\r\n entries: EntryInfo[],\r\n distPath: string,\r\n devOptions?: EntryPluginDevOptions\r\n) {\r\n const { outputRoot, root, appDir } = resolvedConfig;\r\n const publicDir = resolve(root, \"public\");\r\n\r\n // Build all lookup maps and configurations\r\n const entry = buildSourceEntry(entries);\r\n const entryNames = new Set(Object.keys(entry));\r\n const templateMap = createTemplateMap(entries);\r\n const scriptInjectMap = createScriptInjectMap(entries);\r\n const outputMap = buildEntryOutputMap(entries, appDir);\r\n const entryByName = new Map(entries.map((e) => [e.name, e]));\r\n const htmlPaths = entries.filter((e) => e.htmlPath).map((e) => e.htmlPath!);\r\n\r\n const modifyConfigContext = {\r\n entry,\r\n templateMap,\r\n scriptInjectMap,\r\n outputMap,\r\n entryByName,\r\n htmlPaths,\r\n resolvedConfig,\r\n publicDir,\r\n distPath,\r\n };\r\n\r\n return {\r\n name: \"rsbuild-plugin-extension-entry\",\r\n setup(api: RsbuildPluginAPI) {\r\n api.modifyRsbuildConfig((config) => {\r\n modifyRsbuildConfig(config, modifyConfigContext);\r\n });\r\n\r\n api.onBeforeCreateCompiler(async ({ bundlerConfigs }) => {\r\n const bundlerConfig = bundlerConfigs[0];\r\n if (!bundlerConfig) return;\r\n\r\n setupRspackConfig(bundlerConfig, {\r\n root,\r\n outputRoot,\r\n outDir: distPath,\r\n htmlPaths,\r\n outputMap,\r\n entryNames,\r\n hotReloadDisabled:\r\n isHotReloadDisabled(resolvedConfig.hotReload) ||\r\n shouldDisableRspackHmrForFirefox(devOptions?.browser, resolvedConfig.hotReload),\r\n });\r\n });\r\n },\r\n };\r\n}\r\n"],"names":["isHotReloadDisabled","value","NO_HTML_ENTRIES","Set","SHARED_VENDOR_CHUNK_NAME","SHARED_VENDOR_TEST","toWebPath","p","isHmrPlugin","obj","disableRspackHmrInPlace","config","devServer","plugins","Array","getStrippedTemplateContent","htmlPath","parsed","parseAddfoxEntryFromHtml","buildScriptFollowingPaths","entry","appDir","relScript","relative","scriptExt","extname","scriptBase","undefined","buildStandardPaths","scriptStem","basename","isSingleScript","jsPath","cssPath","htmlFile","entryDir","dirname","isEntryDir","isSingleHtml","buildEntryOutputMap","entries","html","js","css","paths","buildJsChunkFilenameFn","outputMap","entryNames","pathData","name","nameStr","String","buildCssChunkFilenameFn","createTemplateMap","map","createScriptInjectMap","needsHtmlGeneration","buildSourceEntry","e","ensurePerformanceConfig","cfg","perf","setupChunkSplit","performance","chunkSplit","prevOverride","ensureDevConfig","setupWatchFiles","htmlPaths","dev","prevWatch","existingPaths","ensureOutputConfig","setupOutputConfig","resolvedConfig","publicDir","distPath","output","existingDistPath","existsSync","copyRules","createTemplateHandler","templateMap","prevTemplate","ctx","createInjectHandler","scriptInjectMap","hasInjectMap","Object","entryName","createHtmlPluginHandler","entryByName","prevHtmlPlugin","htmlConfig","content","createWatchTemplatesPlugin","compiler","compilation","setupRspackConfig","bundlerConfig","context","root","outputRoot","outDir","hotReloadDisabled","resolve","rspackConfig","watchOpts","existingIgnored","ignoredList","jsChunkName","cssChunkName","optimization","split","chunk","ensureSourceConfig","ensureHtmlConfig","ensureToolsConfig","modifyRsbuildConfig","source","tools","shouldDisableRspackHmrForFirefox","browser","hotReload","entryPlugin","devOptions","Map","modifyConfigContext","api","bundlerConfigs"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@addfox/rsbuild-plugin-extension-entry",
|
|
3
|
+
"version": "0.1.1-beta.2",
|
|
4
|
+
"description": "Rsbuild plugin: multi-entry, HTML and public copy (internal)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"main": "./dist/index.js",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@addfox/core": "0.1.1-beta.2"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@rspack/core": "^1.7.8",
|
|
25
|
+
"@rsbuild/core": "^1.7.3",
|
|
26
|
+
"@rslib/core": "^0.20.0",
|
|
27
|
+
"@rstest/core": "^0.9.2",
|
|
28
|
+
"@rstest/coverage-istanbul": "^0.3.0",
|
|
29
|
+
"@types/node": "^20.0.0",
|
|
30
|
+
"typescript": "^5.0.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@rsbuild/core": ">=1.0.0",
|
|
34
|
+
"@rspack/core": ">=1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "rslib build",
|
|
38
|
+
"dev": "rslib build --watch",
|
|
39
|
+
"test": "rstest run",
|
|
40
|
+
"test:coverage": "rstest run --coverage"
|
|
41
|
+
}
|
|
42
|
+
}
|