I’m wondering if anyone could help me. I have built a custom NextJS app on Heroku intended to be embedded on my Shopify storefront using Shopify’s app proxy. It’s mostly working, so it is showing my app when I go to the proxy url within my Shopify store however all of the CSS & JS filepaths have been changed to my Shopify URL rather than remaining as my Heroku app URL.
I have seen someone else have this exact same problem: https://community.shopify.com/c/Shopify-APIs-SDKs/App-Proxy-Sending-index-html-throws-404-on-the-JS-and-CSS-files/td-p/586595
However when I try to implement this solution it keeps breaking the app. I’m relatively new to Node.js/Next.js so while I’m still learning I largely depend on documentation to follow to set up or resolve this type of issue. However, I cannot find any tutorials or documentation specific to this issue.
Is anyone able to advise what I need to do within my server.js to make the ‘/_next/static/…’ files remain to be pulled from my Heroku app URL rather than the Shopify URL when being viewed from the proxy URL? I have included the contents of my server.js file below.
require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
const { verifyRequest } = require('@shopify/koa-shopify-auth');
const { default: Shopify, ApiVersion } = require('@shopify/shopify-api');
const Router = require('koa-router');
dotenv.config();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SHOPIFY_API_SCOPES.split(","),
HOST_NAME: process.env.SHOPIFY_APP_URL.replace(/https:///, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
const ACTIVE_SHOPIFY_SHOPS = {};
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
apiKey: process.env.SHOPIFY_API_KEY,
secret: process.env.SHOPIFY_API_SECRET,
scopes: ["read_products"],
afterAuth(ctx) {
const { shop, scope } = ctx.state.shopify;
ACTIVE_SHOPIFY_SHOPS[shop] = scope;
ctx.redirect(`/?shop=${shop}`);
},
}),
);
const handleRequest = async (ctx) => {
console.log('ctx.req.url', ctx.req.host);
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.get("/", async (ctx) => {
const shop = ctx.query.shop;
ACTIVE_SHOPIFY_SHOPS[shop] = ctx.query.shop;
if (ACTIVE_SHOPIFY_SHOPS[shop] === undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
});
router.get("/_next/*", handleRequest);
router.get("(.*)", verifyRequest(), handleRequest);
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
Many thanks
2
Answers
A Proxy is simply a callback to your App, where as a response you provide either Liquid, or JSON. If you are trying to return links to assets such as CSS or JS, links are just strings. So can just send them as JSON key:value pairs.
A simple workaround is to use
assetPrefix
on next.config.js.The
assetPrefix
will be prefixed for the /_next/ path automatically, so the assets are refered with absolute URL.https://nextjs.org/docs/api-reference/next.config.js/cdn-support-with-asset-prefix