next.js: [NEXT-1255] transpilePackages does not support hooks in pnpm linked modules

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System:
      Platform: darwin
      Arch: x64
      Version: Darwin Kernel Version 22.4.0: Mon Mar  6 21:00:17 PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64
    Binaries:
      Node: 20.2.0
      npm: 9.6.6
      Yarn: N/A
      pnpm: 8.4.0
    Relevant packages:
      next: 13.4.4
      eslint-config-next: 13.4.4
      react: 18.2.0
      react-dom: 18.2.0
      typescript: 5.0.4

Which area(s) of Next.js are affected? (leave empty if unsure)

App directory (appDir: true)

Link to the code that reproduces this issue or a replay of the bug

N/A

To Reproduce

  1. Create a simple Next.js starter app
  2. Use pnpm link --global inside of a third party module
  3. Publish that module and install it to your app
  4. Install it and use pnpm link module_name to link it to your project
  5. Add it to transpilePackages inside of your next.config.js
  6. Create a simple route inside of your pages directory that imports a provider from the external module
  7. Inside that provider, use a hook like a useState or useEffect
  8. The error will throw up: TypeError: Cannot read properties of null (reading 'useState')

This entire process works in appDir OR with @martpie 's deprecated package.

Describe the Bug

This issue only affects the pages directory, not the app directory.

Ever since @martpie 's next transpile modules package was deprecated, we moved to the new built-in solution. The main project is pnpm link-ed to a bunch of external ESM modules that we use to share packages between projects.

When linked, the transpiler does not process hooks correctly.

TypeError: Cannot read properties of null (reading 'useState') - this error throws up regardless of the hook being used (useState, useRef, useEffect, etc.)

However, if you do NOT pnpm link the modules, it works. Previously we used the { resolveSymlinks: false } option in @martpie 's package, but this doesn’t seem to be available or relevant to the built-in solution.

Therefore, the only way we can use the transpilePackages feature is with appDir. But since we do have some routes that need to stay in pages dir, we’re a bit stuck.

Expected Behavior

It should allow hooks to fire as usual.

Which browser are you using? (if relevant)

Any

How are you deploying your application? (if relevant)

Localhost

NEXT-1255

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 14
  • Comments: 19 (4 by maintainers)

Most upvoted comments

Hi @altechzilla I’ve added this to the maintainer’s tracker so this can get prioritized, but it’s still in queue and we don’t have an ETA yet.

This issue happened to us after we migrated our monorepo to use pnpm as the package manager.

  • pnpm: 8.6.8
  • node: v20.5.0
  • next: 13.5.4
  • react AND react-dom: 18.2.0

I tried using npm and yarn and it worked fine. I added this line to next.config.js as @zecka suggested and the issue was resolved with pnpm:

  webpack: (config, _context) => {
  
  config.resolve.alias["react"] = path.resolve(
      __dirname,
      "../../node_modules/react"
    );
    return config;
},

This issue happens when linked library use react hooks.

This error appear to me after next 13.3.1

So this error appear because

  • I use yarn link to consume my library local instead of npm registry
  • I use transpilePackages ( transpilePackages: [‘@mycompany/my-lib’], )
  • I use page router on nextjs 13.5.5

Finally i found a solution by forcing alias of react to node_module/react inside my nextjs project. Inside webpack() config config.resolve.alias['react'] = path.resolve(__dirname, 'node_modules/react')

I added following nextjs config:

//next.config.js
// @ts-check
/**
 * @typedef {import('next').NextConfig} NextConfig
 * @typedef {import('webpack').Configuration} WebpackConfig
 * @typedef {import('next/dist/server/config-shared').WebpackConfigContext} WebpackConfigContext
 * @typedef {(config: WebpackConfig, context: WebpackConfigContext) => any} NextWebpackConfig
 */
const nextConfig = async () => {
 /**
     *
     * @param {import('webpack').Configuration} config
     * @param {import('next/dist/server/config-shared').WebpackConfigContext} _context
     * @returns {import('webpack').Configuration}
     */
    webpack: (config, _context) => {
      config.resolve.alias['react'] = path.resolve(__dirname, 'node_modules/react')
      return config;
    },
}
module.exports = nextConfig;

This issue is maybe related to https://github.com/facebook/react/issues/13991

We have been seeing the same thing, with a bare-bones NextJS repo (pages only, no app dir) and Yarn with linked packages. 13.3.1 seems fine, going to 13.3.2 then breaks.

We’re seeing a similar issue with our internal component library, although we don’t use pnpm. When we actually publish the component library everything works fine.

I created a repro with a similar setup over here: https://github.com/Benimation/link-problem

To reproduce the issue, execute these commands:

cd component-library
npm i
npm link

cd ../reproduction-app
npm link component-library
npm run dev

Remember to re-link when switching between Next versions, I use this: npm i next@13.3.1 && npm link component-library

I added both a “pages” page (the homepage) and an “app” page (“about”).

We’ve been seeing this issue since version 13.3.2, and it’s still there in the latest canary

Hey @altechzilla, we haven’t been able to prioritize fixing this over other bugs that many more people are running into (i.e. more 👍, more comments, etc.). It will be worked on eventually as it’s in our issue tracker but I can’t give an estimate right now as we’re focusing on solve the largest issues people have.

To clarify, we’re also seeing this when not using the app directory at all. I just added it in the repro as an example.

We also just completely switched to the App Router, so we’re not seeing this issue anymore either 😃

Any update…? @ali4heydari Thanks I finally found solution to transpilePackages…🥲

const path = require('path');

/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@tanstack/react-query', '@tanstack/query-core'],
  webpack(webpackConfig) {
    webpackConfig.resolve.alias["@tanstack/react-query"] = path.resolve(
      __dirname,
      "./node_modules/@tanstack/react-query"
    );
    webpackConfig.resolve.alias["@tanstack/query-core"] = path.resolve(
      __dirname,
      "./node_modules/@tanstack/query-core"
    );

    return {
      ...webpackConfig,
    }
  },
}

module.exports = nextConfig

Hey @timneutkens @martpie - Eventually, I managed to rebuild the modules that were preventing us from migrating the remaining routes to the app directory. So, I just wanted to give you guys a heads-up that this issue is no longer a high priority for me. Thanks!

@shuding Any updates on this? Thank you!

Hey @shuding - I know the Next team is working hard on the app router performance issues, but I was just wondering if we have any update on this yet. Thank you!