-
Notifications
You must be signed in to change notification settings - Fork 72
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
Call GPP via code splitting #4447
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Passing run #5445 ↗︎
Details:
Review all test suite changes for PR #4447 ↗︎ |
|
||
export const setupExtensions = (options: FidesOptions) => { | ||
if (options.gppEnabled) { | ||
import(GPP_EXT_PATH).catch((e) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the dynamic importing step!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice. We'll need to test this on a real web server to see the gotchas though - I'd imagine a relative path like this might be stymied when the script tag is a third-party source?
For example, if we're on example.com
and we do this:
<script src="https://ethyca.com/path/to/fides.js" />
Does this know how to import from "https://ethyca.com/path/to/gpp-ext.js", or is it going to try to use "https://example.com/gpp-ext.js"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm yeah I think it'll try to use example.com/gpp-ext.js. how do we want to treat this? should we try to force it to look relative, or allow the whole path to be configurable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Realistically, we'll want to make it configurable, and then test out what works well in our staging/etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is super promising! I have some nitpicky comments about filenames (mostly!) but my main question is: will this work once it's deployed? 😄
|
||
export const setupExtensions = (options: FidesOptions) => { | ||
if (options.gppEnabled) { | ||
import(GPP_EXT_PATH).catch((e) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice. We'll need to test this on a real web server to see the gotchas though - I'd imagine a relative path like this might be stymied when the script tag is a third-party source?
For example, if we're on example.com
and we do this:
<script src="https://ethyca.com/path/to/fides.js" />
Does this know how to import from "https://ethyca.com/path/to/gpp-ext.js", or is it going to try to use "https://example.com/gpp-ext.js"?
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse | ||
) { | ||
const gppJsFile = "public/lib/gpp-ext.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW: I feel like this an API route here is more complicated than we'd want here, just because next.js will happily serve static files... but at the same time, it's fairly painful to force cache headers on them...
In other words, a potentially simpler way to solve this is:
- copy that fides-gpp-ext.js file into
public/
instead ofpublic/lib
- use the default hosting of static files from next
- add the required headers in the next.config.js or similar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh good point, that makes things a lot simpler!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm actually there seem to be some open issues about adding cache headers in the public folder: vercel/next.js#22319
will look into some of the workarounds on monday...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since I couldn't change the cache control header via the public/
folder, I kept this as an endpoint that just serves the file (+ a cache header). I did make the changes to the filenames so the rollup file is easier to follow now though. if you have ideas for how to make caching work on public/
then we can come back to this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, no problem!
I'm running into some issues merging main because of this bit that was just introduced in a separate PR: fides/clients/fides-js/src/lib/tcf/events.ts Lines 19 to 22 in 1c500ab
This PR also has GPP calling the same function, however I'm unclear about how to get the GPP extension file to also have access to fides/clients/fides-js/rollup.config.mjs Lines 105 to 113 in fae7acf
But I'm not sure the right way to tell the GPP extension to also use the same |
Figured it out! I just needed to make sure my GPP ext also had the same window declaration in order to access the |
// Call extensions | ||
// DEFER(PROD#1439): This is likely too late for the GPP stub. | ||
// We should move stub code out to the base package and call it right away instead. | ||
await setupExtensions(options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just changed this to await
because otherwise FidesInitialized
might be called before the extension is ready to listen for it. I'm not sure if this is okay though in terms of initialization times—the first FidesInitialized
from an existing cookie will already have fired, so this is counting on the second one to fire. It would happen after the UI initializes, which might be far enough away from initial load times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the stub initialization, it'd definitely be too late.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall: I'd say ship it! I think you should add a config option here though to experiment with the import path.
// Call extensions | ||
// DEFER(PROD#1439): This is likely too late for the GPP stub. | ||
// We should move stub code out to the base package and call it right away instead. | ||
await setupExtensions(options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the stub initialization, it'd definitely be too late.
|
||
export const setupExtensions = (options: FidesOptions) => { | ||
if (options.gppEnabled) { | ||
import(GPP_EXT_PATH).catch((e) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Realistically, we'll want to make it configurable, and then test out what works well in our staging/etc
export default async function handler( | ||
req: NextApiRequest, | ||
res: NextApiResponse | ||
) { | ||
const gppJsFile = "public/lib/gpp-ext.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, no problem!
* The path where the GPP extension bundle is located, | ||
* likely served by the privacy center | ||
*/ | ||
const GPP_EXT_PATH = "/fides-ext-gpp.js"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do this we should make this configurable, especially as a runtime override option. That'd give a lot of flexibility for testing this out in different environments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! 17b8fa1
Running FIDES_PRIVACY_CENTER__IS_GPP_ENABLED=true FIDES_PRIVACY_CENTER__GPP_EXTENSION_PATH="/test.js" turbo dev
will try to import the GPP path from /test.js
and you'll get an error in the console. Running without the env var will default to /fides-ext-gpp.js
and things should work!
Closes https://ethyca.atlassian.net/browse/PROD-1395
Description Of Changes
Integrates GPP as a dynamically imported JS package. This means it isn't called until it is needed so isn't included in the initial bundle size. This is also a good proof of concept for how we can implement code splitting in our bundle to split out our UI code from our core initialization code.
Caveats
This works pretty well, but there are some warnings in the Privacy Center logs which say
Critical dependency: the request of a dependency is an expression
. After some googling, this appears to be a warning that is okay to ignore: vercel/next.js#10633One way to remove the warning is to force the variable where we cast the GPP bundle parameter to a string but this actually causes the app not to compile. It tries to import typescript files which it can't read, and I haven't figured out why that might be. So I left the warning in, though I can't say I totally understand it.
Code Changes
/gpp-ext
/gpp-ext
FIDES_PRIVACY_CENTER__IS_GPP_ENABLED
to include the GPP bundle dynamically. In the future, this will be done through a config on the backend, but to get this going, I added the env var. We should remove it down the line, similar to what we did for TCF.Steps to Confirm
turbo dev
. This will build the newgpp-ext.js
output and you should see a block along the lines offides-tcf.js
bundle. It should be around40.45 KB
localhost:3000/fides-js-demo.html?geolocation=fr-id
to get the TCF overlay__gpp('ping', (data) => {console.log({data})})
. You should get an error that the function__gpp
is not defined. This is expected since the bundle wasn't included!FIDES_PRIVACY_CENTER__IS_GPP_ENABLED=true
fides-tcf.js
bundle. It should be the same as it was before (40.45 KB
).localhost:3000/fides-js-demo.html?geolocation=fr-id
to get the TCF overlay__gpp('ping', (data) => {console.log({data})})
. This time you should get adata
object back!gpp-ext.js
Tada, GPP without increasing the initial bundle size!
Pre-Merge Checklist
CHANGELOG.md