Skip to content
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

Files outside of app directory will not be transpiled #5666

Closed
Swatinem opened this issue Nov 13, 2018 · 19 comments
Closed

Files outside of app directory will not be transpiled #5666

Swatinem opened this issue Nov 13, 2018 · 19 comments

Comments

@Swatinem
Copy link

Bug report

Describe the bug

I have a monorepo usecase, where I want to share code between the next app and other modules that are located outside of the app folder.

It will end up with this error:

{ Error: (client) ../foo.ts 1:0
Module parse failed: The keyword 'interface' is reserved (1:0)
You may need an appropriate loader to handle this file type.
> interface Foo {
|   prop: string;
| }
 @ ./pages/index.tsx 4:0-28 8:5-8
 @ multi ./pages/index.tsx

To Reproduce

I have set up a simple repo here, based on the next-typescript example:

https://github.com/Swatinem/next-monorepo/tree/master

Expected behavior

Whatever I import should be transpiled like everything else, period.

System information

  • OS: linux
  • Version of Next.js: next@7.0.2

Additional context

Related issue (possibly a duplicate?): vercel/next-plugins#234
Also related maybe:

@timneutkens
Copy link
Member

Sounds like this is a duplicate of #706

@Swatinem
Copy link
Author

Just for reference, this is the extremely ugly workaround I found for this:

    // NOTE(swatinem): we just assume the typescript loader is configured last
    const tsxRules = config.module.rules[config.module.rules.length - 1]

    // By default next-typescript only includes things in the app root for no real reason -_-
    // See: https://github.com/zeit/next-plugins/blob/be21851f63e82845387e576f5f2ed3e5c448cb97/packages/next-typescript/index.js#L51
    // See: https://github.com/zeit/next-plugins/issues/234
    tsxRules.include = undefined

    // Also, apparently babel does not search for the `.babelrc` based on the `root`
    // option correctly when the file to transpile is outside of the root.
    // See: https://babeljs.io/docs/en/options#root
    // So we just pass a path to the babelrc manually here
    defaultLoaders.babel.options.configFile = path.join(__dirname, '.babelrc')

@jakemmarsh
Copy link

jakemmarsh commented Feb 8, 2019

Thanks @Swatinem! Made it slightly more resilient by searching for the relevant loader rather than relying on index:

config.module.rules.forEach((rule) => {
    const ruleContainsTs = rule.test.toString().includes('ts|tsx');

    if (ruleContainsTs && rule.use && rule.use.loader === 'next-babel-loader') {
      rule.include = undefined;
    }
  });

@felixmosh
Copy link
Contributor

@Swatinem, Thanx for the workaround I've spent few hours till found this thread.

@revskill10
Copy link
Contributor

For easier debug, you can console.log the config and find out the exact ts-loader, then modify it.

@timneutkens
Copy link
Member

Going to track this in #706

@Jonasdoubleyou
Copy link

Apparently someone changed the regex in the rules to /\.(tsx|ts|js|mjs|jsx)$/, thus the fix suggested by @jakemmarsh only works if you check for .includes("tsx|ts") ...

@jescalan
Copy link
Contributor

I feel like this should be re-opened because it's a different issue. This one is for files outside of the nextjs root, and #706 is for files within the nextjs root, but in the node_modules folder.

@steida
Copy link
Contributor

steida commented Oct 31, 2019

I seems that transpileModules works for me.

module.exports = withBundleAnalyzer(
  withTranspileModules({
    // To force Next.js to transpile code from other workspace packages.
    // https://github.com/martpie/next-transpile-modules
    transpileModules: ['evolu'],
    // We need server for local next export for integration tests.
    // We can detects ZEIT Now runtime via AWS_REGION.
    target: process.env.AWS_REGION ? 'serverless' : 'server',
    // Enforce relative paths for integration tests.
    // https://github.com/zeit/next.js/issues/2581
    assetPrefix: './',
  }),
);

@brysonandrew
Copy link

brysonandrew commented May 15, 2020

You can also specify a path to an external folder.

config.module.rules.forEach((rule) => {
    const isTsRule = rule.test && rule.test.toString().includes('tsx|ts');
    if (isTsRule && rule.use && rule.use.loader === 'next-babel-loader') {
        rule.include = [
            path.join(__dirname, 'path', 'to', 'external', 'folder'),
            ...rule.include
        ];
    }
});

@Maycon-Santos
Copy link

@jakemmarsh This works for me:

const ruleString = rule.test ? rule.test.toString() : ''
const ruleContainsTs = /tsx?/.test(ruleString)

if (ruleContainsTs && rule.use && rule.use.loader === 'next-babel-loader') {
  rule.include = undefined
}

@desmap
Copy link

desmap commented Aug 19, 2020

Does Next dev mode rebuilds on change of the external files?

@jescalan
Copy link
Contributor

We made this library to do this - it's not 100% reliable but it's pretty good.

https://github.com/hashicorp/next-remote-watch

@gfortaine
Copy link
Contributor

gfortaine commented Jan 20, 2021

@brysonandrew It looks like that we would also need to look for the loader 'next-babel-loader' in case of use is an array :

  const hasNextBabelLoader = (r) => {
    if (Array.isArray(r.use)) {
      return r.use.find(l => l?.loader === 'next-babel-loader')
    }

    return r.use?.loader === 'next-babel-loader';
  }

  if (/(ts|tsx)/.test(String(rule.test)) && hasNextBabelLoader(rule)) {
    rule.include = [
      ...rule.include,
      path.join(__dirname, '..', 'portal')
    ];

    return rule;
  }

@spanwair
Copy link

I made even more simple. The fact is that rule.use can be Object or Array. Which fail to include shared files to all tsx|ts tests.

  webpack: (config) => {
    config.module.rules.forEach((rule) => {
      if (
        rule.test && rule.test.toString().includes('tsx|ts')
      ) {
        rule.include = [
          ...rule.include,
          require('path').join(__dirname, '../packages/shared'),
        ];
      }
    });
    return config
  },
}

@MythicManiac
Copy link

next-transpiled-modules didn't work for us in it's 5.x or 6.x versions, but 4.1.0 seems to be working. They seem to have swapped to enhanced-resolve between versions 4 and 5, which at least when trying to resolve local packages according to the monorepo setup found at https://github.com/NiGhTTraX/ts-monorepo does not work.

The solution by @spanwair did work however 👍

@cliffordfajardo
Copy link

NextJS introduced an experimental option to allow imports from outside the project directory. I tried it out in our mono repo and was able to get it to work

#22867

@taletski
Copy link

taletski commented Jan 23, 2022

If if you attempt to transpile .tsx files as well, you might get the following error ModuleNotFoundError: Module not found: Error: Can't resolve 'react/jsx-dev-runtime' in ...

In this case, Webpack fails to import react/jsx-dev-runtime from outside of the working dir.

The solution was to add Webpack aliases for the missing modules:

config.resolve.alias["react/jsx-runtime"] = require.resolve("react/jsx-runtime")
config.resolve.alias["react/jsx-dev-runtime"] = require.resolve("react/jsx-dev-runtime")
// you may want to add more depending on your use case (take it from the error description)

so that now my full config is:

// next.config.js
module.exports = {
  experimental: {
    externalDir: true,
  },
  webpack: config => {
    config.resolve.alias["react/jsx-runtime"] = require.resolve("react/jsx-runtime")
    config.resolve.alias["react/jsx-dev-runtime"] = require.resolve("react/jsx-dev-runtime")
    return config
  },
}

@github-actions
Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests