Next.js: Add support to transpile modules inside node_modules

Created on 9 Jan 2017  ·  103Comments  ·  Source: vercel/next.js

Now some of us ships NPM packages (specially components) written in ES2015 without transpiling them.

That's a pretty good thing specially if they are gonna used in a project like Next.js or CRA (which does transpiling). They offer benefits like:

  • No need to transpile before shipping to NPM
  • Get the benefit of Webpack 2's tree-shaking

But we can't do this now we exclude everything inside node_modules from babel transpiling.

So, here's the proposed solution.

We have an entry in next.config.js to include modules which needs to go through babel. See:

module.exports = {
   transpileModules: [
     "my-component",
     "redux/src"
   ]
}
story feature request

Most helpful comment

The more I use next.js in earnest, and build out a rich library of modules around it, the more this feature becomes important. It's becoming a real PITA replicating the babel compilation step in my internal modules.

🚀🤖

All 103 comments

  • Why is this not doable with webpack() extension?
  • transpileModules sounds better
  • Will we accept regexps?

Why is this not doable with webpack() extension?

I hope you mean custom webpack config. That's doable. But this sits in a existing loader. Getting that is somewhat harder.

transpileModules sounds better

Awesome. I'll update.

Will we accept regexps?
Yep. sure.

Hey,

As I'm starting my own website I'm trying new techs like Lerna/Next/Styled... and would be happy to provide early feedback on this.

I've opened a duplicate issue where I tried to import/transpile a CRA-based module in my NextJs module but didn't know how to make the transpilation happen (note that I'd like to keep my module runnable as a standalone)

I've also noticed that Babel, also based on Lerna, is transpiling each modules before exposing them, but it looks to me better to do like @arunoda suggest and let the client app do the transpiling.

I'd like to have a single babel config for my client and share that config with all my decoupled modules. That's probably not so easy if I want to keep ability to run my modules as standalone, outside of Next runner

My current test project is here: https://github.com/slorber/playground/ I'll try to upgrade it as soon as there's a fork/PR. @arunoda are you working on it?

@slorber currently we are focusing on 2.0 release and we are fine tuning stuff and finding bugs as possible as we can.

I haven't started work on this but we can do this just after 2.0.

Ok so I'll make a fork. I'm already running against 2.0.0 beta because I'm not building a critical website and I don't think webpack 1.13 resolve jsnext:main/module field.

I'm not a bundler expert but I think I'd rather use "module" field of package.json no? "main" seems for already transpiled code as far as I know. But as the webpack config allows to include/exclude transpilation I'm not sure it's relevant. Any recommendation on which of the 3 fields I'd rather use?

@slorber I think webpack only supports main just like NPM. You can use that.
We can check for the filepath in the exclude function in our next.conf.js

Hmm according to what I've seen in practice against Next 2.x I've seen module works (but fails later at runtime because not transpiled) while jsnext:main did not work (as far as I remember). But it's supposed to be supported.

Anyway, jsnext:main or module does not seem to be the solution to this problem so for company-internal modules just enabling transpilation is probably enough

The community has not agreed on one approach right? For example, I was able to use react-youtube the other out of the box with no problems. I'm assuming a big number of modules transpile before publish?

Ref: https://github.com/rauchg/blog/blob/master/components/post/youtube.js

Yes that makes sense to always transpile before publish because you don't know who/how the module will be consumed and you don't want to force the client to setup appropriate babel settings for your lib. That's what Rollup suggest: to publish the module transpiled in different ways so that bundler can decide which to use.

But for company internal packages, the transpilation settings might be the same across several project (like a babel preset) and it makes sense to me to let the client bundler to transpile all the company dependencies

Very much agree @slorber - this would be very handy for internal modules if you're breaking your project up and isolating things as much as possible.

And @rauchg / @arunoda supporting RegExp's would be really nice, so you could have one entry that catches all the company internal modules, using say the NPM org namespace:

// next.config.js
module.exports = {
  transpileModules: [
    /^\@my-npm-org\/.*/
  ]
}

Beautiful suggestion @philcockfield

Hey maybe it could be worth offering some presets. It looks to me most tools (Lerna/npm link...) rely on symlinks so why not something as simple as:

```javascript
module.exports = {
transpileModules: ["symlinks"]
}
````

The more I use next.js in earnest, and build out a rich library of modules around it, the more this feature becomes important. It's becoming a real PITA replicating the babel compilation step in my internal modules.

🚀🤖

I'm working on this today :)

@philcockfield give this a try: https://github.com/zeit/next.js/pull/749

thanks @arunoda

So as commented on your PR if this does not support symlinks the feature will be a bit limited because it won't work with npm link or Lerna, but only for npm modules that are not transpiled (right? I don't see any other usecase unless you commit modules inside /node_modules)

Why not supporting symlinks? is it harder to support?

Also I wanted to test your branch on my app, but I'm not sure what's the best way to do that. Is there any known procedure so we can easily test a branch and it's not too painful for the tester? I've tried some stuff like:

  • npm install https://github.com/arunoda/next.js.git#add-706 : fails because the next /bin folder is empty on github repo
  • git clone of the fork inside /node_modules: not much success (but it might be because of my specific Lerna settings)

What's the best way to test a fork currently?

If you're looking at doing this with next.config.js: module.exports = { webpack: (config, then config.module.rules has a few things, looks like you need to change one of these rules, or add one?:

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

Looking forward to the simpler syntax suggested.

Sorry for my ignorance I cant see what the resolution of this issue is? We would love to be importing es6 into our codebase, we need the tree-shaking .

Is there a PR on this?

@andrewmclagan This issue is still open and has a related PR that probably won't satisfy all (like LernaJS users)

What's the status of this? Are there any other ways to make next's webpack to transpile files imported from node_modules ?

@slorber i will take a look at the PR. Contribute our use-case.

I am facing kind of similiar problem. Trying to use get-urls package. Works find with dev but when i compile it. I got error from uglify

...
{ Error: commons.js from UglifyJs
...

Is there any workaround for this please?

Arunoda will work on it sometime here. He has done before in #749

I'd love to see this feature implemented. As @philcockfield mentioned, it's a common scenario to build up a library of modules that depend on Next.js transpilation, and it'd be great to be able to share components among projects.

This is not only needed for tree shaking. Also for babel plugins like styled-jsx. So if you have a module (like a library) that uses a babel plugin the best solution is to include the ES6 source code and allow your app to transpile it from node_modules. Of course next already includes styled-jsx by default.

Here's what I did

// next.config.js
exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: Object.prototype.toString.call(exclude) === '[object Function]' ? (str => !/mycomponents/.test(str) && exclude(str)) : exclude,
  ...rest
})), config);

I basically replaced each exclude with a custom function.
I do not know what I am doing wrong, but I just cannot make it work.
I need the contents of node_modules/mycomponents to also be transpiled by Next.js

It doesn't even work if I completely override all excludes with an empty array

exports.webpack = config => (config.module.rules = config.module.rules.map(({exclude, ...rest}) => ({
  exclude: [],
  ...rest
})), config);

Please help me :)
Thanks

Hey guys ( @thealjey ) I've been transpiling jsnext:main powered modules for months by now.

I'm not using next.js but I hope it helps.

@damianobarbati no, unfortunately it does not
Configuring webpack directly to transpile whatever is not difficult, but I am struggling to make this work in the context of Next.js

hey all, anyone have found a solution?

i have a local ES6 linked node module i need to import in my project but i cant get the webpack voodoo right !

I'm sure there's a better way, but we run everything through babel on build:

next build && babel .next/*.js --out-dir . --presets=es2015,react

Did this die? I'm looking for a way to transpile a custom module and seems like it's still not possible.

@mattfelten it's on the roadmap for v5 👍

Does anyone have an example of a workaround for this?

@timneutkens Is there any timeline for this? Appreciate that's often an impossible question but we're trying to determine our stack at work as of now and this is a pretty big blocker for us! :)

Workaround suggestions also valid.

@thealjey realise this is an old comment but your solution probably didn't work because there is an include specified as well which would need to be overridden.

Update: looked into this strategy but it's just not sane given all the different loaders for different module directories within next.js' internal configuration. This will need to be first-class.

@chrisui my (temporary) solution was to use babel-plugin-module-resolver, configured like this - "plugins": [["module-resolver", {"root": ["./"]}]]
it is by no means a perfect solution, but, since everything else failed, it works for now
thanks to that I do not need to write a bunch of ../ with every import
this might actually be a better solution to some, though it certainly doesn't help with reusability

@thealjey could you give an example?
I have a project setup where I try this to no avail...
https://github.com/jamesgorrie/nappy

I'd happily try get a PR in as this would make our life so much easier, but there are a few questions like: Should next.js support transpiling of certain modules or should this be up to the transpiler, but the next.js follows the module resolution more strictly. Not sure who to ask or where to start here as new to next.js.

it's on the roadmap for v5 👍

@timneutkens did this make it into v5?

wondering to know.

Just look at where its merged. this was merged 8 days ago. 5.0.0 was released 2 days ago. from the canary branch where this is merged into...

Does anyone have an example on how this can be implemented? Is it supposed to work like this, as mentioned above?

module.exports = {
    transpileModules: ['my-npm-module']
}

or does it look different?

I'm confused. @timneutkens The abovementioned link is to a PR that is still open. Has this NOT been merged in v5 yet?

EDIT: Never mind, this is just a PR to highlight the example.

It's an example, you can use the example without it being merged. transpileModules is something we'll tackle later on.

As a general rule of thumb: When an issue is open it's not released.

@brianyingling I've turned the example into a plugin for an interim solution (v5 only).
It's working for us at the moment, until the more robust, official solution is put in place.

https://www.npmjs.com/package/@weco/next-plugin-transpile-modules

I would love to see an example of this for a single module in the application codebase.

For example, I have a module that I use both server and client side. I haven't been able to get any of the above examples to work, either by factoring the module into its own separate module and yarn linking it, or by hacking the webpack rules.

Here's a simple repro: https://github.com/statico/nextjs-with-async-lib

// pages/index.js
import { foo } from '../lib/test'
export default () => <div>hello {String(typeof foo)}</div>

// lib/test.js
async function foo () {}
module.exports = { foo }

@timneutkens tells me this is because I'm using async/await in the shared module. I guess my solution might be to remove async/await and change everything to .then()-style callbacks.

OK, I found a fix that works for me.

First, I added the config.resolve.symlinks = false setting to my next.config.js configuration per https://github.com/zeit/next.js/issues/3018#issuecomment-380879576

// next.config.js
webpack: (config, { dev }) => {
  config.resolve.symlinks = false
  return config
}

Then I put my shared library — a .js file that uses CommonJS exports and async/await keywords — in a subdir of the application called shared:

// shared/index.js
async function foo () {}
module.exports = { foo }
// shared/package.json
{
  "name": "@myapp/shared",
  "version": "1.0.0",
  "main": "index.js",
  "license": "UNLICENSED",
  "private": true,
  "dependencies": { ... }
}

And finally I added a postinstall script to link it all together when anyone does a yarn install in the main application:

// package.json
{
  ...
  "scripts": {
    "postinstall": "cd shared ; yarn -s unlink ; yarn link && yarn && cd .. && yarn link @myapp/shared",
   ...

Now my Mocha tests pass on the server side, my custom Koa server starts up fine, and there's no more crazy Cannot assign to read only property 'exports' of object '#<Object>' in my NextJS pages.

I had this same issue when upgrading to NextJs 5.1.0. One or two of the node modules in next were not transpiling fat arrow functions and throwing errors in IE11. I had previously been through setting up individual polyfills and in the end I opted to target those modules files with babel-polyfill in my next.config.js with this:

module.exports = {
  webpack: (config, { dev }) => {
    const polyfill = new Promise((resolve, reject) => {
      const originalEntry = config.entry

      originalEntry().then(entries => {
        if (entries['main.js']) {
          entries['main.js'].unshift('./client/polyfills.js')
          entries['main.js'].unshift('babel-polyfill')
        }
        config.entry = entries

        resolve()
      })
    })

    config.module.rules.push(
     {
        test: path.resolve('./node_modules/next/node_modules/'),
        loader: 'babel-loader',
        options: {
          babelrc: false,
          cacheDirectory: false,
          presets: ['es2015']  
        }
      }
    )

    return polyfill.then(() => { return config })
  }
}

Hope this helps someone.

ESM works like a charm.

With a custom Next.js server in index.js, I can run this command to start the server and esm kicks in perfectly, resolving ES modules in Lerna-symlinked project packages.

node -r esm index.js

@curran cool, can it replace babel-node ?

@curran I would avoid doing that in production

@blackbing I don't know.

@thealjey Why is that?

In case anyone is looking for a quick and easy solution, here's what I did. I created a subdirectory, shared/, with any code we want to run on both the backend via standalone Node script and client via NextJS. It has its own package.json and declares its name as @myproject/shared.

Then, in the main (parent) project, I added a postinstall script to package.json like this: cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared — then run yarn at least once, and change your imports to import { whatever } from '@myproject/shared/somefile'

This way the shared code works without any crazy transpilation steps, plus you don't have to re-run yarn/npm each time you make an update since yarn link makes a symlink.

For those using TypeScript, @weco/next-plugin-transpile-modules should not work. I created a fork to handle Next's withTypescript: https://github.com/KeitIG/next-plugin-transpile-modules

I still need to figure out how to do things properly when we need to have server-side code in TypeScript too though.

Any news on this?

And yet another one by me, in the following gist. It handles TypeScript, and also specific packages of a @scope, rather than all packages. https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

I just put together a simple working example that uses esm and lerna

https://github.com/curran/nextjs-esm-example

/cc @jdalton

Personally got this working with the following next.config.js:

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel
      ]
    })

    return config
  }
}

It babels everything in node_modules, which I needed in order to achieve IE 11 compatibility...

I'd also appreciate a solution for this, struggling with adding non-transpiled npm packages to my project. Had to dowload them to vendor/ for now :(
Really annoying

@bel0v I believe you should already be able to accomplish this with next-plugin-transpile-modules. This issue should likely be closed. cc/ @timneutkens

I'd still like to investigate alternative solutions.

Recently Jamie wrote a very detailed thread about the issue of compiling node_modules: https://twitter.com/jamiebuilds/status/1080840492525350912

I read the thread by Jamie, though I would also like to share Henry Zhu and Babel's take on this situation and solution.
https://babeljs.io/blog/2018/06/26/on-consuming-and-publishing-es2015+-packages

(Not disagreeing with Tim, just thought I'd share, many pros and cons. Might help Tim in investigating alternative solutions)

Yeah we've been talking with many people about this issue the past half year, including Henry 😄

Concerns about transpiling node_modules notwithstanding, wanting to transpile your own packages in a monorepo is a very common requirement, to which these concerns do not apply

@dcalhoun I've tried it but unfortunately I still get unexpected token error. There is an open Next 7 issue on this plugin which might be related

@bel0v

You should read the FAQ ;) there's a solution to this problem: https://github.com/martpie/next-plugin-transpile-modules#i-have-trouble-making-it-work-with-nextjs-7

I've been using this plugin on multiple projects, and it gets the job done nicely. The Next 7 issue is weird, I am not sure if this is coming from Next or Babel, I opened an issue here anyway: https://github.com/zeit/next.js/issues/5393

@martpie yeah I believe I've tried that.. anyways I'll give it another try

@martpie we've started using next7 with a consistent babel.config.js, and yarn workspaces, I might see if I can setup a simple example.

I have forked basic example here
https://github.com/bel0v/learnnextjs-demo
in it, I installed an untranspiled dependency (wired-elements), got a build error Unhandled Rejection (SyntaxError): Unexpected token { and tried to fix it suggested way.
I'm thinking maybe I need some additional babel plugins for it to work.. 🤔

@bel0v in the FAQ again, there is an explanation on why Lerna setups do not work (TL,DR; you are probably using is wrong)

@martpie ah, got it! Didn't realise the third-party package was setup with Lerna. Thanks

It seems https://twitter.com/jamiebuilds has been suspended, so can't read the thread there anymore. #3018 Got closed in reference to this issue, so I'm wondering what the alternative approaches being considered are?
Do these represent the state of the art / best practices of next.js for these use-cases atm?
https://github.com/curran/nextjs-esm-example
https://github.com/wellcometrust/next-plugin-transpile-modules
https://github.com/martpie/next-transpile-modules
https://github.com/zeit/next.js/tree/canary/examples/with-yarn-workspaces

So, if you, like me, are working on a project that has to support IE11, you really have to transpile all of the code inside node_modules/. In Next.js 7.x I was using the following setup, which worked great.

Unfortunately, it stopped working in Next.js 8.x with errors that modules failed to import other modules because they didn't have a default export. I then came up with the below config for Next.js 8.x, which only transpiles the code in node_modules/ with @babel/preset-env, and no other plugins.

This is combined by setting my browserlist property in the package.json:

  "browserslist": "defaults, IE >= 11, EDGE >= 14, Safari >= 11, Chrome >= 41, Firefox >= 52",

Next 7.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: [
        options.defaultLoaders.babel,
      ],
    })

    return config
  },
}

Next.js 8.x

next.config.js

module.exports = {
  webpack: (config, options) => {
    config.module.rules.push({
      test: /\.js$/,
      include: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],
          plugins: ['@babel/plugin-syntax-dynamic-import'],
        },
      },
    })

    return config
  },
}

Unfortunately, I haven't figured out how to use @babel/plugin-transform-runtime with this setup yet, so it will probably spit out quite a few helpers in the code 😞 hopefully gzip takes care of it 😆 😅


I think it would be awesome if Next.js could give us an option to correctly transpile node_modules/ to work with whatever browserlist you have. It seems like any large sites that have corporate users kind of are dependent on this to properly support older browsers.

As the maintainer of next-transpile-modules (based on the awesome work of @jamesgorrie), I am happy to help anyone facing this issue here.

I've been working on professional projects for more than a year with this plugin, and so far it played nicely.

Native support from Next.js would of course be awesome and I would be happy to help integrating this feature into the next package. I know Tim had some ideas he wanted to try, but anyway.

Cheers!

@martpie I quickly looked at your project, but didn't find a quick way to transpile _all_ modules, is that possible? ☺️

Also, I see that you are picking options.defaultLoaders.babel and using that as the babel loader. When doing that with Next.js 8.x I had the problem that some modules would fail to be properly recognised as a CJS module after that, and then other libs would fail to import them, e.g:

./pages/_glamor.js
Attempted import error: 'css' is not exported from 'glamor'.

./components/project-selector.js
Attempted import error: 'react-select/lib/Async' does not contain a default export (imported as 'AsyncSelect').

./node_modules/react-select/dist/react-select.esm.js
Attempted import error: 'react-input-autosize' does not contain a default export (imported as 'AutosizeInput').

./pages/signup/full.js
Attempted import error: 'react-select/lib/Creatable' does not contain a default export (imported as 'CreatableSelect').

./components/markdown-editor.js
Attempted import error: 'react-simplemde-editor' does not contain a default export (imported as 'SimpleMDEEditor').

./components/pagination.js
Attempted import error: 'react-js-pagination' does not contain a default export (imported as 'UpstreamPagination').

./node_modules/react-google-recaptcha/lib/es/recaptcha-wrapper.js
Attempted import error: 'react-async-script' does not contain a default export (imported as 'makeAsyncScriptLoader').

./pages/_glamor.js
Attempted import error: 'rehydrate' is not exported from 'glamor'.

That's why I switched to providing a custom babel config for node_modules/, which only transpile the code using preset-env, and skips the Next.js-specific transforms. What do you think of this approach?

Cheers 🍻

@LinusU Maybe try transpileModules: ['(.*?)'] and tell me if it works?

But it may not be working in a future major release, so be careful.

More generally, I don't recommend (read "highly discourage") to transpile the whole node_modules folder, it will take forever to compile and packages should provide ES3-compatible code (so IE11 compatible).

Only transpile the module you need to! (like lodash-es, local modules etc...)

packages should provide ES3-compatible code (so IE11 compatible).

This is not the reality I've seen though, and I actually don't agree. The module authors will never know exactly which browsers I'm targeting, and if they ship older code they will potentially penalize users that are targeting modern browsers.

it will take forever to compile

It's a bit slow at startup for me, but after that, it seems to be cached and when making changes to a specific page I see near-instant reloads.

Only transpile the module you need to!

This would require me to know exactly which packages are compatible with IE11 and which aren't, as well as keeping this information up to date anytime any dependency (even transient dependencies) changes. I don't see how this is realistic 🤔

The important thing is that ESM entry points that are provided in package.json module are commonly ES5 with ES6 imports/export for tree shaking. So this is the job for a bundler (Webpack) and not transpiler (Babel), unless stated otherwise. A lot of well-mainatained packages already have ESM entry points, e.g. redux/es for Redux that was mentioned by OP.

If you're looking at doing this with next.config.js: module.exports = { webpack: (config, then config.module.rules has a few things, looks like you need to change one of these rules, or add one?:

  { loader: 'babel-loader',
    include: '/Users/me/gh/guide/node_modules/next/dist/pages',
    options: 
     { babelrc: false,
       cacheDirectory: true,
       sourceMaps: 'both',
       plugins: [Object] } },
  { test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: 
     [ '/Users/me/gh/guide',
       '/Users/me/gh/guide/node_modules/next/dist/pages' ],
    exclude: [Function: exclude],
    query: 
     { babelrc: true,
       cacheDirectory: true,
       sourceMaps: 'both',
       presets: [] } } ]

Looking forward to the simpler syntax suggested.

Works fine for me

{
    test: /\.js(\?[^?]*)?$/,
    loader: 'babel-loader',
    include: [
        path.resolve(__dirname, './node_modules/next/dist/pages'),
    ],
    query: {
        cacheDirectory: true,
        sourceMaps: 'both',
        presets: ['@babel/preset-env'],
        plugins: ['@babel/plugin-proposal-object-rest-spread']
    }
},

I ran into this issue using a Lerna mono repo and was scratching my head as to what the cause was. Since the error is coming from webpack it doesn't give good details besides that it's missing a loader, which isn't helpful. Thankfully I found this github issue!

I'm going to leave my solution here for anyone else searching for this issue and is also using Lerna:

Create a prepublish script for the shared package that transpiles the source into a dist directory and tell Lerna to point to the dist directory when linking:

// package.json
"main": "dist",
"scripts": {
  // I'm using the react-app preset because it's easy
  "prepublish": "babel --presets react-app --plugins @babel/plugin-transform-modules-commonjs src --out-dir dist"
},
// This instructs Lerna to use dist when symlinking
"publishConfig": {
  "directory": "dist"
}

Now when you lerna bootstrap it'll run the prepublish script and transpile the source so Next can consume it.

If you're using lerna you can make symlinks to get transpiled using next-transpile-modules. How to use that package with lerna is written at the bottom of the documentation.

For anyone searching for sharing code across NextJs apps, I just like to report that @LinusU's solution worked for me when trying to share React components and utils between multiple NextJs apps across my mono repo:

// next.config.js
const aliasPathsToResolve = [
    { name: 'components', path: path.resolve(__dirname, './components') },
    { name: 'Common', path: path.resolve(__dirname, '../../common/react/') },
]
module.exports = () => {
    return  {
        webpack(config, { defaultLoaders }) {
            config.module.rules.push({
            test: /\.(js|jsx)$/,
            include: [path.resolve(__dirname, '../../common/react/')],
            use: [defaultLoaders.babel],
        })

            /** Resolve aliases */
        aliasPathsToResolve.forEach((module) => {
            config.resolve.alias[module.name] = module.path
        })
        }
    }
}

I'm using the latest version of NextJs at the time of this post.

@Lwdthe1 I tried your code and initially got this error:

TypeError: Cannot read property 'then' of undefined
    at getBaseWebpackConfig (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/build/webpack-config.js:85:25)
    at async Promise.all (index 0)
    at async HotReloader.start (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/hot-reloader.js:14:1675)
    at async DevServer.prepare (/c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/server/next-dev-server.js:7:223)
    at async /c2/wiz-frontend/packages/pipeline-view/node_modules/next/dist/cli/next-dev.js:22:359

Did some tweaking and ended up with this:

const path = require("path");

const libPath = "../components/src"
const aliasPathsToResolve = [
  { name: "Common", path: path.resolve(__dirname, libPath) }
];

module.exports = {
  webpack: (config, { defaultLoaders }) => {
    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, libPath)],
      use: [defaultLoaders.babel]
    });

    /** Resolve aliases */
    aliasPathsToResolve.forEach(module => {
      config.resolve.alias[module.name] = module.path;
    });
    return config
  }
};

But the ran into another error:

export { default as NavBar } from "./NavBar/NavBar"
^^^^^^

SyntaxError: Unexpected token 'export'
    at wrapSafe (internal/modules/cjs/loader.js:1055:16)
    at Module._compile (internal/modules/cjs/loader.js:1103:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1159:10)
....

which seems to have been faced before in #2850 and #883.

So it does seem like the only solution is: https://github.com/martpie/next-transpile-modules#but-i-really-need-to-make-it-work-with-lerna

From what I've heard there will be RFC presented soon how Next.js is planning to solve this issue, but if someone needs to fix it right now, I've published on npm my solution from https://github.com/zeit/next.js/pull/10098 which you can use by putting following in package.json:

    "next": "npm:@sheerun/[email protected]",

and following to next.config.js:

  babelIncludeRegexes: [/turf/],

(in my case I needed all turf files to be precompiled with babel)

This issue have any progress?

I use next.js 9.2.0, but babelIncludeRegexes option not working

This issue have any progress?

next-transpile-modules aims to solve this problem exactly, did you give it a try?

Hi @martpie,

Already solve my problem .babelrc file edit. I reference this issue

Thx

@martpie I am using next-transpile-modules but still, I am facing below error while I am trying to build the application. I am using monorepo with shared codebase. Trying to access components from shared like '@myapp/shared/components/componentname.js'. I am using nextjs 9.x and custom next.config.js.

Error
`
Module parse failed: Unexpected token (12:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| const Spinner = props => {
| const renderDefaultSpinner = (spinnerClass, { ...others }) => (
>


| );
|

Build error occurred
Error: > Build failed because of webpack errors
`

next.config.js
const withTM = require('next-transpile-modules')(['@myapp']); module.exports = withPlugins([withTM, withBundleAnalyzer], { ... }

Please help what I am doing wrong here.

@raghav1086 Can you open an issue on the repo? ;) it will avoid noise for people out here.

+1

I have a src/ directory for my project and lib/ for a starter framework that exports some common utils/wrappers that I reuse throughout a few different nextjs apps (my starting point)

lib does not get noticed when I start the dev server. any components from lib/ don't go through the loader and give an error

I used a variation of @Lwdthe1's solution (https://github.com/zeit/next.js/issues/706#issuecomment-569041997) to fix the src and lib issue in my comment above. Basically the same thing except this uses config.resolve.modules instead of looping through the aliasPathsToResolve array.

  webpack: (config, options) => {
    config.resolve.modules = [
      './src/',
      './lib/',
      'node_modules'
    ];

    config.module.rules.push({
      test: /\.(js|jsx)$/,
      include: [path.resolve(__dirname, './lib/')],
      use: [options.defaultLoaders.babel],
    });

What's the working solution for lerna, nextjs, and babel these days?

I'm trying to avoid pre-transpiling my libraries before import, and I've hit a brick wall with every solution here. Here's what I can't get working:

  • next-transpile-modules.
  • resetting the preset-env settings.
  • updating the next-babel-loader include and exclude rules to pass/fail respectively.

@mikestopcontinues next-transpile-modules worked out of the box for me with TypeScript.

@calebmpeterson and @martpie (I see you! 👀). I circled back to the plug, and the problem seems to be that there's no way to reference sub-modules. For instance, pattern '@mono/components' won't support importing '@mono/components/Div' or whatever. And specifying '@mono/components/Div' as the pattern doesn't work either... not that I would want to do that for every shared component. I also tried reverse engineering the regex generation to create match patterns, and while the output regex works, something else is going on under the hood that isn't.

Ideally, I would just like to specify '@mono` to take care of everything, and leave my package.json to be the single source of truth for what each of my apps depends on. Similarly, I would like to avoid maintaining index files that import/export everything in every single one of my libs just to be able to access sub-modules.

To circle back, I believe the current issue could be entirely resolved if there were some way to pass rootMode: 'upward' through next-babel-loader, so that babel could handle the transpiling logic. Maybe this opens up other Next-related issues, but the root of the problem seems to be the atypical way Next is tangled into webpack and babel. Surely, there's a way to leave babel-loader separate from Next's additional logic?

Just an update on the next-transpile-modules front. I had misdiagnosed the error. No import works using this method (index or submodule) if you need a custom .babelrc config. The custom settings just don't get applied to the required code. This is again a rootMode: 'upward' issue.

@mikestopcontinues You need to use babel.config.js (global config) with next-transpile-modules, and not .babelrc (local config), it is explained in the FAQ ;)

@martpie You have no idea how embarrassed I am. I had to have read that line a dozen times the last few weeks and never bothered to click through to the issue. That totally worked. Thanks!

next-transpile-modules broke React for me. It now throws that I use invalid hooks, while I transpiled THREE example module

Could someone re-iterate what the best configuration is to get transpilation to work. I dont get what i have to write in babel.config.js

@masbaehr in most cases just adding next-transpile-modulesto your next.config setup

The only issue is next-transpile-modules does not support Yarn 2 pnp.

Was this page helpful?
0 / 5 - 0 ratings