Closed xnslx closed 1 year ago
[site] bucket = "./public"
I think your bucket should point to dist/client
instead, since that's where the assets are built.
How are you adding your styling to your components? Plain css?
How are you deploying your styles to cloudflare workers?
If you go to https://hydrogen.shop you can inspect how styles are added a deploy:
They should be in the <head>
as a <link>
. For example:
<link rel="stylesheet" href="https://cdn.shopify.com/oxygen/55145660472/28966968/maqqspnc1/build/_assets/app-QL2UZK4U.css">
In the case of cloudflare, you'd need to check if the file is getting uploaded and if the file is in the
of your project.@lordofthecactus @frandiox I finally made it using this https://github.com/lordofthecactus/hydrogen-v2-cloudflare-edge as a reference. There is a little bit adjustment for remix.config.js
file,
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
devServerBroadcastDelay: 1000,
ignoredRouteFiles: ['**/.*'],
server: './server.js',
serverConditions: ['worker'],
serverDependenciesToBundle: 'all',
serverMainFields: ['browser', 'module', 'main'],
serverMinify: true,
serverModuleFormat: 'esm',
serverPlatform: 'neutral',
appDirectory: 'app',
assetsBuildDirectory: 'public/build',
serverBuildPath: 'build/index.js',
publicPath: '/build/',
future: {
unstable_postcss: true,
unstable_tailwind: true,
v2_meta: true,
v2_routeConvention: true,
v2_errorBoundary: true,
v2_normalizeFormMethod: true,
},
};
But I do have a question, for the server.ts
file, there is a typescirpt issue that I cannot resolve.
Great! Could you show the issue when you hover?
@lordofthecactus This is the issue
server.ts
import * as build from '@remix-run/dev/server-build';
import {createCookieSessionStorage, ServerBuild} from '@remix-run/cloudflare';
import type {GetLoadContextFunction} from '@remix-run/cloudflare-workers';
import {
createRequestHandler as createRemixRequestHandler,
Session,
SessionStorage,
} from '@remix-run/server-runtime';
import type {Options as KvAssetHandlerOptions} from '@cloudflare/kv-asset-handler';
import {
MethodNotAllowedError,
NotFoundError,
getAssetFromKV,
} from '@cloudflare/kv-asset-handler';
import {createStorefrontClient} from '@shopify/hydrogen';
import {getBuyerIp} from '@shopify/remix-oxygen';
import {HydrogenSession} from '~/lib/session.server';
import {getLocaleFromRequest} from '~/lib/utils';
type RequestHandler = (event: FetchEvent) => Promise<Response>;
addEventListener(
'fetch',
createEventHandler({build, mode: process.env.NODE_ENV}),
);
function createEventHandler({
build,
getLoadContext,
mode,
}: {
build: ServerBuild;
getLoadContext?: GetLoadContextFunction;
mode?: string;
}) {
const handleEvent = async (event: FetchEvent) => {
/**
* Open a cache instance in the worker and a custom session instance.
*/
if (!SESSION_SECRET) {
throw new Error('SESSION_SECRET environment variable is not set');
}
const waitUntil = (p: Promise<any>) => event.waitUntil(p);
const env = {
PUBLIC_STOREFRONT_API_TOKEN,
PRIVATE_STOREFRONT_API_TOKEN:
typeof PRIVATE_STOREFRONT_API_TOKEN !== 'undefined'
? PRIVATE_STOREFRONT_API_TOKEN
: undefined,
PUBLIC_STORE_DOMAIN,
PUBLIC_STOREFRONT_API_VERSION,
PUBLIC_STOREFRONT_ID:
typeof PUBLIC_STOREFRONT_ID !== 'undefined'
? PUBLIC_STOREFRONT_ID
: undefined,
SESSION_SECRET,
};
const [cache, session] = await Promise.all([
caches.open('hydrogen'),
HydrogenSession.init(event.request, [SESSION_SECRET]),
]);
/**
* Create Hydrogen's Storefront client.
*/
const {storefront} = createStorefrontClient({
// cache
waitUntil,
buyerIp: getBuyerIp(event.request),
i18n: getLocaleFromRequest(event.request),
publicStorefrontToken: env.PUBLIC_STOREFRONT_API_TOKEN,
privateStorefrontToken: env.PRIVATE_STOREFRONT_API_TOKEN,
storeDomain: `https://${env.PUBLIC_STORE_DOMAIN}`,
storefrontApiVersion: env.PUBLIC_STOREFRONT_API_VERSION || '2023-01',
storefrontId: env.PUBLIC_STOREFRONT_ID,
requestGroupId: event.request.headers.get('request-id'),
});
const handleRequest = createRequestHandler({
build,
getLoadContext: () => ({session, cache, storefront}),
mode,
});
let response = await handleAsset(event, build);
if (!response) {
response = await handleRequest(event);
}
return response;
};
return (event: FetchEvent) => {
try {
event.respondWith(handleEvent(event));
} catch (e: any) {
if (process.env.NODE_ENV === 'development') {
event.respondWith(
new Response(e.message || e.toString(), {
status: 500,
}),
);
return;
}
event.respondWith(new Response('Internal Error', {status: 500}));
}
};
}
function createRequestHandler({
build,
getLoadContext,
mode,
}: {
build: ServerBuild;
getLoadContext?: GetLoadContextFunction;
mode?: string;
}): RequestHandler {
const handleRequest = createRemixRequestHandler(build, mode);
return (event: FetchEvent) => {
const loadContext = getLoadContext?.(event);
return handleRequest(event.request, loadContext);
};
}
async function handleAsset(
event: FetchEvent,
build: ServerBuild,
options?: Partial<KvAssetHandlerOptions>,
) {
try {
if (process.env.NODE_ENV === 'development') {
return await getAssetFromKV(event, {
cacheControl: {
bypassCache: true,
},
...options,
});
}
let cacheControl = {};
const url = new URL(event.request.url);
const assetpath = build.assets.url.split('/').slice(0, -1).join('/');
const requestpath = url.pathname.split('/').slice(0, -1).join('/');
if (requestpath.startsWith(assetpath)) {
// Assets are hashed by Remix so are safe to cache in the browser
// And they're also hashed in KV storage, so are safe to cache on the edge
cacheControl = {
bypassCache: false,
edgeTTL: 31536000,
browserTTL: 31536000,
};
} else {
// Assets are not necessarily hashed in the request URL, so we cannot cache in the browser
// But they are hashed in KV storage, so we can cache on the edge
cacheControl = {
bypassCache: false,
edgeTTL: 31536000,
};
}
return await getAssetFromKV(event, {
cacheControl,
...options,
});
} catch (error: unknown) {
if (
error instanceof MethodNotAllowedError ||
error instanceof NotFoundError
) {
return null;
}
throw error;
}
}
@xnslx You can either pass the env
object to getLoadContext
(if you are going to use it in loaders) or remove its type declaration from the remix.env.d.ts
file:
// server.ts
- getLoadContext: () => ({session, cache, storefront}),
+ getLoadContext: () => ({session, cache, storefront, env}),
or
// remix.env.d.ts
declare module '@shopify/remix-oxygen' {
export interface AppLoadContext {
waitUntil: ExecutionContext['waitUntil'];
session: HydrogenSession;
storefront: Storefront;
- env: Env;
}
}
What is the location of your example repository?
No response
Which package or tool is having this issue?
Hydrogen
What version of that package or tool are you using?
"@shopify/hydrogen": "^2023.1.6"
What version of Remix are you using?
No response
Steps to Reproduce
I managed to deploy shopify hydrogen V2 to Cloudflare workers and I lose all the CSS styling. There is no way to resolve the issue.
package.json
wrangler.toml
server.ts
remix.config.js
app.server.tsx
Expected Behavior
Hope to deploy a fully working website to cloudflare workers.
Actual Behavior
The current live website losing all the CSS styling.