26

I'm trying to import a functions from a dependency to my next/react functional component, but somehow I keep getting the following error:

SyntaxError: Unexpected token 'export'

That's the function I'm trying to import:

export function classes(...args) {
    const list = [];
    for (let i = 0; i < args.length; i++) {
        const entry = args[i];
        if (typeof entry === "string") {
            list.push(entry);
        }
        else {
            for (let key in entry) {
                if (entry[key]) {
                    list.push(key);
                }
            }
        }
    }
    return list.join(" ");

There additionally is a classes.d.ts next to the classes.js above:

export declare function classes(...args: Array<string | {
    [key: string]: any;
}>): string;

Exporting this code identically from within the project works fine, but not when I use an external library from node_modules. How so?

Read about next-transpile-module, but haven't been able to make it run with this one either.

The only way to make the import work is using relative paths ../../node_modules/thedependency/class - how can I make it work properly?

Johnny Kontrolletti
  • 727
  • 1
  • 10
  • 22
  • So this comes from node_modules? If not, could you try to move the first curly braces on the same line as the declaration? This is the only thing which looks kind of wrong to me. Ah, and is it a ts file? – Gh05d Jan 28 '21 at 11:37
  • 1
    @Gh05d yes it comes from node_modules and it's a .js file – Johnny Kontrolletti Jan 28 '21 at 11:39
  • I tried using the above solution but didn't succeed. Please help. https://stackoverflow.com/questions/68212291/implement-pusher-for-real-time-web-notifications-in-nextjs. – hs27 Jul 05 '21 at 06:50

5 Answers5

41

UPDATE: All features of next-transpile-modules are now natively built-in Next.js 13.1. you should be able to use Next's transpilePackages option to transpile external packages


Old Answer: So the dependency in node_modules folder exports a function using ES6 import/export module. The code will throw error when it running in browser since browser cannot recognize the ES6 module syntax.

The reason is that, by default, Next.js configs the babel-loader to only transpile the ES6 code in the src folder, any ES6 code imported from node_modules will directly go into final bundle without transpiling.

Try to modify the webpack config in next.config.js file to let the babel loader transpile the es6 dependency. You may want to use this package next-transpile-modules

MarkoCen
  • 2,189
  • 13
  • 24
  • Thanks the hint! What made it work is using `const withTM = require("next-transpile-modules")(["mojave/classes"]);`. What's odd is that transpiling the whole package (the way it's supposed to work) like this `require("next-transpile-modules")(["mojave"]);` will fail - do you have any idea how so? Trying to transpile `mojave` will throw an error that it's not able to find the package. – Johnny Kontrolletti Jan 28 '21 at 15:15
  • I have no idea.. I think it depends on how mojave package structure its code. from the readme of next-transpile-module, it needs the transpiling package has a valid main field in package.json – MarkoCen Jan 28 '21 at 15:29
  • @Tim I also have ERR_MODULE_NOT_FOUND error, have you been able to overcome this? – agentp Nov 08 '21 at 14:15
  • @agentp Yes, if I remember correctly, I actually had to edit the package itself - an `index.js/ts` was missing. – Johnny Kontrolletti Nov 08 '21 at 15:49
  • 1
    Why do we still need a plugin if Nextjs 12 "supports" native ES modules ? – Jeremy Tenjo Jun 14 '22 at 11:38
  • https://github.com/martpie/next-transpile-modules/releases/tag/the-end – cfl Jan 12 '23 at 13:25
8

There's another way:

import dynamic from 'next/dynamic'

const DynamicComponentWithNoSSR = dynamic(
  () => import('package'),
  { ssr: false }
)

// ...


// use it in render like:
<DynamicComponentWithNoSSR />

Found in https://stackoverflow.com/a/60738624/3051080

Context:

I was getting the same error: Unexpected token 'export'; with a node_modules dependency made for the browser (client-side). I tried with @MarkoCen's answer with no luck, because I got a window is not defined error later.

The dynamic approach did the trick.

Gus
  • 6,545
  • 4
  • 36
  • 39
2

Next.js 13 has an option called transpilePackages that is somewhat equivalent to next-transpile-modules, check the docs here: https://beta.nextjs.org/docs/api-reference/next.config.js#transpilepackages.

I use it for youtubei.js on 'next.config.js'

experimental: {
    transpilePackages: ['youtubei.js'],
}
Adel
  • 5,341
  • 2
  • 21
  • 31
0

As you said that it is a js file, I am pretty sure to pinpoint your problem to this line: export function classes(...args): string

You have a Typescript declaration behind the function declaration. So remove the : string part and you should be fine.

Gh05d
  • 7,923
  • 7
  • 33
  • 64
  • I just copied the function into my code and imported it and I had no problems. Except that a curly brace was missing at the end and that it returned numbers instead of strings. Don't know whether that is helpful to you. – Gh05d Jan 28 '21 at 12:14
  • Copying it inside of my code works fine as well, but importing it from node_modules breaks it. What happens if you `npm i mojave` and then `import {classes} from "mojave/classes". ` – Johnny Kontrolletti Jan 28 '21 at 12:18
  • I get the same error as you do. Baffliing. – Gh05d Jan 28 '21 at 13:19
  • Just a guess, but `export` is **es6** syntax. But I guess your webpack or whatever you use expects `module.exports`. So maybe you would have to run it through a babel-loader or something similar for it in order to work. – Gh05d Jan 28 '21 at 13:22
0

In my case, updating node.js version make it work!

Kunal Tyagi
  • 2,341
  • 1
  • 15
  • 26