Skip to content
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

wrong baseURL in inline CSS #242

Closed
JohnCampionJr opened this issue Sep 4, 2024 · 14 comments
Closed

wrong baseURL in inline CSS #242

JohnCampionJr opened this issue Sep 4, 2024 · 14 comments
Labels
bug Something isn't working

Comments

@JohnCampionJr
Copy link

JohnCampionJr commented Sep 4, 2024

Related to #96; this still is broken.

If I set baseUrl to /subapp then Nuxt Fonts uses a link like:

http://localhost:5001/subapp/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff

However this results in a 404, but this link works (note no base url)
http://localhost:5001/_fonts/rP2rp2ywxg089UriCZaSExd86J3t9jz86Mvy4qCRAL19DksVat9XCm3w-ByvzuLy2fa.woff

Copy link

dosubot bot commented Sep 4, 2024

Hey @JohnCampionJr! I'm here to help you with your issue. I'm a bot that can assist you with bug fixes, answer questions, and guide you on becoming a contributor.

I found a similar closed issue: Nuxt baseURL ignored when resolving cached font path. This issue was referenced by other discussions and commits, such as nuxt/fonts does not honour the nuxt baseUrl setting and Using BaseUrl breaks fonts [1].

To fix the issue where setting baseUrl to /subapp in Nuxt results in 404 errors for font links, you need to ensure that the assetsBaseURL is correctly prefixed with the baseUrl. Here's the relevant part of the code that handles the URL adjustment:

source.url = nuxt.options.dev
  ? joinRelativeURL(nuxt.options.app.baseURL, assetsBaseURL, file)
  : joinURL(assetsBaseURL, file)

To ensure that the font URLs are correctly prefixed with /subapp in both development and production, you should modify the assetsBaseURL to include the baseUrl:

const assetsBaseURL = joinURL(nuxt.options.app.baseURL, options.prefix || '/_fonts');

This change ensures that assetsBaseURL always includes the baseUrl, whether in development or production.

Here is the updated code snippet:

export function setupPublicAssetStrategy(options: ModuleOptions['assets'] = {}) {
  const nuxt = useNuxt();
  const assetsBaseURL = joinURL(nuxt.options.app.baseURL, options.prefix || '/_fonts');
  const renderedFontURLs = new Map<string, string>();

  function normalizeFontData(faces: FontFaceData | FontFaceData[]): NormalizedFontFaceData[] {
    const data: NormalizedFontFaceData[] = [];
    for (const face of Array.isArray(faces) ? faces : [faces]) {
      data.push({
        ...face,
        unicodeRange: face.unicodeRange === undefined || Array.isArray(face.unicodeRange) ? face.unicodeRange : [face.unicodeRange],
        src: (Array.isArray(face.src) ? face.src : [face.src]).map((src) => {
          const source = typeof src === 'string' ? parseFont(src) : src;
          if ('url' in source && hasProtocol(source.url, { acceptRelative: true })) {
            source.url = source.url.replace(/^\/\//, 'https://');
            const file = [
              filename(source.url.replace(/\?.*/, '')).replace(/^-+/, ''),
              hash(source) + (extname(source.url) || formatToExtension(source.format) || ''),
            ].filter(Boolean).join('-');
            renderedFontURLs.set(file, source.url);
            source.originalURL = source.url;
            source.url = joinURL(assetsBaseURL, file);
          }
          return source;
        }),
      });
    }
    return data;
  }

  // Register font proxy URL for development
  addDevServerHandler({
    route: assetsBaseURL,
    handler: lazyEventHandler(async () => {
      return eventHandler(async (event) => {
        const filename = event.path.slice(1);
        const url = renderedFontURLs.get(event.path.slice(1));
        if (!url) {
          throw createError({ statusCode: 404 });
        }
        const key = 'data:fonts:' + filename;
        // Use storage to cache the font data between requests
        let res = await storage.getItemRaw(key);
        if (!res) {
          res = await fetch(url).then(r => r.arrayBuffer()).then(r => Buffer.from(r));
          await storage.setItemRaw(key, res);
        }
        return res;
      });
    }),
  });

  if (nuxt.options.dev) {
    nuxt.options.routeRules ||= {};
    nuxt.options.routeRules[joinURL(assetsBaseURL, '**')] = {
      cache: {
        maxAge: ONE_YEAR_IN_SECONDS,
      },
    };
  }

  nuxt.options.nitro.publicAssets ||= [];
  const cacheDir = join(nuxt.options.buildDir, 'cache', 'fonts');

  nuxt.options.nitro = defu(nuxt.options.nitro, {
    publicAssets: [{
      dir: cacheDir,
      maxAge: ONE_YEAR_IN_SECONDS,
      baseURL: assetsBaseURL,
    }],
    ignore: [`!${join(cacheDir, '**/*')}`],
    prerender: {
      ignore: [assetsBaseURL],
    },
  } satisfies NitroConfig);

  // TODO: refactor to use nitro storage when it can be cached between builds
  nuxt.hook('nitro:init', async (nitro) => {
    if (nuxt.options.dev) {
      return;
    }
    nitro.hooks.hook('rollup:before', async () => {
      await fsp.rm(cacheDir, { recursive: true, force: true });
      await fsp.mkdir(cacheDir, { recursive: true });
      let banner = false;
      for (const [filename, url] of renderedFontURLs) {
        const key = 'data:fonts:' + filename;
        // Use storage to cache the font data between builds
        let res = await storage.getItemRaw(key);
        if (!res) {
          if (!banner) {
            banner = true;
            logger.info('Downloading fonts...');
          }
          logger.log(chalk.gray('  ├─ ' + url));
          res = await fetch(url).then(r => r.arrayBuffer()).then(r => Buffer.from(r));
          await storage.setItemRaw(key, res);
        }
        await fsp.writeFile(join(cacheDir, filename), res);
      }
      if (banner) {
        logger.success('Fonts downloaded and cached.');
      }
    });
  });

  return { normalizeFontData };
}

const ONE_YEAR_IN_SECONDS = 60 * 60 * 24 * 365;

This should resolve the 404 errors for font links when baseUrl is set to /subapp [2][3][4].

To continue talking to Dosu, mention @dosu.

@danielroe
Copy link
Member

Resolved in v0.8.0.

@danielroe danielroe closed this as not planned Won't fix, can't repro, duplicate, stale Sep 12, 2024
@JohnCampionJr
Copy link
Author

I'm not seeing a change in 0.8.0. Same symptoms. It's not the link to the font, it has the baseUrl. It is the actual location of the font file from the server

@danielroe
Copy link
Member

@JohnCampionJr Would you be able to provide a reproduction? 🙏

@JohnCampionJr
Copy link
Author

JohnCampionJr commented Sep 20, 2024

@danielroe

Reproduction

Running it gets this console error
image

Fonts are here though (and should not be) - note the missing baseurl
http://localhost:3000/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2

@danielroe danielroe reopened this Sep 20, 2024
@danielroe
Copy link
Member

@JohnCampionJr I believe this is an issue with prerendered pages only - can you confirm?

@danielroe danielroe changed the title Using BaseUrl breaks fonts wrong baseURL in prerendered pages Sep 22, 2024
@JohnCampionJr
Copy link
Author

@danielroe I'm not using prerendering in my main app that experiences this bug.

Disabled this, no effect:

 routeRules: {
     // Temporary workaround for prerender regression. see https://github.com/nuxt/nuxt/issues/27490
     '/': { prerender: false }
   },

tried ssr:false, no effect

@danielroe danielroe added the bug Something isn't working label Sep 23, 2024
@danielroe danielroe changed the title wrong baseURL in prerendered pages wrong baseURL in inline CSS Sep 23, 2024
@JohnCampionJr
Copy link
Author

JohnCampionJr commented Sep 24, 2024

@danielroe I'm sorry to report this, but the bug persists in v0.9.0.

image

Fonts continue to be served without the baseUrl:
http://localhost:3000/_fonts/rP2Yp2ywxg089UriI5-g4vlH9VoD8Cmcqbu0-K6z9mXg-VNw7NHvqnp.woff2

Loads the font just fine.

@danielroe
Copy link
Member

@JohnCampionJr I think I totally misunderstood your issue. So the baseURL is being correctly rendered but the fonts aren’t served there?

how are you running/deploying your built site? (Not with nuxi preview I trust?)

@danielroe danielroe reopened this Sep 24, 2024
@JohnCampionJr
Copy link
Author

JohnCampionJr commented Sep 24, 2024

@danielroe That is correct. I'm just using nuxt last dev server. It's pretty easy to see the bug with the reproduction. Just run it and look at the console.

@danielroe
Copy link
Member

sorry for the back and forth on this one - I thought you were talking about production CSS.

hopefully should be resolved in v0.9.1 🙏

@JohnCampionJr
Copy link
Author

@danielroe confirming it is fixed - thank you so much!!!

@danielroe
Copy link
Member

at last!! 🎉

@Jan-Heussner

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants