Skip to content

Commit 0d3c4b2

Browse files
committed
Adds script isolation example.
Refs #26. This verifies that scripts are only included on pages which actually reference them via `includeScript()`. It ensures that scripts which are _not_ included by the developer are _actually_ not included at runtime.
1 parent 70b63ad commit 0d3c4b2

6 files changed

Lines changed: 173 additions & 0 deletions

File tree

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/typescript:defs.bzl", "ts_project")
3+
load("//tools/jasmine:defs.bzl", "jasmine_web_test_suite")
4+
5+
prerender_pages(
6+
name = "site",
7+
src = "site.ts",
8+
scripts = [":foo", ":bar"],
9+
tsconfig = "//:tsconfig",
10+
source_map = True,
11+
lib_deps = ["//:node_modules/rules_prerender"],
12+
)
13+
14+
ts_project(
15+
name = "foo",
16+
srcs = ["foo.ts"],
17+
tsconfig = "//:tsconfig_client",
18+
)
19+
20+
ts_project(
21+
name = "bar",
22+
srcs = ["bar.ts"],
23+
tsconfig = "//:tsconfig_client",
24+
)
25+
26+
web_resources_devserver(
27+
name = "devserver",
28+
resources = ":site",
29+
)
30+
31+
ts_project(
32+
name = "test_lib",
33+
srcs = ["test.ts"],
34+
testonly = True,
35+
deps = [
36+
"//:node_modules/@types/jasmine",
37+
"//common/testing:devserver",
38+
"//common/testing:webdriver",
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: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Script Isolation
2+
3+
An example which bundles and loads JavaScript on multiple pages and verifies
4+
that only necessary scripts are included on the pages they are required. Scripts
5+
used on one page should not be forced on other pages.

examples/script_isolation/bar.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export {}; // Treat this as an ES module.
2+
3+
if (document.readyState === 'complete'
4+
|| document.readyState === 'interactive') {
5+
// Document already loaded.
6+
update();
7+
} else {
8+
// Wait for document to load.
9+
document.addEventListener('DOMContentLoaded', () => {
10+
update();
11+
});
12+
}
13+
14+
function update(): void {
15+
// Overwrite a prerendered HTML element with different content.
16+
const el = document.getElementById('replace-bar');
17+
if (!el) throw new Error('Could not find `#replace-bar` element.');
18+
el.innerText = 'This text rendered by page JavaScript!';
19+
}

examples/script_isolation/foo.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export {}; // Treat this as an ES module.
2+
3+
if (document.readyState === 'complete'
4+
|| document.readyState === 'interactive') {
5+
// Document already loaded.
6+
update();
7+
} else {
8+
// Wait for document to load.
9+
document.addEventListener('DOMContentLoaded', () => {
10+
update();
11+
});
12+
}
13+
14+
function update(): void {
15+
// Overwrite a prerendered HTML element with different content.
16+
const el = document.getElementById('replace-foo');
17+
if (!el) throw new Error('Could not find `#replace-foo` element.');
18+
el.innerText = 'This text rendered by page JavaScript!';
19+
}

examples/script_isolation/site.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { includeScript, PrerenderResource } from 'rules_prerender';
2+
3+
export default function*(): Generator<PrerenderResource, void, void> {
4+
yield PrerenderResource.of('/index.html', `
5+
<!DOCTYPE html>
6+
<html>
7+
<head>
8+
<title>Script Isolation</title>
9+
<meta charset="utf8">
10+
</head>
11+
<body>
12+
<ul>
13+
<li><a href="/foo.html">Foo</a></li>
14+
<li><a href="/bar.html">Bar</a></li>
15+
</ul>
16+
</body>
17+
</html>
18+
`.trim());
19+
20+
yield PrerenderResource.of('/foo.html', `
21+
<!DOCTYPE html>
22+
<html>
23+
<head>
24+
<title>Script Isolation</title>
25+
<meta charset="utf8">
26+
</head>
27+
<body>
28+
<div id="replace-foo">Text to be replaced.</div>
29+
<div id="replace-bar">Text to be replaced.</div>
30+
${includeScript('examples/script_isolation/foo')}
31+
</body>
32+
</html>
33+
`.trim());
34+
35+
yield PrerenderResource.of('/bar.html', `
36+
<!DOCTYPE html>
37+
<html>
38+
<head>
39+
<title>Script Isolation</title>
40+
<meta charset="utf8">
41+
</head>
42+
<body>
43+
<div id="replace-foo">Text to be replaced.</div>
44+
<div id="replace-bar">Text to be replaced.</div>
45+
${includeScript('examples/script_isolation/bar')}
46+
</body>
47+
</html>
48+
`.trim());
49+
}

examples/script_isolation/test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { useDevserver } from '../../common/testing/devserver';
2+
import { useWebDriver, webDriverTestTimeout } from '../../common/testing/webdriver';
3+
4+
describe('Script Isolation', () => {
5+
const devserver = useDevserver('examples/script_isolation/devserver.sh');
6+
const wd = useWebDriver(devserver);
7+
8+
it('renders `/foo.html` page with only `foo.js`', async () => {
9+
const browser = wd.get();
10+
await browser.url('/foo.html');
11+
12+
expect(await browser.getTitle()).toBe('Script Isolation');
13+
expect(await browser.$('#replace-foo').getText())
14+
.toBe('This text rendered by page JavaScript!');
15+
16+
// Not replaced, because `bar.js` isn't included.
17+
expect(await browser.$('#replace-bar').getText())
18+
.toBe('Text to be replaced.');
19+
}, webDriverTestTimeout);
20+
21+
it('renders `/bar.html` page with only `bar.js`', async () => {
22+
const browser = wd.get();
23+
await browser.url('/bar.html');
24+
25+
expect(await browser.getTitle()).toBe('Script Isolation');
26+
27+
// Not replaced, because `bar.js` isn't included.
28+
expect(await browser.$('#replace-foo').getText())
29+
.toBe('Text to be replaced.');
30+
31+
expect(await browser.$('#replace-bar').getText())
32+
.toBe('This text rendered by page JavaScript!');
33+
}, webDriverTestTimeout);
34+
});

0 commit comments

Comments
 (0)