-
Notifications
You must be signed in to change notification settings - Fork 46
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
Support NextJS 13 font resolvers #2021
Comments
Thanks for reporting this @jordanarldt, I didn't even know NextJS fonts API was a thing. Will look into it. |
I believe it is a new thing since version 13 👍 still very cool though, and will be super useful in PreviewJS! |
So I found the logic that makes this work in Next.js: https://github.com/vercel/next.js/blob/c56f9f4ff906fb2ad4f1acb126071cb876d4363c/packages/next/src/build/webpack/loaders/next-font-loader/index.ts#L16 This is close to magic, and it has various weird edge cases. For example the following will fail: import * as googleFonts from "next/font/google";
const inter = googleFonts.Inter({ subsets: ["latin"] }); I agree that making this work would be convenient, but I'm not quite sure how to proceed yet. I don't really want to hack Next.js-specific code in Preview.js, as it adds a maintenance burden in the future (whenever this API changes in future versions of Next.js, Preview.js needs to be updated to support all current and future versions, just like React itself). In the meantime, here's a workaround:
const path = require("path");
module.exports = {
vite: {
resolve: {
alias: {
"next/font/google": path.resolve(__dirname, "./google-font-mock.js"),
},
},
},
};
export const Inter = () => ({}); This won't load the correct font, but at least it won't crash! |
@fwouts Awesome! Nice find, by the way! The way NextJS does it definitely seems like magic, and of course I wouldn't expect the PreviewJS implementation to be the same way they do it. I have a suggestion on an implementation that may help you. So typically in a NextJS project you'll have a main file to contain all the font imports (e.g. Here's an example:
And if i
So all we would really need PreviewJS to do is to be aware of the fonts we want to import, and then you could populate the Preview HTML with the necessary tags / class names. For example, here's the Google Font API URL for Plus Jakarta Sans: That will give you all of the font face information (replaced with the font family name from the font data above), and then you would just need to make the styles, for example: /* latin - Fetched from Google*/
@font-face {
font-family: '__Plus_Jakarta_Sans_d21556'; // use the family name from the font output above
font-style: normal;
font-weight: 400;
src: url(https://fonts.gstatic.com/s/plusjakartasans/v8/LDIbaomQNQcsA88c7O9yZ4KMCoOg4IA6-91aHEjcWuA_qU79TR_VMq2oRsWk.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
.__className_d21556 {
font-family: '__Plus_Jakarta_Sans_d21556';
} Theoretically, this would work, but maybe PreviewJS would be able to control what the returned classnames are? I might have to try this out in my wrapper file to see if it works. What do you think? |
@fwouts I actually made a working proof of concept, this may help you come up with a broader solution :-) I mock my // preview.config.js
module.exports = {
alias: {
"@/fonts": "__previewjs__/mocks/fonts.js",
},
}; Here is the mock file: // mock/fonts.js
export const jakartaSans = {
style: {
fontFamily: "'Plus Jakarta Sans'",
fontStyle: 'normal'
},
className: '__previewjs_jakarta_sans',
}; And here is my wrapper: // Wrapper.tsx
import { useEffect, useState } from "react";
import "@/app/globals.scss";
function useMockFonts() {
const [fontStyles, setFontStyles] = useState("");
useEffect(() => {
(async () => {
const styles = await fetch(
"https://fonts.googleapis.com/css?family=Plus%20Jakarta%20Sans",
).then(res => res.text());
setFontStyles(styles);
})();
});
return fontStyles;
}
export function Wrapper({ children }: React.PropsWithChildren): JSX.Element {
const style = useMockFonts();
const css = `
.__previewjs_jakarta_sans {
font-family: "Plus Jakarta Sans";
}`;
return (
<div>
<style>{style}</style>
<style>{css}</style>
{children}
</div>
);
} |
That's neat, thanks. For anyone reading this issue, @jordanarldt's solution is the recommended approach until we come to a more permanent solution ☝️ |
Is your feature request related to a problem? Please describe.
Hey again @fwouts :-) it's been a while.
I'm using PreviewJS with my NextJS app and I want my
__previewjs__/Wrapper.tsx
file to wrap components in the NextJSlayout
component, but it seems to be failing because I'm attempting to use a Google Font with the new NextJS fonts API.Here's my layout file:
and here's my
Wrapper.tsx
file:Describe the solution you'd like
It would be cool if the PreviewJS preview was able to automatically resolve these fonts so that they display correctly in the preview. Perhaps you could leverage the Google API and the name of the requested font from the NextJS import and use that to inject the font family tags into the preview body.
Describe alternatives you've considered
Manually setting the font in the wrapper file, but this won't be feasible as my project grows.
Additional context
Any more support for NextJS 13 will be awesome. Thanks again for the great work!
The text was updated successfully, but these errors were encountered: