Skip to content

Commit

Permalink
Migrates //examples/external to use Preact.
Browse files Browse the repository at this point in the history
Refs #71.

The migration is relatively straightforward, with one major bug which needed to be addressed. The comment in `//:node_modules/@rules_prerender/preact` explains most of the context, but essentially we cannot allow `//packages/preact:pkg` to depend on `//:node_modules/rules_prerender` because this is an NPM peer dependency, not a normal dependency. External workspaces cannot `npm_link_package()` from `@rules_prerender//packages/preact:pkg` when there is a transitive dependency on `//:node_modules/rules_prerender` because it duplicates the `rules_prerender` package in addition to the `//:node_modules/rules_prerender` target in their own workspace. This introduces incompatibilities, since user code and `@rules_prerender/preact` would be importing different versions of the `rules_prerender` package.

Instead, we depend on `//:node_modules/rules_prerender_types` which drops the JS implementation from the output to avoid duplicating the `rules_prerender` NPM package. However this alone means there is no dependency whatsoever between `@rules_prerender/preact` and `rules_prerender` and users have to manually depend on both, even when they only import `@rules_prerender/preact`. To address this, we use `deps` in `link_npm_package()` to add the dependency _at link time_. Doing so allows the same package to be linked in multiple places with different implementations of `rules_prerender`. In the `@rules_prerender` workspace, we link it to `@rules_prerender//:node_modules/rules_prerender` as built from HEAD. In other workspaces (such as `examples/external/`), users should link to the `//:node_modules/rules_prerender` of that workspace. This keeps a single definition of `rules_prerender` and always places it in the right location.
  • Loading branch information
dgp1130 committed Mar 17, 2023
1 parent 63cb9a6 commit fa3c4f3
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 50 deletions.
18 changes: 18 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@ npm_link_package(
name = "node_modules/@rules_prerender/preact",
src = "//packages/preact:pkg",
visibility = ["//:__subpackages__"],

# `@rules_prerender/preact` has an NPM peer dep on `rules_prerender`. We
# need to supply this at link-time rather than when the `npm_package()` is
# built so different links can specify different `rules_prerender` packages.
#
# For example, `@rules_prerender//:node_modules/@rules_prerender/preact`
# needs a dependency on `@rules_prerender//:node_modules/rules_prerender`,
# but an external workspace linking the same `npm_package()` would need its
# `@external_wksp//:node_modules/@rules_prerender/preact` to depend on
# `@external_wksp//:node_modules/rules_prerender`.
#
# If we didn't do this and allowed `//packages/preact:pkg` to directly
# depend on `//:node_modules/rules_prerender`, it would duplicate the
# `rules_prerender` package at runtime.
# See: https://bazelbuild.slack.com/archives/CEZUUKQ6P/p1678741591216319
deps = {
"//:.aspect_rules_js/node_modules/rules_prerender": "rules_prerender",
},
)

bzl_library(
Expand Down
23 changes: 21 additions & 2 deletions examples/external/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@aspect_bazel_lib//lib:copy_to_bin.bzl", "copy_to_bin")
load("@aspect_rules_js//js:defs.bzl", "js_binary", "js_run_binary")
load("@aspect_rules_js//npm:defs.bzl", "npm_link_package")
load("@aspect_rules_ts//ts:defs.bzl", "ts_config", "ts_project")
Expand All @@ -10,6 +11,11 @@ load(
)
load("@rules_prerender_npm//:defs.bzl", "npm_link_all_packages")

copy_to_bin(
name = "package",
srcs = ["package.json"],
)

npm_link_all_packages(name = "node_modules")

npm_link_package(
Expand All @@ -27,6 +33,14 @@ link_prerender_component(
package = ":node_modules/@rules_prerender/declarative_shadow_dom",
visibility = ["//visibility:public"],
)
npm_link_package(
name = "node_modules/@rules_prerender/preact",
src = "@rules_prerender//packages/preact:pkg",
visibility = ["//visibility:public"],
deps = {
"//:.aspect_rules_js/node_modules/rules_prerender": "rules_prerender",
},
)

ts_config(
name = "tsconfig",
Expand All @@ -43,10 +57,15 @@ ts_config(

prerender_pages(
name = "site",
src = "site.mts",
src = "site.tsx",
source_map = True,
tsconfig = "//:tsconfig",
lib_deps = ["//:node_modules/rules_prerender"],
# Need `"type": "module"` to load `*.js` files output by `*.tsx` compilation.
data = [":package"],
lib_deps = [
"//:node_modules/@rules_prerender/preact",
"//:node_modules/preact",
],
deps = ["//component"],
)

Expand Down
7 changes: 5 additions & 2 deletions examples/external/component/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ load(

prerender_component(
name = "component",
srcs = ["component.mts"],
srcs = ["component.tsx"],
scripts = [":script"],
styles = [":style"],
resources = [":resources"],
source_map = True,
tsconfig = "//:tsconfig",
visibility = ["//:__subpackages__"],
lib_deps = ["//:node_modules/rules_prerender"],
lib_deps = [
"//:node_modules/@rules_prerender/preact",
"//:node_modules/preact",
],
deps = ["//:prerender_components/@rules_prerender/declarative_shadow_dom"],
)

Expand Down
18 changes: 0 additions & 18 deletions examples/external/component/component.mts

This file was deleted.

25 changes: 25 additions & 0 deletions examples/external/component/component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { VNode } from 'preact';
import { Template, includeScript, inlineStyle } from '@rules_prerender/preact';
import { polyfillDeclarativeShadowDom } from '@rules_prerender/declarative_shadow_dom/preact.mjs';

declare module 'preact' {
namespace JSX {
interface IntrinsicElements {
'my-component': JSX.HTMLAttributes<HTMLElement>;
}
}
}

export function Component(): VNode {
return <my-component>
<Template shadowroot="open">
<img src="/logo" />
<span>Component</span>
<div id="replace">This text to be replaced by JavaScript.</div>

{polyfillDeclarativeShadowDom()}
{includeScript('./script.mjs', import.meta)}
{inlineStyle('./style.css', import.meta)}
</Template>
</my-component>;
}
3 changes: 2 additions & 1 deletion examples/external/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "rules_prerender_external",
"version": "0.0.0",
"private": true
"private": true,
"type": "module"
}
25 changes: 0 additions & 25 deletions examples/external/site.mts

This file was deleted.

18 changes: 18 additions & 0 deletions examples/external/site.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { PrerenderResource, renderToHtml } from '@rules_prerender/preact';
import { Component } from './component/component.js';

export default function*(): Generator<PrerenderResource, void, void> {
yield PrerenderResource.fromHtml('/index.html', renderToHtml(
<html>
<head>
<title>Test</title>
<meta charSet="utf8" />
</head>
<body>
<h2>Hello, World!</h2>

<Component />
</body>
</html>
));
}
4 changes: 3 additions & 1 deletion examples/external/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
"moduleResolution": "node",
"declaration": true,
"sourceMap": true,
"jsx": "react-jsx",
"jsxImportSource": "preact",
"paths": {
"rules_prerender": ["../../packages/rules_prerender"],
"@rules_prerender/declarative_shadow_dom": ["../../packages/declarative_shadow_dom"],
"@rules_prerender/*": ["../../packages/*"],
},
}
}
5 changes: 4 additions & 1 deletion packages/preact/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ ts_project(
deps = [
":node_modules/preact-render-to-string",
"//:node_modules/preact",
"//:node_modules/rules_prerender",
# As a peer dep, we can't depend on the JS implementation of
# `rules_prerender` because it needs to be supplied at link time.
# See `//:node_modules/@rules_prerender/preact` deps.
"//:node_modules_types/rules_prerender",
],
)

Expand Down

0 comments on commit fa3c4f3

Please sign in to comment.