Supporting multri entry

This commit is contained in:
Miel Truyen 2023-05-02 05:05:42 +02:00
parent 4006f3954e
commit 9768b3efe5
10 changed files with 193 additions and 13 deletions

View File

@ -64,8 +64,9 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
let htmlModules = new Map<string, HtmlModule>();// todo clean this per new build? let htmlModules = new Map<string, HtmlModule>();// todo clean this per new build?
let virtualSources = new Map<string, string>(); let virtualSources = new Map<string, string>();
const pluginName = 'html2';
return { return {
name: 'html2',// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one name: pluginName,// TODO: Need a better name, original plugin was just named `html` and might still make sense to use in conjunction with this one
resolveId: { resolveId: {
async handler(specifier: string, async handler(specifier: string,
@ -95,6 +96,13 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
htmlModules.set(htmlModule.id, htmlModule); htmlModules.set(htmlModule.id, htmlModule);
// TODO: trigger special handling when imported from a JS file (in which case we want might want to export a module returning the HTML, instead of HTML directly) // TODO: trigger special handling when imported from a JS file (in which case we want might want to export a module returning the HTML, instead of HTML directly)
return {
...resolved,
meta: {
...resolved.meta,
[pluginName]: {name: specifier}
}
}
} }
} }
}, },
@ -132,20 +140,18 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
sourceId = makeInlineId(id, node, 'js'); sourceId = makeInlineId(id, node, 'js');
} }
if(source){ if(source){
virtualSources.set(sourceId, source);// TODO actually loading in the virtual source (if any) virtualSources.set(sourceId, source);
} }
const resolved = await this.resolve(sourceId, id, { const resolved = await this.resolve(sourceId, id, {
isEntry: type==='entryChunk', isEntry: type==='entryChunk',
}); });
// if(!resolved){ if(!resolved){
// throw new Error(`Could not resolve ${sourceId} from ${id}`); throw new Error(`Could not resolve ${sourceId} from ${id}`);
// } }
// const loaded = await this.load({
// id: sourceId, const selfInfo = this.getModuleInfo(id);
// resolveDependencies: true, const importName = (source && selfInfo?.meta[pluginName].name) ? makeInlineId(selfInfo?.meta[pluginName].name, node, extname(sourceId)) : undefined;
// moduleSideEffects: 'no-treeshake'
// });
const htmlImport: HtmlImport = { const htmlImport: HtmlImport = {
id: <string>sourceId, id: <string>sourceId,
@ -158,6 +164,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
(resolved && (['chunk','entryChunk'].includes(type!))) ? this.emitFile({ (resolved && (['chunk','entryChunk'].includes(type!))) ? this.emitFile({
type: 'chunk', // Might want to adapt, or make configurable (see LoadType) type: 'chunk', // Might want to adapt, or make configurable (see LoadType)
id: resolved.id, id: resolved.id,
name: importName,
importer: id, importer: id,
}) : null, }) : null,
placeholder: `html-import-${crypto.randomBytes(32).toString('base64')}`, placeholder: `html-import-${crypto.randomBytes(32).toString('base64')}`,
@ -198,6 +205,7 @@ export default function html(opts: RollupHtmlOptions = {}): Plugin {
} }
} }
// TODO when importing html from .js this will not do. (
const htmlJSModule = [ const htmlJSModule = [
...moduleImports, ...moduleImports,
``, ``,

View File

@ -60,9 +60,9 @@ Generated by [AVA](https://avajs.dev).
[ [
{ {
code: undefined, code: undefined,
fileName: 'script.html.body.script-e3b82208.js.map', fileName: 'script.html.body.script.js-e3b82208.js.map',
map: undefined, map: undefined,
source: '{"version":3,"file":"script.html.body.script-e3b82208.js","sources":["../batman.js","../script.html.body.script.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n","\\n import {b} from \\"./batman.js\\";\\n document.body.appendChild(\\n document.createTextNode(`Inline script including ${b()}`)\\n );\\n "],"names":[],"mappings":"AAAO,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;ACCJ,QAAQ,CAAC,IAAI,CAAC,WAAW;AACrC,gBAAgB,QAAQ,CAAC,cAAc,CAAC,CAAC,wBAAwB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,aAAa"}', source: '{"version":3,"file":"script.html.body.script.js-e3b82208.js","sources":["../batman.js","../script.html.body.script.js"],"sourcesContent":["export const b = ()=>\'batman\';\\nconsole.log(b());\\n","\\n import {b} from \\"./batman.js\\";\\n document.body.appendChild(\\n document.createTextNode(`Inline script including ${b()}`)\\n );\\n "],"names":[],"mappings":"AAAO,MAAM,CAAC,GAAG,IAAI,QAAQ,CAAC;AAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;;ACCJ,QAAQ,CAAC,IAAI,CAAC,WAAW;AACrC,gBAAgB,QAAQ,CAAC,cAAc,CAAC,CAAC,wBAAwB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACzE,aAAa"}',
}, },
{ {
code: undefined, code: undefined,
@ -77,7 +77,7 @@ Generated by [AVA](https://avajs.dev).
document.body.appendChild(␊ document.body.appendChild(␊
document.createTextNode(\`Inline script including ${b()}\`)␊ document.createTextNode(\`Inline script including ${b()}\`)␊
);␊ );␊
//# sourceMappingURL=script.html.body.script-e3b82208.js.map␊ //# sourceMappingURL=script.html.body.script.js-e3b82208.js.map␊
</script> </script>

Binary file not shown.

View File

@ -0,0 +1,12 @@
<html>
<head>
</head>
<body>
<div id="root"></div>
<script type="module">
import {bootstrap} from "../app/app.js"
import {adminDeps} from "../app/admin-deps.js";
bootstrap(document.getElementById('root'), adminDeps());
</script>
</body>
</html>

View File

@ -0,0 +1,3 @@
export function adminDeps(){
return "robin!";
}

View File

@ -0,0 +1,6 @@
export const bootstrap = (el,deps = [])=>{
el.innerHtml = `
<div>I'm "annoying" ${"in case we need to test \`string\` escaping."}. Hence this file \'tries\' to include all allowed forms of 'it'</div>
<div>Deps: ${deps}</div>
`;
}

View File

@ -0,0 +1,11 @@
<html>
<head>
</head>
<body>
<div id="root"></div>
<script type="module">
import {bootstrap} from "./app/app.js"
bootstrap(document.getElementById('root'), "<none>");
</script>
</body>
</html>

View File

@ -0,0 +1,100 @@
# Snapshot report for `test/multi-entry/test.js`
The actual snapshot is saved in `test.js.snap`.
Generated by [AVA](https://avajs.dev).
## multi-entry
> Snapshot 1
[
{
code: `const bootstrap = (el,deps = [])=>{␊
el.innerHtml = \`␊
<div>I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this file \\'tries\\' to include all allowed forms of 'it'</div>
<div>Deps: ${deps}</div>
\`;␊
};␊
export { bootstrap as b };␊
//# sourceMappingURL=app-01141b67.js.map␊
`,
fileName: 'app-01141b67.js',
map: SourceMap {
file: 'app-01141b67.js',
mappings: 'AAAY,MAAC,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,GAAG;AACzC,IAAI,EAAE,CAAC,SAAS,GAAG,CAAC;AACpB,4BAA4B,EAAE,8CAA8C,CAAC;AAC7E,mBAAmB,EAAE,IAAI,CAAC;AAC1B,IAAI,CAAC,CAAC;AACN;;;;',
names: [],
sources: [
'../app/app.js',
],
sourcesContent: [
`export const bootstrap = (el,deps = [])=>{␊
el.innerHtml = \`␊
<div>I'm "annoying" ${"in case we need to test \\\`string\\\` escaping."}. Hence this file \\'tries\\' to include all allowed forms of 'it'</div>
<div>Deps: ${deps}</div>
\`;␊
}␊
`,
],
version: 3,
},
source: undefined,
},
{
code: undefined,
fileName: 'index.html.body.script.js-45303f0f.js.map',
map: undefined,
source: '{"version":3,"file":"index.html.body.script.js-45303f0f.js","sources":["../index.html.body.script.js"],"sourcesContent":["\\n import {bootstrap} from \\"./app/app.js\\"\\n bootstrap(document.getElementById(\'root\'), \\"<none>\\");\\n "],"names":[],"mappings":";;AAEY,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC"}',
},
{
code: undefined,
fileName: 'admin/index.html.body.script.js-15dfaff3.js.map',
map: undefined,
source: '{"version":3,"file":"index.html.body.script.js-15dfaff3.js","sources":["../../app/admin-deps.js","../../admin/index.html.body.script.js"],"sourcesContent":["export function adminDeps(){\\n return \\"robin!\\";\\n}\\n","\\n import {bootstrap} from \\"../app/app.js\\"\\n import {adminDeps} from \\"../app/admin-deps.js\\";\\n bootstrap(document.getElementById(\'root\'), adminDeps());\\n "],"names":[],"mappings":";;AAAO,SAAS,SAAS,EAAE;AAC3B,IAAI,OAAO,QAAQ,CAAC;AACpB;;ACCY,SAAS,CAAC,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC"}',
},
{
code: undefined,
fileName: 'app-01141b67.js.map',
map: undefined,
source: '{"version":3,"file":"app-01141b67.js","sources":["../app/app.js"],"sourcesContent":["export const bootstrap = (el,deps = [])=>{\\n el.innerHtml = `\\n <div>I\'m \\"annoying\\" ${\\"in case we need to test \\\\`string\\\\` escaping.\\"}. Hence this file \\\\\'tries\\\\\' to include all allowed forms of \'it\'</div>\\n <div>Deps: ${deps}</div>\\n `;\\n}\\n"],"names":[],"mappings":"AAAY,MAAC,SAAS,GAAG,CAAC,EAAE,CAAC,IAAI,GAAG,EAAE,GAAG;AACzC,IAAI,EAAE,CAAC,SAAS,GAAG,CAAC;AACpB,4BAA4B,EAAE,8CAA8C,CAAC;AAC7E,mBAAmB,EAAE,IAAI,CAAC;AAC1B,IAAI,CAAC,CAAC;AACN;;;;"}',
},
{
code: undefined,
fileName: 'index.html',
map: undefined,
source: `<html><head>
</head>
<body>
<div id="root"></div>
<script type="module">import { b as bootstrap } from './app-01141b67.js';
bootstrap(document.getElementById('root'), "<none>");␊
//# sourceMappingURL=index.html.body.script.js-45303f0f.js.map␊
</script>
</body></html>`,
},
{
code: undefined,
fileName: 'admin/index.html',
map: undefined,
source: `<html><head>
</head>
<body>
<div id="root"></div>
<script type="module">import { b as bootstrap } from '../app-01141b67.js';
function adminDeps(){␊
return "robin!";␊
}␊
bootstrap(document.getElementById('root'), adminDeps());␊
//# sourceMappingURL=index.html.body.script.js-15dfaff3.js.map␊
</script>
</body></html>`,
},
]

Binary file not shown.

40
test/multi-entry/test.js Normal file
View File

@ -0,0 +1,40 @@
import {join, dirname} from "node:path";
import test from "ava";
import { rollup } from "rollup";
import {debugPrintOutput, getCode} from "../util/test.js";
import html from "../../src/index.ts";
const output = {
dir: 'output', // Output all files
format: 'es', // iifi and cjs should be added to tests
sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
};
import {fileURLToPath} from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
process.chdir(join(__dirname, 'fixtures'));
test.serial('multi-entry', async (t) => {
const bundle = await rollup({
input: {
['index']: 'index.html',
['admin/index']: 'admin/index.html'
},
plugins: [
html({
}),
]
});
const code = await getCode(bundle, output, true);
debugPrintOutput('multi-entry',code);
t.snapshot(code);
});
// TODO various parameters
// - format: cjs, iifi, ...
// - sourcemap: inline, false, (and the various exotic sourcemap options)
// Watch mode tests would be its own dir
// ...