-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Performs a no-op bundle if no client-side JavaScript is provided.
Previously the build would fail if `includeScript` was never called and `bundle_js = True`. This is because Rollup _requires_ at least one input to bundle or it will fail. In this case, we don't actually care and doing nothing is the correct solution which will inject no scripts into the page. There's a bit of wasted build-time effort, but it's not that big a deal. Unfortunately there's no way to check if any files are in a `TreeArtifact` at analysis-time and no way to configure Rollup to allow the "no inputs" case. Instead we wrap the Rollup binary with another tool, called `js_bundle`. This is simply a pass through to Rollup, however it adds one `if` statement to check for the "no inputs" case. If so, then it exits successfully as a no-op. Bazel creates the output directory automatically, so there's nothing we need to do. It bugs me a little to have to introduce another Node process for this one `if` statement. I did try to see if I could run Rollup in-process, however this seemed to require manually parsing the command line arguments and passing them through to Rollup in a structured manner, which I'd rather not deal with. If we find the extra process overhead is significant, we can maybe revisit that optimization.
- Loading branch information
Showing
9 changed files
with
165 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
load("//:index.bzl", "prerender_pages", "web_resources_devserver") | ||
load("//tools/jasmine:defs.bzl", "jasmine_web_test_suite") | ||
load("//tools/typescript:defs.bzl", "ts_project") | ||
|
||
prerender_pages( | ||
name = "site", | ||
entry_point = "./site.js", | ||
prerender = ":prerender", | ||
) | ||
|
||
ts_project( | ||
name = "prerender", | ||
srcs = ["site.tsx"], | ||
deps = [ | ||
"//:node_modules/@rules_prerender/preact", | ||
"//:node_modules/preact", | ||
], | ||
) | ||
|
||
web_resources_devserver( | ||
name = "devserver", | ||
resources = ":site", | ||
) | ||
|
||
ts_project( | ||
name = "test_lib", | ||
srcs = ["test.mts"], | ||
testonly = True, | ||
deps = [ | ||
"//common/testing:devserver", | ||
"//common/testing:webdriver", | ||
"//:node_modules/@types/jasmine", | ||
], | ||
) | ||
|
||
jasmine_web_test_suite( | ||
name = "test", | ||
browsers = ["//tools/browsers:chromium-local"], | ||
data = [":devserver"], | ||
deps = [":test_lib"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# No scripts | ||
|
||
Test case which does _not_ include any client-side JavaScript. This should not | ||
emit any errors or warnings during the build process. It also should _not_ | ||
inject any `<script>` tag into the page, as this would be wasted bytes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { PrerenderResource, renderToHtml } from '@rules_prerender/preact'; | ||
|
||
export default function*(): Generator<PrerenderResource, void, void> { | ||
yield PrerenderResource.fromHtml('/index.html', renderToHtml( | ||
<html> | ||
<head> | ||
<meta charSet="utf8" /> | ||
<title>No scripts</title> | ||
</head> | ||
<body> | ||
<h2>No scripts</h2> | ||
</body> | ||
</html> | ||
)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { useDevserver } from '../../common/testing/devserver.mjs'; | ||
import { useWebDriver } from '../../common/testing/webdriver.mjs'; | ||
|
||
describe('no_scripts', () => { | ||
const devserver = useDevserver('examples/no_scripts/devserver.sh'); | ||
const wd = useWebDriver(devserver); | ||
|
||
describe('index page', () => { | ||
it('renders without a script', async () => { | ||
const browser = wd.get(); | ||
await browser.url('/'); | ||
|
||
expect(await browser.$('h2').getText()).toBe('No scripts'); | ||
|
||
// Expect only the live reload script. | ||
const scripts = await browser.$$('script'); | ||
expect(scripts.length).toBe(1); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
load("@aspect_rules_js//js:defs.bzl", "js_binary") | ||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library") | ||
load("//tools/typescript:defs.bzl", "ts_project") | ||
|
||
bzl_library( | ||
name = "js_bundle", | ||
srcs = ["js_bundle.bzl"], | ||
visibility = ["//packages/rules_prerender:__pkg__"], | ||
) | ||
|
||
js_binary( | ||
name = "js_bundler", | ||
entry_point = "js_bundler.mjs", | ||
data = ["js_bundler_lib"], | ||
visibility = ["//visibility:public"], | ||
) | ||
|
||
ts_project( | ||
name = "js_bundler_lib", | ||
srcs = ["js_bundler.mts"], | ||
data = ["//packages/rules_prerender:rollup"], | ||
deps = ["//common:binary"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/** | ||
* @fileoverview Bundles the given JavaScript entry points into a directory of | ||
* bundled output files. | ||
* | ||
* The command line arguments for this binary are passed through to Rollup | ||
* without modification and use the contract. The only difference that in Rollup | ||
* passing no input files is an error, but in `js_bundler` it is a no-op | ||
* success. | ||
*/ | ||
|
||
import { execFile as execFileCb } from 'child_process'; | ||
import { promisify } from 'util'; | ||
import { main } from '../../../common/binary.mjs'; | ||
|
||
const execFile = promisify(execFileCb); | ||
|
||
const rollup = | ||
`${process.env['RUNFILES']}/rules_prerender/packages/rules_prerender/rollup.sh`; | ||
|
||
main(async () => { | ||
// No files to bundle. This would be an error in Rollup, but we don't care | ||
// and just skip running Rollup altogether. Bazel creates the output | ||
// directory automatically, so we don't need to do anything, just exit | ||
// successfully. | ||
if (!process.argv.includes('-i')) return 0; | ||
|
||
// Drop Node parts of the argument string. | ||
const rollupArgs = process.argv.slice(2); | ||
|
||
// Execute Rollup as a subprocess. | ||
const proc = execFile(rollup, rollupArgs, {}); | ||
|
||
// Pipe subprocess stdout/stderr to this process' stdout/stderr. | ||
proc.child.stdout?.on('data', (chunk) => { | ||
process.stdout.write(chunk); | ||
}); | ||
proc.child.stderr?.on('data', (chunk) => { | ||
process.stderr.write(chunk); | ||
}); | ||
|
||
// Wait for Rollup to complete. | ||
try { | ||
await proc; | ||
} catch { | ||
// No need to propagate error message, stderr is already piped to the | ||
// process output. | ||
return 1; | ||
} | ||
|
||
return 0; | ||
}); |