Closed7
Next.js上でMSWを、useSWRでSuspenseを有効にしているページでも初期表示で動作させる
公式であるように
// windowがないときに server.listen()
} else {
const { worker } = require('./browser');
worker.start();
}
として
import 'mock.tsのパス'
としても、Suspenseを利用しているページにURLを直接アクセス叩いてアクセスすると
AxiosError: Request failed with status code 404
This error happened while generating the page. Any console logs will be displayed in the terminal window.
GET http://localhost:XXXX/foo
ステータス 500 Internal Server Error
のようにエラーを返される。
- URL直叩きでなく、何もAPIを叩いていないページから遷移してくると動作する
- suspenseを切ったときも動作する
- API単体で切り出してボタン経由で叩くと動作する
から、どうやらモックが準備できたタイミングより前に叩いているのが原因っぽい。
そのため以下のようにHOCとして書いたところ、それでも動作しなかった。
consoleでは mock enabled
のような表記のあとにAPI通信でエラーが発生していた。
export const MswWrapper: FC<Props> = ({ children }) => {
const [enabled, setEnabled] = useState(false);
useEffect(() => {
if (enabled) return;
if (process.env.NODE_ENV !== 'development') return setEnabled(true);
(async () => {
const { worker } = await import('./browser');
worker.start();
setEnabled(true);
})();
}, [enabled, setEnabled]);
if (process.env.NODE_ENV === 'production') return children;
return <>{enabled && children}</>;
};
そのためmockが有効になるタイミングとmockAPIが実際に叩けるタイミングにズレがあり、その僅かな差の間に通信が差し込まれてエラーになった、と仮定した。
よって若干待つ処理を入れたところ、動作した。
(async () => {
const { worker } = await import('./browser');
worker.start();
// モックが有効になるまで時間がかかるので少し待つ
await new Promise((_) => setTimeout(_, 1000));
setup();
})();
まったく綺麗ではないけれど開発環境でしか影響しないしいったんこれでいいや……という気持ち半分、それでも綺麗に書きたい気持ち半分。
どなたか正しく美しく動作するコードあれば教えてください…… :bow:
なんてことはなく、StartReturnType
が内部的にPromise型だったのを見落としていただけだった。
しょーーーーーもないエラーで詰まってたっぽいですかなしい
declare type StartReturnType = Promise<ServiceWorkerRegistration | undefined>;
interface SetupWorkerApi {
start: (options?: StartOptions) => StartReturnType;
(async () => {
const { worker } = await import('./browser');
await worker.start();
setup();
})();
return <>{enabled && children}</>;
これSEO死にます(useEffectの中でしかenabledはtrueにならないのでcrawlerが解釈できない。envを見てchildrenを即座に流せるようにしないといけない)
このスクラップは2022/11/08にクローズされました