Skip to content

Commit

Permalink
fix(nextjs): Use dynamic imports in ClerkProvider (#2292)
Browse files Browse the repository at this point in the history
* fix(nextjs): Use dynamic imports for ClerkProvider

* chore(repo): Add changeset

* fix(nextjs): Try another dynamic import

* fix(nextjs): Typo

* fix(nextjs): Try reverting a change
  • Loading branch information
LekoArts committed Dec 12, 2023
1 parent 7657cd3 commit ada4bd0
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
36 changes: 36 additions & 0 deletions .changeset/selfish-books-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
'@clerk/nextjs': patch
---

Use dynamic imports in `<ClerkProvider />` which you import from `@clerk/nextjs`.

Users on Next.js 12 and older can run into errors like these:

```shell
error - ./node_modules/@clerk/nextjs/dist/esm/app-router/client/ClerkProvider.js:10:22
Module not found: Can't resolve 'next/navigation'
```
The aforementioned `<ClerkProvider />` component contains code for both Next.js 12 (+ older) and Next.js 13 (+ newer). On older versions it can't find the imports only available in newer versions.

If you're seeing these errors, you have to do two things:
1. Update `@clerk/nextjs` to this version
1. Update your `next.config.js` to ignore these imports:
```js
const webpack = require('webpack');
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack(config) {
config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /^next\/(navigation|headers|compat\/router)$/ }))
return config;
}
}
module.exports = nextConfig
```
It is safe to ignore these modules as your Next.js 12 app won't hit these code paths.
21 changes: 16 additions & 5 deletions packages/nextjs/src/client-boundary/ClerkProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
'use client';

import { useRouter } from 'next/compat/router';
import React from 'react';

import { ClientClerkProvider } from '../app-router/client/ClerkProvider';
import { ClerkProvider as PageClerkProvider } from '../pages/ClerkProvider';
import { type NextClerkProviderProps } from '../types';

/**
* This is a compatibility layer to support a single ClerkProvider component in both the app and pages routers.
* It also needs to support both Next.js before and after v13, hence the dynamic imports for certain modules.
*/
export function ClerkProvider(props: NextClerkProviderProps) {
const router = useRouter();
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { useRouter } = require('next/compat/router');
const router = useRouter();

const Provider = router ? PageClerkProvider : ClientClerkProvider;
return router ? <PageClerkProvider {...props} /> : <AppClerkProvider {...props} />;
} catch (error) {
// Silently ignore the error
return <PageClerkProvider {...props} />;
}
}

function AppClerkProvider(props: NextClerkProviderProps) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { ClientClerkProvider } = require('../app-router/client/ClerkProvider');

return <Provider {...props} />;
return <ClientClerkProvider {...props} />;
}

0 comments on commit ada4bd0

Please sign in to comment.