Skip to content

Commit 62f2eab

Browse files
committed
Deletes empty output client-side JavaScript bundles.
This updates the Rollup config to avoid generating empty bundles. This used to be a warning, but now the bundles are not emitted at all. The build process will properly skip injecting a pointless `<script>` tag, so everything works as expected.
1 parent a1962af commit 62f2eab

5 files changed

Lines changed: 107 additions & 4 deletions

File tree

examples/empty_script/BUILD.bazel

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
load("//:index.bzl", "prerender_pages", "web_resources_devserver")
2+
load("//tools/jasmine:defs.bzl", "jasmine_web_test_suite")
3+
load("//tools/typescript:defs.bzl", "ts_project")
4+
5+
prerender_pages(
6+
name = "site",
7+
entry_point = "./site.js",
8+
prerender = ":prerender",
9+
scripts = ":scripts",
10+
)
11+
12+
ts_project(
13+
name = "prerender",
14+
srcs = ["site.tsx"],
15+
deps = [
16+
"//:node_modules/@rules_prerender/preact",
17+
"//:node_modules/preact",
18+
],
19+
)
20+
21+
ts_project(
22+
name = "scripts",
23+
srcs = ["empty_script.mts"],
24+
)
25+
26+
web_resources_devserver(
27+
name = "devserver",
28+
resources = ":site",
29+
)
30+
31+
ts_project(
32+
name = "test_lib",
33+
srcs = ["test.mts"],
34+
testonly = True,
35+
deps = [
36+
"//common/testing:devserver",
37+
"//common/testing:webdriver",
38+
"//:node_modules/@types/jasmine",
39+
],
40+
)
41+
42+
jasmine_web_test_suite(
43+
name = "test",
44+
browsers = ["//tools/browsers:chromium-local"],
45+
data = [":devserver"],
46+
deps = [":test_lib"],
47+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Empty script, should not be injected into the page.

examples/empty_script/site.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { PrerenderResource, renderToHtml, includeScript } from '@rules_prerender/preact';
2+
3+
export default function*(): Generator<PrerenderResource, void, void> {
4+
yield PrerenderResource.fromHtml('/index.html', renderToHtml(
5+
<html>
6+
<head>
7+
<meta charSet="utf8" />
8+
<title>Empty script</title>
9+
</head>
10+
<body>
11+
<h2>Empty script</h2>
12+
13+
{includeScript('./empty_script.mjs', import.meta)}
14+
</body>
15+
</html>
16+
));
17+
}

examples/empty_script/test.mts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { useDevserver } from '../../common/testing/devserver.mjs';
2+
import { useWebDriver } from '../../common/testing/webdriver.mjs';
3+
4+
describe('empty_scripts', () => {
5+
const devserver = useDevserver('examples/empty_script/devserver.sh');
6+
const wd = useWebDriver(devserver);
7+
8+
describe('index page', () => {
9+
it('renders without a script', async () => {
10+
const browser = wd.get();
11+
await browser.url('/');
12+
13+
expect(await browser.$('h2').getText()).toBe('Empty script');
14+
15+
// Expect only the live reload script.
16+
const scripts = await browser.$$('script');
17+
expect(scripts.length).toBe(1);
18+
});
19+
});
20+
});

packages/rules_prerender/rollup.config.mts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
11
import { nodeResolve } from '@rollup/plugin-node-resolve';
2-
import { RollupOptions } from 'rollup';
2+
import { Plugin, RollupOptions } from 'rollup';
3+
4+
/**
5+
* Deletes any empty output bundles before they are written to disk. This
6+
* prevents the build process from injecting an empty script onto the page.
7+
*/
8+
const deleteEmptyBundles: Plugin = {
9+
name: 'delete-empty-bundles',
10+
11+
// Called right before writing output bundles to disk.
12+
generateBundle(_options, bundle): void {
13+
for (const [ key, value ] of Object.entries(bundle)) {
14+
if (value.type === 'chunk' && value.isEntry && value.code.trim() === '') {
15+
delete bundle[key];
16+
}
17+
}
18+
},
19+
};
320

421
export default {
522
plugins: [
623
// Needed to support absolute imports.
724
nodeResolve({ browser: true }),
25+
deleteEmptyBundles,
826
],
927

1028
// Fail the build on any warning.
1129
onwarn(warning) {
1230
if (warning.code === 'EMPTY_BUNDLE') {
13-
// Give a better suggestion when no JavaScript is generated.
14-
console.warn('Generated an empty JavaScript bundle, do you have'
15-
+ ' any JavaScript?\n\n' + warning.message);
31+
// Ignore empty output errors because the `deleteEmptyBundles`
32+
// plugin will delete them after the fact. This is not considered a
33+
// problem and does not need to warn or error.
1634
return;
1735
}
1836

0 commit comments

Comments
 (0)