mirror of
https://github.com/jlengrand/open-wc.git
synced 2026-03-10 08:31:19 +00:00
feat: support building of multi page applications (mpa)
This commit is contained in:
committed by
Thomas Allmer
parent
f2734ec623
commit
a65453576c
@@ -0,0 +1,3 @@
|
||||
import './js/homepage-side-effect-dep.js';
|
||||
|
||||
window.__homepageSideEffectMetaUrl = import.meta.url;
|
||||
2
packages/building-rollup/demo/mpa/homepage.js
Normal file
2
packages/building-rollup/demo/mpa/homepage.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { homepageDepMetaUrl } from './js/homepage-dep.js';
|
||||
export const homepageMetaUrl = import.meta.url;
|
||||
49
packages/building-rollup/demo/mpa/index.html
Normal file
49
packages/building-rollup/demo/mpa/index.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta http-equiv="expires" content="0" />
|
||||
|
||||
<title>My Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Static content in index.html is preserved</h1>
|
||||
|
||||
<a href="./subpage/">SubPage</a>
|
||||
|
||||
<div id="test"></div>
|
||||
|
||||
<script type="module" src="./homepage-side-effect.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { homepageMetaUrl, homepageDepMetaUrl } from './homepage.js';
|
||||
import { navigationMetaUrl } from './navigation.js';
|
||||
|
||||
function extractServiceWorkerScriptUrl() {
|
||||
const code = document.querySelectorAll('script')[2].textContent;
|
||||
const start = code.indexOf('navigator.serviceWorker.register(');
|
||||
const end = code.indexOf(')', start + 1);
|
||||
return code.substring(start + 34, end - 1);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
window.__tests = {
|
||||
homepageMetaUrl,
|
||||
homepageDepMetaUrl,
|
||||
navigationMetaUrl,
|
||||
__homepageSideEffectMetaUrl: window.__homepageSideEffectMetaUrl,
|
||||
__homepageSideEffectDepMetaUrl: window.__homepageSideEffectDepMetaUrl,
|
||||
serviceWorkerScriptUrl: extractServiceWorkerScriptUrl(),
|
||||
};
|
||||
|
||||
document.getElementById('test').innerHTML = `<pre>${JSON.stringify(
|
||||
window.__tests,
|
||||
null,
|
||||
2,
|
||||
)}</pre>`;
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
packages/building-rollup/demo/mpa/js/homepage-dep.js
Normal file
1
packages/building-rollup/demo/mpa/js/homepage-dep.js
Normal file
@@ -0,0 +1 @@
|
||||
export const homepageDepMetaUrl = import.meta.url;
|
||||
@@ -0,0 +1 @@
|
||||
window.__homepageSideEffectDepMetaUrl = import.meta.url;
|
||||
1
packages/building-rollup/demo/mpa/js/subpage-dep.js
Normal file
1
packages/building-rollup/demo/mpa/js/subpage-dep.js
Normal file
@@ -0,0 +1 @@
|
||||
export const subpageDepMetaUrl = import.meta.url;
|
||||
@@ -0,0 +1 @@
|
||||
window.__subpageSideEffectDepMetaUrl = import.meta.url;
|
||||
1
packages/building-rollup/demo/mpa/navigation.js
Normal file
1
packages/building-rollup/demo/mpa/navigation.js
Normal file
@@ -0,0 +1 @@
|
||||
export const navigationMetaUrl = import.meta.url;
|
||||
12
packages/building-rollup/demo/mpa/rollup.mpa.config.js
Normal file
12
packages/building-rollup/demo/mpa/rollup.mpa.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
const merge = require('deepmerge');
|
||||
const { createMpaConfig } = require('../../index.js');
|
||||
|
||||
const baseConfig = createMpaConfig({
|
||||
developmentMode: true,
|
||||
injectServiceWorker: true,
|
||||
rootDir: 'demo/mpa',
|
||||
});
|
||||
|
||||
module.exports = merge(baseConfig, {
|
||||
input: '**/*.html',
|
||||
});
|
||||
49
packages/building-rollup/demo/mpa/subpage/index.html
Normal file
49
packages/building-rollup/demo/mpa/subpage/index.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
<meta http-equiv="expires" content="0" />
|
||||
|
||||
<title>My Demo Subpage</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Static content in subpage/index.html is preserved</h1>
|
||||
|
||||
<div id="test"></div>
|
||||
|
||||
<script type="module" src="./subpage-side-effect.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import { subpageMetaUrl, subpageDepMetaUrl } from './subpage.js';
|
||||
// supports absolute URLs as well
|
||||
import { navigationMetaUrl } from '/navigation.js';
|
||||
|
||||
function extractServiceWorkerScriptUrl() {
|
||||
const code = document.querySelectorAll('script')[2].textContent;
|
||||
const start = code.indexOf('navigator.serviceWorker.register(');
|
||||
const end = code.indexOf(')', start + 1);
|
||||
return code.substring(start + 34, end - 1);
|
||||
}
|
||||
|
||||
(async () => {
|
||||
window.__tests = {
|
||||
subpageMetaUrl,
|
||||
subpageDepMetaUrl,
|
||||
navigationMetaUrl,
|
||||
__subpageSideEffectMetaUrl: window.__subpageSideEffectMetaUrl,
|
||||
__subpageSideEffectDepMetaUrl: window.__subpageSideEffectDepMetaUrl,
|
||||
serviceWorkerScriptUrl: navigator.serviceWorker.controller.scriptURL,
|
||||
serviceWorkerScriptUrl: extractServiceWorkerScriptUrl(),
|
||||
};
|
||||
|
||||
document.getElementById('test').innerHTML = `<pre>${JSON.stringify(
|
||||
window.__tests,
|
||||
null,
|
||||
2,
|
||||
)}</pre>`;
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
import '../js/subpage-side-effect-dep.js';
|
||||
|
||||
window.__subpageSideEffectMetaUrl = import.meta.url;
|
||||
2
packages/building-rollup/demo/mpa/subpage/subpage.js
Normal file
2
packages/building-rollup/demo/mpa/subpage/subpage.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { subpageDepMetaUrl } from '../js/subpage-dep.js';
|
||||
export const subpageMetaUrl = import.meta.url;
|
||||
@@ -5,5 +5,6 @@
|
||||
|
||||
const { createBasicConfig } = require('./src/createBasicConfig');
|
||||
const { createSpaConfig } = require('./src/createSpaConfig');
|
||||
const { createMpaConfig } = require('./src/createMpaConfig');
|
||||
|
||||
module.exports = { createBasicConfig, createSpaConfig };
|
||||
module.exports = { createBasicConfig, createSpaConfig, createMpaConfig };
|
||||
|
||||
@@ -19,16 +19,18 @@
|
||||
"build:basic": "rimraf dist && rollup -c demo/js/rollup.basic.config.js",
|
||||
"build:cjs": "rimraf dist && rollup -c demo/cjs/rollup.spa.config.js",
|
||||
"build:modify-babel-plugin": "rimraf dist && rollup -c demo/modify-babel-plugin/rollup.config.js",
|
||||
"build:mpa": "rimraf dist && rollup -c demo/mpa/rollup.mpa.config.js",
|
||||
"build:spa": "rimraf dist && rollup -c demo/js/rollup.spa.config.js",
|
||||
"build:spa-js-input": "rimraf dist && rollup -c demo/js/rollup.spa-js-input.config.js",
|
||||
"build:spa-nomodule": "rimraf dist && rollup -c demo/js/rollup.spa-nomodule.config.js",
|
||||
"build:ts": "rimraf dist && rollup -c demo/ts/rollup.spa.config.js",
|
||||
"prepublishOnly": "../../scripts/insert-header.js",
|
||||
"start:babelrc": "npm run build:babelrc && npm run start:build",
|
||||
"start:build": "es-dev-server --root-dir dist --compatibility none --open",
|
||||
"start:build": "node ../es-dev-server/dist/cli.js --root-dir dist --compatibility none --open",
|
||||
"start:cjs": "npm run build:cjs && npm run start:build",
|
||||
"start:demo": "es-dev-server --app-index demo/js/index.html --open --compatibility none",
|
||||
"start:demo": "node ../es-dev-server/dist/cli.js --app-index demo/js/index.html --open --compatibility none",
|
||||
"start:modify-babel-plugin": "npm run build:modify-babel-plugin && npm run start:build",
|
||||
"start:mpa": "npm run build:mpa && npm run start:build",
|
||||
"start:spa": "npm run build:spa && npm run start:build",
|
||||
"start:spa-js-input": "npm run build:spa-js-input && npm run start:build",
|
||||
"start:spa-nomodule": "npm run build:spa-nomodule && npm run start:build",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { babelPluginBundledHelpers } = require('./babel-plugin-bundled-helpers');
|
||||
const { isFalsy } = require('../utils');
|
||||
|
||||
const createBabelConfigRollupBuild = developmentMode => ({
|
||||
const createBabelConfigRollupBuild = ({ developmentMode, rootDir }) => ({
|
||||
babelHelpers: 'bundled',
|
||||
compact: true,
|
||||
plugins: [
|
||||
@@ -11,7 +11,7 @@ const createBabelConfigRollupBuild = developmentMode => ({
|
||||
|
||||
// plugins that aren't part of @babel/preset-env should be applied regularly in
|
||||
// the rollup build phase
|
||||
require.resolve('babel-plugin-bundled-import-meta'),
|
||||
[require.resolve('babel-plugin-bundled-import-meta'), { bundleDir: rootDir }],
|
||||
!developmentMode && [
|
||||
require.resolve('babel-plugin-template-html-minifier'),
|
||||
{
|
||||
|
||||
@@ -28,7 +28,7 @@ function createBasicConfig(userOptions = {}) {
|
||||
},
|
||||
userOptions,
|
||||
);
|
||||
const { developmentMode } = userOptions;
|
||||
const { developmentMode, rootDir } = userOptions;
|
||||
const fileName = `[${developmentMode ? 'name' : 'hash'}].js`;
|
||||
const assetName = `[${developmentMode ? 'name' : 'hash'}][extname]`;
|
||||
|
||||
@@ -60,7 +60,11 @@ function createBasicConfig(userOptions = {}) {
|
||||
|
||||
// build non-standard syntax to standard syntax and other babel optimization plugins
|
||||
// user plugins are deduped to allow overriding
|
||||
dedupedBabelPlugin(babel, opts.babel, createBabelConfigRollupBuild(developmentMode)),
|
||||
dedupedBabelPlugin(
|
||||
babel,
|
||||
opts.babel,
|
||||
createBabelConfigRollupBuild({ developmentMode, rootDir }),
|
||||
),
|
||||
|
||||
// minify js code
|
||||
!developmentMode && pluginWithOptions(terser, opts.terser, { output: { comments: false } }),
|
||||
|
||||
20
packages/building-rollup/src/createMpaConfig.js
Normal file
20
packages/building-rollup/src/createMpaConfig.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/* eslint-disable */
|
||||
/** @typedef {import('./types').MpaOptions} MpaOptions */
|
||||
|
||||
const merge = require('deepmerge');
|
||||
const { createSpaConfig } = require('./createSpaConfig.js');
|
||||
|
||||
/**
|
||||
* @param {MpaOptions} options
|
||||
*/
|
||||
function createMpaConfig(options) {
|
||||
const userOptions = merge(
|
||||
{
|
||||
html: { flatten: false },
|
||||
},
|
||||
options,
|
||||
);
|
||||
return createSpaConfig(userOptions);
|
||||
}
|
||||
|
||||
module.exports = { createMpaConfig };
|
||||
@@ -8,12 +8,7 @@ const polyfillsLoader = require('@open-wc/rollup-plugin-polyfills-loader');
|
||||
const path = require('path');
|
||||
const { generateSW } = require('rollup-plugin-workbox');
|
||||
const { createBasicConfig } = require('./createBasicConfig');
|
||||
const {
|
||||
pluginWithOptions,
|
||||
applyServiceWorkerRegistration,
|
||||
isFalsy,
|
||||
createSwPath,
|
||||
} = require('./utils');
|
||||
const { pluginWithOptions, applyServiceWorkerRegistration, isFalsy } = require('./utils');
|
||||
const { defaultPolyfills } = require('./polyfills');
|
||||
|
||||
/**
|
||||
@@ -34,8 +29,19 @@ function createSpaConfig(options) {
|
||||
);
|
||||
let outputDir = basicConfig.output.dir;
|
||||
|
||||
const swPath = createSwPath(userOptions, outputDir);
|
||||
const applySw = htmlString => applyServiceWorkerRegistration(htmlString, swPath);
|
||||
if (userOptions.rootDir) {
|
||||
if (typeof userOptions.html === 'boolean' && userOptions.html) {
|
||||
userOptions.html = {
|
||||
rootDir: userOptions.rootDir,
|
||||
};
|
||||
}
|
||||
if (typeof userOptions.html === 'object') {
|
||||
userOptions.html.rootDir = userOptions.rootDir;
|
||||
}
|
||||
}
|
||||
|
||||
const applySw = (htmlString, transformOptions) =>
|
||||
applyServiceWorkerRegistration(htmlString, transformOptions, userOptions, outputDir);
|
||||
|
||||
const htmlPlugin = pluginWithOptions(html, userOptions.html, {
|
||||
minify: !userOptions.developmentMode,
|
||||
|
||||
13
packages/building-rollup/src/types.d.ts
vendored
13
packages/building-rollup/src/types.d.ts
vendored
@@ -1,3 +1,5 @@
|
||||
import { PluginOptions } from '@open-wc/rollup-plugin-html';
|
||||
|
||||
export interface BasicOptions {
|
||||
outputDir?: string;
|
||||
nodeResolve?: boolean | object;
|
||||
@@ -5,16 +7,19 @@ export interface BasicOptions {
|
||||
terser?: boolean | object;
|
||||
legacyBuild?: boolean;
|
||||
developmentMode?: boolean;
|
||||
rootDir?: string;
|
||||
}
|
||||
|
||||
export interface SpaOptions extends BasicOptions {
|
||||
html?: boolean | object;
|
||||
html?: boolean | PluginOptions;
|
||||
polyfillsLoader?: boolean | object;
|
||||
workbox?: boolean | WorkboxOptions;
|
||||
injectServiceWorker?: boolean;
|
||||
}
|
||||
|
||||
export interface MpaOptions extends SpaOptions {}
|
||||
|
||||
interface WorkboxOptions {
|
||||
swDest?: string,
|
||||
globDirectory?: string,
|
||||
}
|
||||
swDest?: string;
|
||||
globDirectory?: string;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** @typedef {import('./types').SpaOptions} SpaOptions */
|
||||
|
||||
const merge = require('deepmerge');
|
||||
const path = require('path');
|
||||
const { createScript } = require('@open-wc/building-utils');
|
||||
const { parse, serialize } = require('parse5');
|
||||
const { append, predicates, query } = require('@open-wc/building-utils/dom5-fork');
|
||||
@@ -39,11 +40,30 @@ function pluginWithOptions(plugin, userConfig, defaultConfig, ...otherParams) {
|
||||
return plugin(config, ...otherParams);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpaOptions} userOptions
|
||||
* @param {string} outputDir
|
||||
* @param {string} htmlFileName
|
||||
*/
|
||||
function createSwPath(userOptions, outputDir, htmlFileName) {
|
||||
let swPath;
|
||||
if (typeof userOptions.workbox === 'object' && userOptions.workbox.swDest) {
|
||||
swPath = userOptions.workbox.swDest.replace(`${outputDir}/`, '');
|
||||
} else {
|
||||
swPath = './sw.js';
|
||||
}
|
||||
|
||||
swPath = path.relative(path.dirname(htmlFileName), swPath);
|
||||
return swPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} htmlString
|
||||
* @returns {string}
|
||||
*/
|
||||
function applyServiceWorkerRegistration(htmlString, swPath) {
|
||||
function applyServiceWorkerRegistration(htmlString, transformOptions, userOptions, outputDir) {
|
||||
const swPath = createSwPath(userOptions, outputDir, transformOptions.htmlFileName);
|
||||
const documentAst = parse(htmlString);
|
||||
const body = query(documentAst, predicates.hasTagName('body'));
|
||||
const swRegistration = createScript(
|
||||
@@ -68,21 +88,6 @@ function applyServiceWorkerRegistration(htmlString, swPath) {
|
||||
return serialize(documentAst);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {SpaOptions} userOptions
|
||||
* @param {string} outputDir
|
||||
*/
|
||||
function createSwPath(userOptions, outputDir) {
|
||||
let swPath;
|
||||
if (typeof userOptions.workbox === 'object' && userOptions.workbox.swDest) {
|
||||
swPath = userOptions.workbox.swDest.replace(`${outputDir}/`, '');
|
||||
} else {
|
||||
swPath = './sw.js';
|
||||
}
|
||||
return swPath;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isFalsy,
|
||||
pluginWithOptions,
|
||||
|
||||
96
packages/building-rollup/test/mpa-integration.test.js
Normal file
96
packages/building-rollup/test/mpa-integration.test.js
Normal file
@@ -0,0 +1,96 @@
|
||||
/* eslint-disable global-require, import/no-dynamic-require */
|
||||
const puppeteer = require('puppeteer');
|
||||
const { expect } = require('chai');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const rimraf = require('rimraf');
|
||||
const { rollup } = require('rollup');
|
||||
const { startServer, createConfig } = require('es-dev-server');
|
||||
|
||||
const rootDir = path.resolve(__dirname, '..', 'dist');
|
||||
|
||||
describe('integration tests', () => {
|
||||
let server;
|
||||
let serverConfig;
|
||||
/** @type {import('puppeteer').Browser} */
|
||||
let browser;
|
||||
|
||||
before(async () => {
|
||||
serverConfig = createConfig({
|
||||
port: 8081,
|
||||
rootDir,
|
||||
});
|
||||
|
||||
({ server } = await startServer(serverConfig));
|
||||
browser = await puppeteer.launch();
|
||||
rimraf.sync(rootDir);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await browser.close();
|
||||
await new Promise(resolve =>
|
||||
server.close(() => {
|
||||
resolve();
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
describe(`Mpa Config`, function describe() {
|
||||
this.timeout(10000);
|
||||
let page;
|
||||
|
||||
before(async () => {
|
||||
rimraf.sync(rootDir);
|
||||
const configPath = path.join(__dirname, '..', 'demo', 'mpa', 'rollup.mpa.config.js');
|
||||
const config = require(configPath);
|
||||
const bundle = await rollup(config);
|
||||
if (Array.isArray(config.output)) {
|
||||
await Promise.all([bundle.write(config.output[0]), bundle.write(config.output[1])]);
|
||||
} else {
|
||||
await bundle.write(config.output);
|
||||
}
|
||||
|
||||
page = await browser.newPage();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
rimraf.sync(rootDir);
|
||||
});
|
||||
|
||||
it('passes the in-browser tests for index.html', async () => {
|
||||
await page.goto('http://localhost:8081/', {
|
||||
waitUntil: 'networkidle0',
|
||||
});
|
||||
// @ts-ignore
|
||||
const browserTests = await page.evaluate(() => window.__tests);
|
||||
expect(browserTests).to.eql({
|
||||
homepageMetaUrl: 'http://localhost:8081/homepage.js',
|
||||
homepageDepMetaUrl: 'http://localhost:8081/js/homepage-dep.js',
|
||||
__homepageSideEffectMetaUrl: 'http://localhost:8081/homepage-side-effect.js',
|
||||
__homepageSideEffectDepMetaUrl: 'http://localhost:8081/js/homepage-side-effect-dep.js',
|
||||
navigationMetaUrl: 'http://localhost:8081/navigation.js',
|
||||
serviceWorkerScriptUrl: 'sw.js',
|
||||
});
|
||||
});
|
||||
|
||||
it('passes the in-browser tests for subpage/index.html', async () => {
|
||||
await page.goto('http://localhost:8081/subpage/', {
|
||||
waitUntil: 'networkidle0',
|
||||
});
|
||||
// @ts-ignore
|
||||
const browserTests = await page.evaluate(() => window.__tests);
|
||||
expect(browserTests).to.eql({
|
||||
subpageMetaUrl: 'http://localhost:8081/subpage/subpage.js',
|
||||
subpageDepMetaUrl: 'http://localhost:8081/js/subpage-dep.js',
|
||||
__subpageSideEffectMetaUrl: 'http://localhost:8081/subpage/subpage-side-effect.js',
|
||||
__subpageSideEffectDepMetaUrl: 'http://localhost:8081/js/subpage-side-effect-dep.js',
|
||||
navigationMetaUrl: 'http://localhost:8081/navigation.js',
|
||||
serviceWorkerScriptUrl: '../sw.js',
|
||||
});
|
||||
});
|
||||
|
||||
it('outputs a service worker', () => {
|
||||
expect(fs.existsSync(path.join(rootDir, 'sw.js'))).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -13,11 +13,12 @@ describe('createSwPath', () => {
|
||||
},
|
||||
},
|
||||
'dist',
|
||||
'index.html',
|
||||
),
|
||||
).to.equal('./foo.js');
|
||||
).to.equal('foo.js');
|
||||
});
|
||||
|
||||
it('uses "./sw.js" as swPath if no swDest is provided by the workbox config', () => {
|
||||
it('uses "sw.js" as swPath if no swDest is provided by the workbox config', () => {
|
||||
expect(
|
||||
createSwPath(
|
||||
{
|
||||
@@ -26,26 +27,29 @@ describe('createSwPath', () => {
|
||||
},
|
||||
},
|
||||
'dist',
|
||||
'index.html',
|
||||
),
|
||||
).to.equal('./sw.js');
|
||||
).to.equal('sw.js');
|
||||
});
|
||||
|
||||
it('returns "./sw.js" as swPath if the workbox property is a boolean', () => {
|
||||
it('returns "sw.js" as swPath if the workbox property is a boolean', () => {
|
||||
expect(
|
||||
createSwPath(
|
||||
{
|
||||
workbox: true,
|
||||
},
|
||||
'dist',
|
||||
'index.html',
|
||||
),
|
||||
).to.equal('./sw.js');
|
||||
).to.equal('sw.js');
|
||||
expect(
|
||||
createSwPath(
|
||||
{
|
||||
workbox: false,
|
||||
},
|
||||
'dist',
|
||||
'index.html',
|
||||
),
|
||||
).to.equal('./sw.js');
|
||||
).to.equal('sw.js');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -61,4 +61,4 @@
|
||||
"lit-html": "^1.0.0",
|
||||
"lit-element": "^2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,15 @@ const { createHtmlAsset, createHtmlAssets } = require('./src/createHtmlAssets');
|
||||
const watchMode = process.env.ROLLUP_WATCH === 'true';
|
||||
const defaultFileName = 'index.html';
|
||||
|
||||
/**
|
||||
* @param {string} id
|
||||
* @param {string} rootDir
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isAbsoluteUrl(id, rootDir) {
|
||||
return id.startsWith('/') && !id.startsWith(rootDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PluginOptions} pluginOptions
|
||||
* @returns {RollupPluginHtml}
|
||||
@@ -128,6 +137,9 @@ function rollupPluginHtml(pluginOptions) {
|
||||
},
|
||||
|
||||
resolveId(id) {
|
||||
if (pluginOptions.rootDir && isAbsoluteUrl(id, pluginOptions.rootDir)) {
|
||||
return path.join(pluginOptions.rootDir, id);
|
||||
}
|
||||
for (const file of htmlFiles) {
|
||||
if (file.inlineModules && file.inlineModules.has(id)) {
|
||||
return id;
|
||||
|
||||
@@ -39,6 +39,7 @@ async function createHtmlAsset(
|
||||
entrypointBundles,
|
||||
html,
|
||||
externalTransformFns,
|
||||
htmlFileName,
|
||||
});
|
||||
return {
|
||||
fileName: htmlFileName,
|
||||
|
||||
@@ -39,7 +39,7 @@ function createImportPath({ publicPath, mainOutputDir, fileOutputDir, htmlFileNa
|
||||
* @param {PluginOptions} args.pluginOptions
|
||||
* @param {GeneratedBundle[]} args.generatedBundles
|
||||
* @param {string} args.mainOutputDir
|
||||
* @param {string} args.htmlFileName
|
||||
* @param {string | undefined} [args.htmlFileName]
|
||||
* @param {string[] | undefined} [args.inputModuleIds]
|
||||
*/
|
||||
function getEntrypointBundles({
|
||||
|
||||
@@ -15,8 +15,15 @@ const defaultHtml = '<!DOCTYPE html><html><head><meta charset="utf-8"></head><bo
|
||||
* @param {Record<string, EntrypointBundle>} args.entrypointBundles
|
||||
* @param {TransformFunction[]} [args.externalTransformFns]
|
||||
* @param {string | undefined} [args.html]
|
||||
* @param {string | undefined} [args.htmlFileName]
|
||||
*/
|
||||
async function getOutputHtml({ pluginOptions, entrypointBundles, externalTransformFns, html }) {
|
||||
async function getOutputHtml({
|
||||
pluginOptions,
|
||||
entrypointBundles,
|
||||
externalTransformFns,
|
||||
html,
|
||||
htmlFileName,
|
||||
}) {
|
||||
const { template, inject, minify } = pluginOptions;
|
||||
let outputHtml;
|
||||
|
||||
@@ -55,6 +62,7 @@ async function getOutputHtml({ pluginOptions, entrypointBundles, externalTransfo
|
||||
outputHtml = await transform(outputHtml, {
|
||||
bundle: defaultBundle,
|
||||
bundles: multiBundles,
|
||||
htmlFileName,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
2
packages/rollup-plugin-html/src/types.d.ts
vendored
2
packages/rollup-plugin-html/src/types.d.ts
vendored
@@ -25,6 +25,7 @@ export interface PluginOptions {
|
||||
inputHtml?: string;
|
||||
/** @deprecated use files instead */
|
||||
inputPath?: string;
|
||||
htmlFileName?: string;
|
||||
}
|
||||
|
||||
export type MinifyFunction = (html: string) => string | Promise<string>;
|
||||
@@ -68,6 +69,7 @@ export interface TransformArgs {
|
||||
bundle: EntrypointBundle;
|
||||
// see TemplateArgs
|
||||
bundles: Record<string, EntrypointBundle>;
|
||||
htmlFileName: string;
|
||||
}
|
||||
|
||||
export type TransformFunction = (html: string, args: TransformArgs) => string | Promise<string>;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
/** @typedef {import('polyfills-loader').GeneratedFile} GeneratedFile */
|
||||
/** @typedef {import('./src/types').PluginOptions} PluginOptions */
|
||||
|
||||
const path = require('path');
|
||||
const { injectPolyfillsLoader } = require('polyfills-loader');
|
||||
const { createError, shouldInjectLoader } = require('./src/utils');
|
||||
const { createPolyfillsLoaderConfig } = require('./src/createPolyfillsLoaderConfig');
|
||||
@@ -72,7 +73,12 @@ function rollupPluginPolyfillsLoader(pluginOptions = {}) {
|
||||
let preloaded = [];
|
||||
for (const entrypoint of entrypoints) {
|
||||
preloaded.push(entrypoint.importPath);
|
||||
preloaded.push(...entrypoint.chunk.imports);
|
||||
|
||||
// js files (incl. chunks) will always be in the root directory
|
||||
const pathToRoot = path.posix.relative('./', path.posix.dirname(entrypoint.importPath));
|
||||
for (const chunkPath of entrypoint.chunk.imports) {
|
||||
preloaded.push(path.posix.join(pathToRoot, chunkPath));
|
||||
}
|
||||
}
|
||||
preloaded = [...new Set(preloaded)];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user