-
Notifications
You must be signed in to change notification settings - Fork 325
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
Script and useScript #2194
base: v1.x-2022-07
Are you sure you want to change the base?
Script and useScript #2194
Changes from 26 commits
8a7f93c
0ea6916
ece42cb
ba75029
ab5b61b
3654c6a
4c76136
6f0e64b
a385d99
fce62a4
645ba78
5f8258d
9528a01
8aed11d
d034a82
538ad4d
624cb4d
282b3f7
5feac32
f742bad
062b3b7
f05677f
0685b42
afe07f6
dc2ade1
1d02f69
56341a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,376 @@ | ||||||||
--- | ||||||||
gid: 5848138c-3dbb-11ed-b878-0242ac120002 | ||||||||
title: Script | ||||||||
description: The Script component renders a script tag | ||||||||
--- | ||||||||
|
||||||||
<aside class="note beta"> | ||||||||
<h4>Experimental feature</h4> | ||||||||
|
||||||||
<p>Hydrogen Script is an experimental feature. As a result, functionality is subject to change. You can provide feedback on this feature by <a href="https://github.com/Shopify/hydrogen/issues">submitting an issue in GitHub</a>.</p> | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
</aside> | ||||||||
|
||||||||
The `Script` component is an enhanced HTML [`<script>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) element. Script enables efficient loading third-party scripts by offering different loading strategies within the application lifecycle. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Maybe a use case here, like a |
||||||||
|
||||||||
## Example code | ||||||||
|
||||||||
Load google analytics only after react has finished hydrating on the client. "afterHydration" is the default loading strategy | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Throughout, review for correct capitalization on Google |
||||||||
|
||||||||
{% codeblock file, filename: 'App.server.jsx' %} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
hypo-nit. Just a linting thing on the |
||||||||
```tsx | ||||||||
import {Script} from '@shopify/hydrogen'; | ||||||||
|
||||||||
export default function App() { | ||||||||
return ( | ||||||||
<> | ||||||||
//... | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I don't think that you need to comment out code elisions but I could be wrong. |
||||||||
<Script src="https://www.google-analytics.com/analytics.js" /> | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
apply throughout to minimize linting complains in |
||||||||
|
||||||||
## Props | ||||||||
|
||||||||
You can customize the behavior of the component with the following props | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
| Name | Type | Description | | ||||||||
| -------------- | ------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||||||||
| `target` | <code>"head" \| "body" (default)</code> | The target DOM element where the script should be inserted. This feature is only available to non-inline loading strategies such as "afterHydration", "inWorker" and "onIdle" | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Apply links where required throughout, and apply code formatting over names where required, throughout. |
||||||||
| `id` | <code>string (required)</code> | A unique identifier for the script. The id will be used as the key of the script. | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Unless representing as a literal value, upcase on ID. |
||||||||
| `src` | <code>string</code> | A URL string. This string can be an absolute path or a relative path depending on the location of the third-party script. The `src` prop is required if `dangerouslySetInnerHTML` or `children` are not used | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Review the descriptions for period use |
||||||||
| `dangerouslySetInnerHTML` | <code>string</code> | Any valid javascript code | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
and below |
||||||||
| `children` | <code>string \| string[]</code> | Any valid javascript code | | ||||||||
| `load` | <code>"beforeHydration" \| "afterHydration" (default) \| "inWorker" \| "onIdle"</code>| The loading strategy. See Loading strategies for more info. | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
do you need the quotes if the phrase is in code? Revise references to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we might want to bikeshed these strategy names |
||||||||
| `reload` | <code>boolean (default false)</code> | Scripts rendered with this option will be reloaded after every page navigation (if available on the next route). This option is only available in "afterHydration" and "onIdle" loading strategies. | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not sure if I got this correctly. Just figured that we could resolve some ambiguity and tighten up the description a bit. |
||||||||
| `onLoad` | <code>(script) => void</code> | A callback that fires when a script is loaded. This callback is only available in "afterHydration" and "onIdle" loading strategies | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
| `onReady` | <code>(script) => void</code> | A callback that fires when a script is successfully loaded and run. This callback is only available in "afterHydration" and "onIdle" loading strategies | | ||||||||
| `onError` | <code>(script) => void</code> | A callback that fires when a script fail to load. This callback is only available in "afterHydration" and "onIdle" loading strategies | | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
|
||||||||
## Loading strategies | ||||||||
|
||||||||
### `beforeHydration` | ||||||||
|
||||||||
These scripts are inlined and hence considered render-blocking. This strategy is mainly recommended for scripts aiming to set global `window` properties, configurations or event listeners. These scripts can only be included in `App.server.tsx`. This ensures that they are run on any initial route. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #The To @cartogram's edit, would add an Oxford comma between Verify throughout that you're using the Oxford comma |
||||||||
|
||||||||
{% codeblock file, filename: 'App.server.jsx' %} | ||||||||
```jsx | ||||||||
/* App.server.tsx */ | ||||||||
import {Script} from '@shopify/hydrogen'; | ||||||||
|
||||||||
export default function App() { | ||||||||
return ( | ||||||||
<> | ||||||||
// via dangerouslySetInnerHTML | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
<Script | ||||||||
id="bh-dangerously" | ||||||||
load="beforeHydration" | ||||||||
dangerouslySetInnerHTML={{ | ||||||||
__html: ` | ||||||||
window.dataLayer = window.dataLayer || []; | ||||||||
`, | ||||||||
}} | ||||||||
/> | ||||||||
|
||||||||
// or via children prop | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
<Script id="bh-children" load="beforeHydration"> | ||||||||
{`window.dataLayer = window.dataLayer || [];`} | ||||||||
</Script> | ||||||||
|
||||||||
// or via src — not recommended as this would block the main thread. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
// use afterHydration or onIdle instead to improve performance | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
<Script | ||||||||
id="bh-src" | ||||||||
load="beforeHydration" | ||||||||
src="//example.com/script.js" | ||||||||
/> | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
### `afterHydration` | ||||||||
|
||||||||
These scripts are loaded, injected and run after react has finished hydrating on the client (via a useEffect). In addition, these scripts include additional props to further customize their behavior `target`, `reload`, `onLoad`, `onReady` and `onError` callbacks. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you link to the table(s) that discuss |
||||||||
|
||||||||
{% codeblock file, filename: 'Component.client.jsx' %} | ||||||||
```jsx | ||||||||
import {Script} from '@shopify/hydrogen'; | ||||||||
|
||||||||
function Component() { | ||||||||
return ( | ||||||||
<> | ||||||||
// with children | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Caps to start comments. So |
||||||||
<Script | ||||||||
id="oi-children-reload" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
load="afterHydration" | ||||||||
reload={true} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Make this change for all of these I think. |
||||||||
> | ||||||||
{`console.log('Loaded after hydration!. Will re-execute if navigating to another route that also renders <Component />.`} | ||||||||
</Script> | ||||||||
|
||||||||
// with a src | ||||||||
<Script | ||||||||
id="oi-src" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
load="afterHydration" | ||||||||
src="//example.com/script.js" | ||||||||
/> | ||||||||
|
||||||||
// with a src and with reload | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
<Script | ||||||||
id="oi-src-reload" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
src="//example.com/script.js" | ||||||||
load="afterHydration" | ||||||||
reload={true} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
/> | ||||||||
|
||||||||
// with callbacks | ||||||||
<Script | ||||||||
id="oi-src-cbs" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
src="//example.com/script.js" | ||||||||
load="afterHydration" | ||||||||
onLoad={() => { | ||||||||
console.log('🌕 onLoad event'); | ||||||||
}} | ||||||||
onReady={() => { | ||||||||
console.log('🟢 onReady event'); | ||||||||
}} | ||||||||
onError={(error) => { | ||||||||
console.error('🔴 onError event', error); | ||||||||
}} | ||||||||
/> | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
### `onIdle` | ||||||||
|
||||||||
These scripts are loaded, injected and run when the main thread is idle (via requestIdleCallback). In addition, these scripts include additional props to further customize their behavior `target`, `reload`, `onLoad`, `onReady` and `onError` callbacks. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you end up making the suggestions above, please apply them to this paragraph as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
{% codeblock file, filename: 'Component.client.jsx' %} | ||||||||
```jsx | ||||||||
import {Script} from '@shopify/hydrogen'; | ||||||||
|
||||||||
function Component() { | ||||||||
return ( | ||||||||
<> | ||||||||
// with children | ||||||||
<Script | ||||||||
id="oi-children-reload" | ||||||||
load="onIdle" | ||||||||
reload={true} | ||||||||
> | ||||||||
{`console.log('Loaded when on idle!. Will re-execute if navigating to another route that also renders <Component />.`} | ||||||||
</Script> | ||||||||
|
||||||||
// with a src | ||||||||
<Script | ||||||||
id="oi-src" | ||||||||
load="onIdle" | ||||||||
src="//example.com/script.js" | ||||||||
/> | ||||||||
|
||||||||
// with a src and with reload | ||||||||
<Script | ||||||||
id="oi-src-reload" | ||||||||
src="//example.com/script.js" | ||||||||
load="onIdle" | ||||||||
reload={true} | ||||||||
/> | ||||||||
|
||||||||
// with callbacks | ||||||||
<Script | ||||||||
id="oi-src-cbs" | ||||||||
src="//example.com/script.js" | ||||||||
load="onIdle" | ||||||||
onLoad={() => { | ||||||||
console.log('🌕 onLoad event'); | ||||||||
}} | ||||||||
onReady={() => { | ||||||||
console.log('🟢 onReady event'); | ||||||||
}} | ||||||||
onError={(error) => { | ||||||||
console.error('🔴 onError event', error); | ||||||||
}} | ||||||||
/> | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
### `inWorker` | ||||||||
|
||||||||
These scripts are run outside the main thread by leveraging a [Partytown](https://partytown.builder.io/) web worker. To enable support for this strategy follow these steps: | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Scripts using the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
##### 1. Install partytown | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Add the |
||||||||
|
||||||||
```terminal | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
yarn add @builder.io/partytown | ||||||||
``` | ||||||||
|
||||||||
##### 2. Add partytown copylib script | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
|
||||||||
{% codeblock file, filename: 'package.json' %} | ||||||||
``` | ||||||||
{ | ||||||||
... | ||||||||
"scripts": { | ||||||||
"dev": "npm run partytown && shopify hydrogen dev", | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does it matter that |
||||||||
"build": "npm run partytown && shopify hydrogen build", | ||||||||
"partytown": "partytown copylib public/~partytown", | ||||||||
... | ||||||||
} | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
##### 3. Import `Partytown` and enable atomic mode | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some differences in capitalization and code formatting around |
||||||||
|
||||||||
{% codeblock file, filename: 'App.server.tsx' %} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On line 59 you've got |
||||||||
```jsx | ||||||||
import {Script} from '@shopify/hydrogen'; | ||||||||
import {partytownSnippet} from '@builder.io/partytown/integration'; | ||||||||
|
||||||||
/* | ||||||||
Set the required response headers to enable partytown atomics | ||||||||
@see: https://partytown.builder.io/atomics | ||||||||
*/ | ||||||||
function enablePartytownAtomic(response) { | ||||||||
response.headers.set('Cross-Origin-Embedder-Policy', 'credentialless'); | ||||||||
response.headers.set('Cross-Origin-Opener-Policy', 'same-origin'); | ||||||||
} | ||||||||
|
||||||||
export default function App({request, response}) { | ||||||||
enablePartytownAtomic(response); | ||||||||
|
||||||||
return ( | ||||||||
<> | ||||||||
// Initialize and configure partytown | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just wondering why the mix of comment styles, e.g. |
||||||||
<Script id="partytown-snippet" load="onIdle"> | ||||||||
{partytownSnippet({ | ||||||||
forward: ['forwardedTestFn'], | ||||||||
resolveUrl(url, location, type) { | ||||||||
// Some 3rd party libs/resources like https://www.googletagmanager.com/gtm.js | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
// require a reverse proxy to handle CORS via when loaded via Web Worker | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is |
||||||||
const isScriptReq = type === 'script'; | ||||||||
const isProxyReq = url.href.includes('/reverse-proxy'); | ||||||||
const isCorsReq = | ||||||||
url.href.includes('cors=true') || url.href.includes('gtm.js'); | ||||||||
|
||||||||
if (isScriptReq && isCorsReq && !isProxyReq) { | ||||||||
const proxyUrl = new URL(location.origin + '/reverse-proxy'); | ||||||||
proxyUrl.searchParams.append('libUrl', url.href); | ||||||||
return proxyUrl; | ||||||||
} | ||||||||
return url; | ||||||||
}, | ||||||||
})} | ||||||||
</Script> | ||||||||
<ShopifyProvider countryCode={countryCode}> | ||||||||
.... | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
#### 4. Add a reverse proxy (optional) | ||||||||
|
||||||||
The following reverse proxy can be integrated to provide the correct CORS headers for libraries that require them when loaded within a web worker. For more information please check [proxying-requests](https://partytown.builder.io/proxying-requests) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
above you use |
||||||||
|
||||||||
{% codeblock file, filename: '/src/routes/reverse-proxy.server.js' %} | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just curious re. |
||||||||
```jsx | ||||||||
/* | ||||||||
Reverse proxies partytown libs that require CORS. Used by Partytown resolveUrl | ||||||||
@see: https://partytown.builder.io/proxying-requests | ||||||||
@see: https://developers.cloudflare.com/workers/examples/cors-header-proxy/ | ||||||||
*/ | ||||||||
|
||||||||
// The endpoint you want the CORS reverse proxy to be on | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Should be consistent with using periods at the end of full sentences and multi-sentence comments. |
||||||||
const PROXY_ENDPOINT = '/reverse-proxy'; | ||||||||
|
||||||||
export async function api(request) { | ||||||||
const url = new URL(request.url); | ||||||||
const isProxyReq = url.pathname.startsWith(PROXY_ENDPOINT); | ||||||||
const isGet = request.method === 'GET'; | ||||||||
|
||||||||
if (isProxyReq && isGet) { | ||||||||
// Handle requests to the API server | ||||||||
return handleRequest(request); | ||||||||
} else { | ||||||||
return new Response(null, { | ||||||||
status: 405, | ||||||||
statusText: 'Only proxy requests are allowed', | ||||||||
}); | ||||||||
} | ||||||||
} | ||||||||
|
||||||||
async function handleRequest(request) { | ||||||||
const url = new URL(request.url); | ||||||||
// The target lib url | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
let libUrl = url.searchParams.get('libUrl'); | ||||||||
|
||||||||
if (libUrl == null) { | ||||||||
libUrl = request.url.href; | ||||||||
} | ||||||||
|
||||||||
try { | ||||||||
let response = await fetch(libUrl); | ||||||||
const body = await response.arrayBuffer(); | ||||||||
const contentType = response.headers.get('content-type'); | ||||||||
const cacheControl = response.headers.get('cache-control'); | ||||||||
|
||||||||
// Recreate the response so you can modify the headers | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
response = new Response(body, { | ||||||||
headers: { | ||||||||
'content-type': contentType, | ||||||||
'Access-Control-Allow-Origin': url.origin, | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is an |
||||||||
'cache-control': `${cacheControl}`, | ||||||||
Vary: 'Origin', // Append to/Add Vary header so browser will cache response correctly | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
}, | ||||||||
status: 200, | ||||||||
}); | ||||||||
|
||||||||
return response; | ||||||||
} catch (error) { | ||||||||
return new Response(error, {status: 500}); | ||||||||
} | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
#### 5. Add inWorker scripts | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
etc. |
||||||||
{% codeblock file, filename: 'App.server.tsx' %} | ||||||||
```jsx | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Would review file format and syntax highlighting combos in case there are other inconsistencies |
||||||||
export default function App() { | ||||||||
return ( | ||||||||
<> | ||||||||
// Loading google analytics.js via a web worker | ||||||||
<Script | ||||||||
id="inWorker-analytics" | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I don't really care how these IDs are named as long as it is consistent. |
||||||||
load="inWorker" | ||||||||
src="https://www.google-analytics.com/analytics.js?cors=true" | ||||||||
/> | ||||||||
|
||||||||
// Loading google gtm.js via a web worker | ||||||||
<Script | ||||||||
id="inWorker-gtm" | ||||||||
load="inWorker" | ||||||||
src="https://www.googletagmanager.com/gtm.js?id=GTM-XYZ12345" | ||||||||
/> | ||||||||
</> | ||||||||
) | ||||||||
} | ||||||||
``` | ||||||||
{% endcodeblock %} | ||||||||
|
||||||||
## Related components | ||||||||
|
||||||||
- [`useScript`](https://shopify.dev/api/hydrogen/hooks/primitive/usescript) |
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.