Next.js: Webpack alias does not work when alias is outside of next root

Created on 3 May 2019  Â·  10Comments  Â·  Source: vercel/next.js

Bug report

Describe the bug

Let's say that you have your NextJS root at ./next and your React components in ./client. Now, when you configure a webpack alias to ./client/components with @components and use it in ./next/pages/Page.js - the build will fail with this error:

➜  next-webpack-issue git:(master) yarn build
yarn run v1.15.2
$ next build ./next
Creating an optimized production build ...

Failed to compile.

../app/pages/Index.js 1:21
Module parse failed: Unexpected token (1:21)
You may need an appropriate loader to handle this file type.
> export default () => <div>Hello World!</div>;
|

> Build error occurred
Error: > Build failed because of webpack errors
    at Object.build [as default] (/home/jsarnowski/Workshop/next-webpack-issue/node_modules/next/dist/build/index.js:192:15)
    at process._tickCallback (internal/process/next_tick.js:68:7)
error Command failed with exit code 1.

To Reproduce

Here's an easy reproduction repo: https://github.com/sarneeh/zeit-next.js-issues-7234

Just run yarn install and yarn build after that.

Expected behavior

I expect the alias to work.

System information

  • OS: Ubuntu 18.04
  • Version of Next.js: 8.x and also 7.x

Most helpful comment

I as a developer still expect the alias to work or a description in documentation of aspects of the next.js framework which break when doing otherwise 'normal' Webpack configuration such as module aliasing in combination with workspaces. It should at least be documented where the node ssr or client javascript breaks due to the framework's implementation.

All 10 comments

I just noticed that it might have nothing to do with aliases. It's just because nextjs default webpack config does only include the nextjs root directory into babel-loader, that's why the directory outside can't get compiled, am I right?

I am getting the same issue, but not even alias, importing directly dose not work to me as well.
For ex, lets say I have the following folder structure:

<project_root>
    |__node_modules/
    |__src/
    |    |__lib/
    |    |    |__myAwesomeUtils.ts
    |    |    |__ ...
    |    |__www/
    |    |    |__pages/
    |    |        |__HomePage.tsx
    |    |        |__ ...
    |    |__server/
    |    |    |__server.ts  // custom server
    |    |    |__ ...
    |__next.config.js
    |__tsconfig.js
    |__tsconfig.server.js
    |__package.json
// server.ts
...
const nextApp = next({ dev, dir: path.join(process.cwd(), 'src/www') });
...



md5-d47649f4f331fc365a5e205298b406bf



// next.config.js
module.exports = withTypescript({
    ...
    distDir: '../../.next',
    ...
});

Everything work fine until I import myAwesomeUtils.ts in HomePage.tsx. Then I tried to build the project and got this error: You may need an appropriate loader to handle this file type.

Any clue? How can I have the above folder structure to work smoothly?

@tronjs I guess you need to either have everything in your NextJS rootDir or add specific paths to the webpack config. In the second case - I'm not sure if it will break anything within NextJS.

yes @sarneeh, I did try both solutions you mentioned. The first solution, of course, it works to me, but it changes my convention folder struct from the beginning. But the second one, I tried to change the webpack context and I have no luck, nextjs said it cannot resolve modules for its own process.

For now I am temporary move the pages folder out, put it the same level with server and lib folder and change nextjs's root dir to src

But it will be so awesome if nextjs team can consider this and having an option that let us free to customize the folder structure or something like that rather than everything rely on nextjs's root dir

@tronjs I had the same issue as you had with the webpack approach. The solution is that you need to be sure that you merge your config and the nextjs config. Be sure that you don't replace the values but append them. Have you tried that?

yes @sarneeh, I did, I did merge webpack config in nextjs config, not sure if I was missing something, but I cannot get it to work, can you please share your working config @sarneeh? thank you!

@tronjs The mistake I have taken when merging the webpack configs was using lodash.merge method, which deeply merges the objects, but only objects. It was somehow breaking array properties. What worked for me was using webpack-merge package. Try it out!

ok @sarneeh, I finally got this to work by adding custom rules in webpack config, somethings like this:

// next.config.js
module.exports = withTypescript({
    ...
    distDir: '../../.next',
    webpack(config, options) {
        config.module.rules.push({
           test: /\.(ts|tsx)$/,
           include: [path.join(__dirname, 'src/lib')],
           use: [
             {
               loader: 'next-babel-loader',
               options: {
                  asyncToPromises: false,
                  cwd: path.join(__dirname, 'src/lib'),
                  isServer: false,
               },
             },
           ],
        });
      return config;
    }
    ...
});

I just tried this config pattern for both my own project and your issue repo and it just works fine
Thank you for your webpack-merge suggestion, maybe someday i will use it if the config become more complexly

@tronjs No problem :) I guess that the problem is solved :smile:

I as a developer still expect the alias to work or a description in documentation of aspects of the next.js framework which break when doing otherwise 'normal' Webpack configuration such as module aliasing in combination with workspaces. It should at least be documented where the node ssr or client javascript breaks due to the framework's implementation.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pie6k picture pie6k  Â·  3Comments

YarivGilad picture YarivGilad  Â·  3Comments

knipferrc picture knipferrc  Â·  3Comments

formula349 picture formula349  Â·  3Comments

wagerfield picture wagerfield  Â·  3Comments