Skip to content

Commit

Permalink
Merge pull request #23891 from nsheaps/make-font-failed-to-load-error…
Browse files Browse the repository at this point in the history
…-message-useful

Nextjs: Improve Google Fonts failure error messages and documentation
  • Loading branch information
yannbf authored Sep 18, 2023
2 parents 04ced71 + a941216 commit dd144a0
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 3 deletions.
46 changes: 46 additions & 0 deletions code/frameworks/nextjs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [next/font/google](#nextfontgoogle)
- [next/font/local](#nextfontlocal)
- [Not supported features of next/font](#not-supported-features-of-nextfont)
- [Mocking fonts during testing](#mocking-fonts-during-testing)
- [Next.js Routing](#nextjs-routing)
- [Overriding defaults](#overriding-defaults)
- [Global Defaults](#global-defaults)
Expand Down Expand Up @@ -271,6 +272,51 @@ The following features are not supported (yet). Support for these features might
- [preload](https://nextjs.org/docs/api-reference/next/font#preload) option gets ignored. Storybook handles Font loading its own way.
- [display](https://nextjs.org/docs/api-reference/next/font#display) option gets ignored. All fonts are loaded with display set to "block" to make Storybook load the font properly.

#### Mocking fonts during testing

Occasionally fetching fonts from Google may fail as part of your Storybook build step. It is highly recommended to mock these requests, as those failures can cause your pipeline to fail as well. Next.js [supports mocking fonts](https://github.com/vercel/next.js/blob/725ddc7371f80cca273779d37f961c3e20356f95/packages/font/src/google/fetch-css-from-google-fonts.ts#L36) via a JavaScript module located where the env var `NEXT_FONT_GOOGLE_MOCKED_RESPONSES` references.

For example, using [GitHub Actions](https://www.chromatic.com/docs/github-actions):

```shell
- uses: chromaui/action@v1
env:
#👇 the location of mocked fonts to use
NEXT_FONT_GOOGLE_MOCKED_RESPONSES: ${{ github.workspace }}/mocked-google-fonts.js
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
token: ${{ secrets.GITHUB_TOKEN }}
```

Your mocked fonts will look something like this:

```js
// mocked-google-fonts.js
//👇 Mocked responses of google fonts with the URL as the key
module.exports = {
'https://fonts.googleapis.com/css?family=Inter:wght@400;500;600;800&display=block': `
/* cyrillic-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZJhiJ-Ek-_EeAmM.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* more font declarations go here */
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: block;
src: url(https://fonts.gstatic.com/s/inter/v12/UcCO3FwrK3iLTeHuS_fvQtMwCp50KnMw2boKoduKmMEVuLyfAZ9hiJ-Ek-_EeA.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;
}`,
};
```

### Next.js Routing

[Next.js's router](https://nextjs.org/docs/routing/introduction) is automatically stubbed for you so that when the router is interacted with, all of its interactions are automatically logged to the Actions ctions panel if you have the [Storybook actions addon](https://storybook.js.org/docs/react/essentials/actions).
Expand Down
1 change: 1 addition & 0 deletions code/frameworks/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
"@storybook/addon-actions": "workspace:*",
"@storybook/builder-webpack5": "workspace:*",
"@storybook/core-common": "workspace:*",
"@storybook/core-events": "workspace:*",
"@storybook/node-logger": "workspace:*",
"@storybook/preset-react-webpack": "workspace:*",
"@storybook/preview-api": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import loaderUtils from 'next/dist/compiled/loader-utils3';
import {
GoogleFontsDownloadError,
GoogleFontsLoadingError,
} from '@storybook/core-events/server-errors';
import type { LoaderOptions } from '../types';

const cssCache = new Map<string, Promise<string>>();
Expand Down Expand Up @@ -33,7 +37,10 @@ export async function getFontFaceDeclarations(options: LoaderOptions) {
cssCache.delete(url);
}
if (fontFaceCSS === null) {
throw Error(`Failed to fetch \`${fontFamily}\` from Google Fonts.`);
throw new GoogleFontsDownloadError({
fontFamily,
url,
});
}

return {
Expand All @@ -45,6 +52,6 @@ export async function getFontFaceDeclarations(options: LoaderOptions) {
variable,
};
} catch (error) {
throw new Error("Google Fonts couldn't be loaded.");
throw new GoogleFontsLoadingError({ error, url });
}
}
40 changes: 40 additions & 0 deletions code/lib/core-events/src/errors/server-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,3 +328,43 @@ export class MissingBuilderError extends StorybookError {
`;
}
}

export class GoogleFontsDownloadError extends StorybookError {
readonly category = Category.FRAMEWORK_NEXTJS;

readonly code = 1;

public readonly documentation =
'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization';

constructor(public data: { fontFamily: string; url: string }) {
super();
}

template() {
return dedent`
Failed to fetch \`${this.data.fontFamily}\` from Google Fonts with URL: \`${this.data.url}\`
`;
}
}

export class GoogleFontsLoadingError extends StorybookError {
readonly category = Category.FRAMEWORK_NEXTJS;

readonly code = 2;

public readonly documentation =
'https://github.com/storybookjs/storybook/blob/next/code/frameworks/nextjs/README.md#nextjs-font-optimization';

constructor(public data: { error: unknown | Error; url: string }) {
super();
}

template() {
return dedent`
An error occurred when trying to load Google Fonts with URL \`${this.data.url}\`.
${this.data.error instanceof Error ? this.data.error.message : ''}
`;
}
}
1 change: 1 addition & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7347,6 +7347,7 @@ __metadata:
"@storybook/addon-actions": "workspace:*"
"@storybook/builder-webpack5": "workspace:*"
"@storybook/core-common": "workspace:*"
"@storybook/core-events": "workspace:*"
"@storybook/node-logger": "workspace:*"
"@storybook/preset-react-webpack": "workspace:*"
"@storybook/preview-api": "workspace:*"
Expand Down
2 changes: 1 addition & 1 deletion scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@
]
},
"resolutions": {
"@testing-library/jest-dom": "^5.11.9",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/experimental-utils": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"esbuild": "^0.18.0",
"eslint": "^8.28.0",
"serialize-javascript": "^3.1.0",
"@testing-library/jest-dom": "^5.11.9",
"type-fest": "~2.19"
},
"dependencies": {
Expand Down

0 comments on commit dd144a0

Please sign in to comment.