-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
includeScript()
strict deps
#2
Comments
I took a quick look at this in the
We could do the same thing here, make our own I posted on the Bazel slack channel asking about this to see if I'm missing anything. I couldn't find any issues or references to custom plugins in the |
Had a brief discussion about this on Slack. Unfortunately there's no great answer here atm. TypeScript does not actually support compiler plugins, as I originally thought. First, we could fork I'm not sure how hard it is to fork The second option is to generate a stricter declare export function includeScript(script: 'rules_prerender/examples/strict_deps/foo.js' | 'rules_prerender/examples/strict_deps/bar.js'): string; This has the benefit of not requiring a custom compiler. However the generated type definitions can't know where a file is being included from, so we can't apply module resolution logic here, meaning relative paths are not possible. Comparing the two approaches:
Before making a decision here I want to resolve those two major unknowns for each. As of right now, I'm leaning a bit more the first option just because it feels a bit less hacky. With a little more information we can hopefully identify a path forward here. |
I did a quick prototype of option 2 to validate the approach. Apparently, we can get a list of direct source files in a dependent I attempted to generate a simple TypeScript source which re-exported I did try another strategy which leaves the declare module 'rules_prerender' {
export function includeScript(script: 'wksp/foo/bar/baz.js' | 'wksp/hello/world.js'): string;
} This actually works around the one definition issue because it does not create a new There are two major issues with this strategy however. First is that there is no way to re-export all the existing
I don't see a viable solution to the removed value reference. I think the core issue here is that modules are not really intended to be augmented in this fashion. Technically, TypeScript does not support declaration merging of modules, however you can use them to extend interface types. There might be some magic incantation of TypeScript syntax that gets something kind of what I want, but this is a pretty unique enough problem that I'm comfortable saying this just isn't supported by TypeScript. The takeaway from all this is that I don't think the second approach of using generated type definitions is viable. I don't see a way this could work with TypeScript in its current state. Prototype: c3bb765 That means that we either need to fork |
I took a pass at forking The first issue is loading other packages which use paths like After that, I get errors about a missing The next issue is that Finally, I was missing files from It's a bit awkward for a number of reasons and I would like to make this simpler in a few ways:
Ultimately the fork wasn't that difficult, just need to polish everything and see if we can avoid vendoring it. Currently working in the |
Tried doing the same thing but using I first used After accepting this, I found a
I suspect this is because I haven't run I think the core problem is that I'm building Fortunately, the dev experience with |
Noticed this in the Bazel Slack today: https://bazelbuild.github.io/rules_nodejs/changing-rules.html Might be worth exploring if we can patch |
I started looking into A couple interesting aspects: How should we publish this Alternatively, I'm thinking I could patch the user's
This requires one extra setup step from users (the const { PrerenderPlugin } = require('rules_prerender_tsc_plugin');
// ...
diagnosticPlugins.add(new PrerenderPlugin()); And anytime I also discovered that I needed I definitely think going with |
Snapshot of current progress: 27eb205. |
It's also worth considering how this patching strategy would work with Yarn PnP (or the NPM equivalent whose name I'm forgetting). Writing to As a similar strategy, I'm wonder if we could
|
This has been in the back of my mind for a while (honestly forgot I put this much effort into the investigation). Two ideas I want to write down quickly before I forget: First, we don't necessarily need a real compiler plugin. TypeScript does support plugins, but only for editor intellisense, not actual compilations. Similarly we can generate component-specific
The second approach is to use I'm not sure how well supported that is in NodeJS or if it requires ESM. This also pushes the problem to runtime and requires more tooling to generate a strict deps map (prerender file -> client script file) which gets validated at I've have to explore both of these options a little more to see what the best path forward is. |
Currently, the
includeScript()
function does not validate that the included file is present in thescripts
attribute of the associatedprerender_component()
rule. If you include a script which you don't depend on, it could throw a file not found error at the bundling step. Worse, if another component depends on that file, it could pass the build until that component changes in the future and removes the script. Simply put,prerender_component()
should verify that allincludeScript()
statements have files which are direct dependencies of thescripts
attribute.How to do this could be quite tricky. Since we need to throw an error in a
ts_library()
component, the only want to do that is to make this state a TypeScript compile error. I can think of two ways to do that:ts_library()
solves the problem today and we could do something similar. The downside here is that we need to somehow add this plugin. Users may have their own version ofts_library()
which applies some of their own plugins, and we need to be compatible with that. Considering that right now we don't allow customts_library()
implementations, this may not be too bad, but it is something we will have to deal with.includeScript()
implementation with a more specific type. Instead of depending on@npm//rules_prerender
to provide theincludeScript()
function, we could instead haveprerender_component()
read thescripts
attribute and generate ats_library()
which providesincludeScript()
. This generated version could then accept as input a union of all the valid strict deps, rather than a simple string. This dodges the plugin problem but adds a lot of its own complexity.We also have to consider what happens if a user calls
includeScript()
with a variable that can't be resolved to a specific string. There shouldn't be much use for that, but I'm sure users will try it. This should probably be an error in order to improve strictness, but we may need some means of ignoring such cases.The text was updated successfully, but these errors were encountered: