remix-run / remix

Build Better Websites. Create modern, resilient user experiences with web fundamentals.
https://remix.run
MIT License
29.74k stars 2.51k forks source link

<Scripts crossOrigin /> doesn't work for when hosting the app's JS assets on a different CDN server #3572

Closed ranjithkumar-n closed 1 year ago

ranjithkumar-n commented 2 years ago

What version of Remix are you using?

1.6.1

Steps to Reproduce

Try to host public/build assets in a CDN by passing the right CDN prefix to publicPath in your remix.config.js

Sample: remix.config.js

image

And now when the scripts are loaded via <Scripts crossOrigin/> in root.tsx file, the scripts fail to load with CORS Error

image image

As per the docs here https://remix.run/docs/en/v1/api/remix#meta-links-scripts, the above settings should work when scripts are hosted on another server than the app, screenshot of the docs below

image

Expected Behavior

<Scripts crossOrigin /> should work when assets are hosted in an external CDN server.

If possible add props to <Scripts /> component to add scripts as plain scrips instead of module

Actual Behavior

When using <Scripts crossOrigin /> to add CDN based JS files the JS files fail to load with CORS error

kennethvdberghe commented 2 years ago

Are you sure you have configured the CDN correctly to allow other origins to fetch these resources? Since the error is stating No 'Access-Control-Allow-Origin' header is present. I think this is the reason for the browser blocking you to fetch the resources from the CDN coming from qaa.priceline.com.

ranjithkumar-n commented 2 years ago

@kennethvdberghe yes, the scripts load perfectly fine when included directly, like eg. <script src="https://assets.pclncdn.com/web/partner-pages/ccffcd2c6e/bundle.c23ea32b87e6b15a417d.js"></script>, but fails only with an error when using <Scripts crossOrigin />

kennethvdberghe commented 2 years ago

And what is Scripts rendering in the html?

ranjithkumar-n commented 2 years ago

@kennethvdberghe sorry for the late response, so I inspected the HTML, the <Scripts /> component seems to render link tag with rel set to modulepreload

Like this below, <link rel="modulepreload" href="https://assets.pclncdn.com/web/partner-pages/ccffcd2c6e/bundle.c23ea32b87e6b15a417d.js"></link>

brophdawg11 commented 1 year ago

I'm going to close this out since I can't reproduce and it seems to be an error due to a mismatching CORS header on your asset server. If you can provide a minimal reproduction, please feel free to re-open!

To test, I created a new Remix express app (npx create-remix@latest) and set publicPath: "http://localhost:8888/assets".

Then I created an asset Express server to serve from the public/build/ directory on port 8888 at the path /assets:

import express from "express";

const app = express();
app.use(
  "/assets",
  express.static("public/build", { immutable: true, maxAge: "1y" })
);

app.listen(8888, async () => {
  console.log(`Asset server listening on port 8888`);
});

This produced your error above - both with and without crossOrigin="" on <Scripts />:

Access to script at 'http://localhost:8888/assets/entry.client-ZNK7YNKG.js' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

To remedy the error, I just added the indicated header to my asset server:

app.use(
  "/assets",
  (req, res, next) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    next();
  },
  express.static("public/build", { immutable: true, maxAge: "1y" })
);

Then the remix app works fine loading assets from my pseudo-CDN.