Next.js: 添加对 node_modules 内的转译模块的支持

创建于 2017-01-09  ·  103评论  ·  资料来源: vercel/next.js

现在,我们中的一些人发布了用 ES2015 编写的 NPM 包(特别是组件),而无需转译它们。

这是一件非常好的事情,特别是如果它们将用于 Next.js 或 CRA(进行转译)之类的项目。 它们提供以下好处:

  • 在运送到 NPM 之前无需转译
  • 从 Webpack 2 的 tree-shaking 中获益

但是我们现在不能这样做,我们node_modules 中的所有内容从 babel 转译中

所以,这是建议的解决方案。

我们在next.config.js有一个条目来包含需要通过 babel 的模块。 看:

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

最有用的评论

我越认真地使用next.js ,并围绕它构建了一个丰富的模块库,这个特性就变得越重要。 它正在成为一个真正的 PITA,在我的内部模块中复制 babel 编译步骤。

🚀🤖

所有103条评论

  • 为什么webpack()扩展名不可行?
  • transpileModules听起来更好
  • 我们会接受正则表达式吗?

为什么这对 webpack() 扩展不可行?

我希望你的意思是自定义 webpack 配置。 这是可行的。 但这位于现有的加载器中。 得到它有点困难。

transpileModules听起来更好

惊人的。 我来更新。

我们会接受正则表达式吗?
是的。 当然。

嘿,

当我开始自己的网站时,我正在尝试像 Lerna/Next/Styled... 这样的新技术,并且很乐意提供有关此的早期反馈。

我打开了一个重复的问题,我试图在我的 NextJs 模块中导入/转译基于 CRA 的模块,但不知道如何进行转译(请注意,我想让我的模块作为独立运行)

我还注意到,同样基于 Lerna 的 Babel 在暴露每个模块之前会对其进行转译,但在我看来,最好像@arunoda建议的那样

我想为我的客户端提供一个 babel 配置,并与我所有的解耦模块共享该配置。 如果我想保持在 Next runner 之外独立运行我的模块的能力,这可能不是那么容易

我当前的测试项目在这里: https : @arunoda你在努力吗?

@slorber目前我们专注于 2.0 版本,我们正在微调内容并尽可能查找错误。

我还没有开始做这方面的工作,但我们可以在 2.0.0 之后做到这一点。

好的,所以我会做一个叉子。 我已经在运行 2.0.0 测试版,因为我没有构建一个关键网站,而且我认为 webpack 1.13 没有解决jsnext:main/module字段。

我不是打包专家,但我想我宁愿使用 package.json 的“模块”字段,不是吗? 据我所知,“main”似乎是已经转译的代码。 但是由于 webpack 配置允许包含/排除转译,我不确定它是否相关。 关于我更愿意使用的 3 个字段中的哪一个的任何建议?

@slorber我认为 webpack 只支持main就像 NPM 一样。 你可以用那个。
我们可以检查该文件路径exclude在我们的函数next.conf.js

嗯,根据我在针对 Next 2.x 的实践中所看到的,我看到模块工作(但在运行时由于未转译而失败)而jsnext:main没有工作(据我所知)。 不过应该是支持的

无论如何, jsnext:main或 module 似乎不是这个问题的解决方案,所以对于公司内部的模块,只启用转译可能就足够了

社区尚未就一种方法达成一致,对吗? 例如,我可以开箱即用地使用react-youtube另一个。 我假设有大量模块在发布之前进行转换?

参考: https :

是的,在发布之前始终进行转换是有意义的,因为您不知道模块将被谁/如何使用,并且您不想强制客户端为您的库设置适当的 babel 设置。 这就是Rollup 的建议:发布以不同方式转译的模块,以便捆绑程序可以决定使用哪个。

但是对于公司内部包,转换设置可能在多个项目中是相同的(例如 babel 预设),并且让客户端打包程序转换所有公司依赖项对我来说是有意义的

非常同意@slorber - 如果您正在分解项目并尽可能地隔离事物,这对于内部模块将非常方便。

并且@rauchg / @arunoda支持 RegExp 会非常好,所以你可以有一个条目来捕获所有公司内部模块,使用 NPM org 命名空间:

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

美丽的建议@philcockfield

嘿,也许值得提供一些预设。 在我看来,大多数工具(Lerna/npm 链接...)都依赖于符号链接,所以为什么不使用以下简单的方法:

```javascript
模块.出口 = {
transpileModules: ["符号链接"]
}
````

我越认真地使用next.js ,并围绕它构建了一个丰富的模块库,这个特性就变得越重要。 它正在成为一个真正的 PITA,在我的内部模块中复制 babel 编译步骤。

🚀🤖

我今天正在做这个:)

@philcockfield试试这个: https :

谢谢@arunoda

因此,正如对您的 PR 的评论,如果这不支持符号链接,该功能将受到一些限制,因为它不适用于 npm 链接或 Lerna,但仅适用于未转译的 npm 模块(对吗?我没有看到任何其他用例,除非您在/node_modules内提交模块)

为什么不支持符号链接? 是不是更难支持?

此外,我想在我的应用程序上测试您的分支,但我不确定这样做的最佳方法是什么。 是否有任何已知的程序,以便我们可以轻松地测试分支,并且对测试人员来说不会太痛苦? 我试过一些东西,如:

  • npm install https://github.com/arunoda/next.js.git#add -706 :失败,因为 github 存储库上的下一个 /bin 文件夹为空
  • /node_modules 内的 fork 的 git clone: 不太成功(但这可能是因为我的特定 Lerna 设置)

目前测试分叉的最佳方法是什么?

如果您正在考虑使用next.config.js : module.exports = { webpack: (config ,那么config.module.rules有一些事情,看起来您需要更改其中一项规则,还是添加一项? :

  { 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: [] } } ]

期待更简单的语法建议。

抱歉我的无知我看不出这个问题的解决方案是什么? 我们很想将 es6 导入我们的代码库,我们需要 tree-shaking 。

这个有PR吗?

@andrewmclagan这个问题仍然是开放的,并且有一个相关的PR可能不会满足所有人(比如 LernaJS 用户)

这是什么状态? 有没有其他方法可以让 next 的 webpack 转译从 node_modules 导入的文件?

@slorber我会看一下 PR。 贡献我们的用例。

我面临着类似的问题。 尝试使用get-urls包。 可以用dev找到,但是当我编译它时。 我从 uglify 得到错误

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

请问有什么解决方法吗?

Arunoda 将在这里的某个时间处理它。 他之前做过#749

我很想看到这个功能被实现。 正如@philcockfield 所提到的,构建依赖于 Next.js 转译的模块库是一个常见的场景,并且能够在项目之间共享组件会很棒。

这不仅需要用于摇树。 也适用于像styled-jsx这样的 babel 插件。 因此,如果您有一个使用 babel 插件的模块(如库),最好的解决方案是包含 ES6 源代码并允许您的应用程序从 node_modules 转译它。 当然 next 默认已经包含了styled-jsx

这是我所做的

// 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);

我基本上用自定义函数替换了每个exclude
我不知道我做错了什么,但我无法让它发挥作用。
我需要node_modules/mycomponents的内容也被 Next.js 转译

如果我用空数组完全覆盖所有排除,它甚至不起作用

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

请帮我 :)
谢谢

嘿伙计们 ( @thealjey )jsnext:main驱动的模块。

我没有使用next.js但我希望它有所帮助。

@damianobarbati不,不幸的是它没有
直接配置 webpack 以转译任何内容并不困难,但我正在努力在 Next.js 的上下文中完成这项工作

大家好,有人找到解决办法了吗?

我有一个本地 ES6 链接节点模块,我需要在我的项目中导入,但我无法正确使用 webpack 巫毒!

我确定有更好的方法,但我们在构建时通过 babel 运行所有内容:

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

这是死了吗? 我正在寻找一种转换自定义模块的方法,但似乎仍然不可能。

@mattfelten它在 v5 的路线图上👍

有没有人有一个解决方法的例子?

@timneutkens有这方面的时间表吗? 意识到这通常是一个不可能的问题,但我们正在努力确定我们目前在工作中的筹码量,这对我们来说是一个非常大的障碍! :)

解决方法建议也有效。

@thealjey意识到这是一条旧评论,但您的解决方案可能不起作用,因为还指定了include需要覆盖。

更新:研究了这个策略,但考虑到 next.js 内部配置中不同模块目录的所有不同加载器,它并不明智。 这将需要是一流的。

@chrisui我的(临时)解决方案是使用babel-plugin-module-resolver ,配置如下 - "plugins": [["module-resolver", {"root": ["./"]}]]
这绝不是一个完美的解决方案,但是,由于其他一切都失败了,它现在有效
多亏了我不需要每次导入都写一堆../
对于某些人来说,这实际上可能是更好的解决方案,尽管它肯定无助于可重用性

@thealjey你能举个例子吗?
我有一个项目设置,我尝试此操作无济于事...
https://github.com/jamesgorrie/nappy

我很乐意尝试获得 PR,因为这会让我们的生活变得更加轻松,但有一些问题,例如: next.js是否应该支持某些模块的转译,或者这应该由转译器决定,但是next.js更严格地遵循模块解析。 作为next.js新手,不确定该问谁或从哪里开始。

它在 v5 的路线图上👍

@timneutkens 是否已将其纳入 v5?

想知道。

只要看看它合并的地方。 这是8天前合并的。 5.0.0 于 2 天前发布。 从金丝雀分支合并到...

有没有人有关于如何实施的例子? 如上所述,它应该像这样工作吗?

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

或者看起来不一样?

我糊涂了。 @timneutkens上述链接指向仍处于打开状态的 PR。 这还没有在 v5 中合并吗?

编辑:没关系,这只是一个突出例子的公关。

这是一个示例,您可以在不合并的情况下使用该示例。 transpileModules是我们稍后会解决的问题。

作为一般经验法则:当一个问题处于开放状态时,它不会被发布。

@brianyingling我已经把这个例子变成了一个临时解决方案的插件(仅限 v5)。
目前它正在为我们工作,直到更强大的官方解决方案到位。

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

我很想看到应用程序代码库中单个模块的示例。

例如,我有一个同时使用服务器端和客户端的模块。 我无法通过将模块分解为自己的单独模块并yarn link对其进行分解,或者通过破解 webpack 规则来使上述任何示例工作。

这是一个简单的重现: https :

// 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告诉我这是因为我在共享模块中使用了async/await 。 我想我的解决方案可能是删除 async/await 并将所有内容更改为.then()样式的回调。

好的,我找到了一个适合我的修复程序。

首先,我根据https://github.com/zeit/next.js/issues/3018#issuecomment -380879576 在我的next.config.js配置中添加了config.resolve.symlinks = false设置

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

然后我将我的共享库——一个使用 CommonJS 导出和async / await关键字的.js文件——放在名为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": { ... }
}

最后,当有人在主应用程序中执行yarn install ,我添加了一个postinstall脚本将它们链接在一起:

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

现在我的 Mocha 测试在服务器端通过了,我的自定义 Koa 服务器启动正常,并且我的 NextJS 页面中不再有疯狂的Cannot assign to read only property 'exports' of object '#<Object>'

升级到 NextJs 5.1.0 时我遇到了同样的问题。 next 中的一两个节点模块没有转译胖箭头函数并在 IE11 中抛出错误。 我之前已经设置了单独的 polyfill,最后我选择在我的next.config.js使用babel-polyfill定位这些模块文件:

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 })
  }
}

希望这可以帮助某人。

ESM就像一种魅力。

使用index.js的自定义 Next.js 服务器,我可以运行此命令来启动服务器并且 esm 完美启动,解析 Lerna 符号链接项目包中的 ES 模块。

node -r esm index.js

@curran很酷,它可以代替 babel-node 吗?

@curran我会避免在生产中这样做

@blackbing我不知道。

@thealjey为什么会这样?

如果有人正在寻找快速简便的解决方案,这就是我所做的。 我创建了一个子目录shared/ ,其中包含我们希望通过独立 Node 脚本在后端和通过 NextJS 在客户端上运行的任何代码。 它有自己的package.json并将其名称声明为@myproject/shared

然后,在主(父)项目中,我向package.json添加了一个安装后脚本,如下所示: cd shared && yarn -s unlink >/dev/null 2>&1 ; yarn -s link && yarn -s && yarn link @myproject/shared — 然后至少运行yarn一次,并将导入更改为import { whatever } from '@myproject/shared/somefile'

这样,共享代码无需任何疯狂的转译步骤即可工作,而且每次进行更新时您都不必重新运行yarn / npm因为yarn link使符号链接。

对于那些使用 TypeScript 的人, @weco/next-plugin-transpile-modules不应该工作。 我创建了一个 fork 来处理 Next 的withTypescripthttps :

不过,当我们也需要在 TypeScript 中使用服务器端代码时,我仍然需要弄清楚如何正确地做事。

有这方面的消息吗?

我的另一个,在以下要点中。 它处理 TypeScript,以及@scope特定包,而不是所有包。 https://gist.github.com/trusktr/44400d0d016c506629b4f914799dc9cd

我只是把一个简单的工作例子放在一起,使用esmlerna

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

/cc @jdalton

个人使用以下next.config.js

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

    return config
  }
}

它包含node_modules ,这是我实现 IE 11 兼容性所需要的...

我也很欣赏这个解决方案,努力将非转译的 npm 包添加到我的项目中。 现在不得不将它们下载到供应商/ :(
真烦人

@bel0v我相信你应该已经能够用next-plugin-transpile-modules来完成这个。 这个问题应该很可能被关闭。 抄送/ @timneutkens

我仍然想研究替代解决方案。

最近 Jamie 写了一篇关于编译 node_modules 问题的非常详细的帖子: https ://twitter.com/jamiebuilds/status/1080840492525350912

我阅读了 Jamie 的帖子,但我也想分享 Henry Zhu 和 Babel 对这种情况和解决方案的看法。
https://babeljs.io/blog/2018/06/26/on-sumption-and-publishing-es2015+-packages

(不反对蒂姆,只是想我会分享,许多优点和缺点。可能有助于蒂姆研究替代解决方案)

是的,过去半年我们一直在和很多人讨论这个问题,包括亨利😄

尽管担心转译 node_modules,但希望在 monorepo 中转译您自己的包是一个非常普遍的要求,这些问题并不适用

@dcalhoun我试过了,但不幸的是我仍然遇到意外的令牌错误。 此插件有一个未解决的 Next 7 问题,可能与此相关

@bel0v

您应该阅读常见问题解答;) 这个问题有一个解决方案: https :

我一直在多个项目中使用这个插件,它很好地完成了工作。 Next 7 问题很奇怪,我不确定这是来自 Next 还是 Babel,我还是在这里打开了一个问题: https :

@martpie是的,我相信我已经尝试过了..无论如何我会再试一次

@martpie我们已经开始使用 next7 和一致的 babel.config.js 和 yarn 工作区,我可能会看看我是否可以设置一个简单的例子。

我在这里分叉了基本示例
https://github.com/bel0v/learnnextjs-demo
在其中,我安装了一个未转译的依赖项(有线元素),得到了一个构建错误Unhandled Rejection (SyntaxError): Unexpected token {并尝试以建议的方式修复它。
我在想也许我需要一些额外的 babel 插件才能让它工作..🤔

@bel0v再次出现在常见问题解答中,解释了为什么 Lerna 设置不起作用(TL,DR;您可能使用的是错误的)

@martpie啊,明白了! 没有意识到第三方包是用 Lerna 设置的。 谢谢

似乎https://twitter.com/jamiebuilds已暂停,因此无法再阅读那里的线程。 #3018 关于此问题已关闭,所以我想知道正在考虑的替代方法是什么?
对于这些用例 atm,这些是否代表了 next.js 的最新技术/最佳实践?
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

所以,如果你和我一样,正在开发一个必须支持 IE11 的项目,你真的必须转译node_modules/所有代码。 在 Next.js 7.x 中,我使用了以下设置,效果很好。

不幸的是,它在 Next.js 8.x 中停止工作,错误是模块无法导入其他模块,因为它们没有默认导出。 然后我想出了 Next.js 8.x 的以下配置,它只用@babel/preset-env转译node_modules/的代码,没有其他插件。

这是通过在package.json设置我的browserlist属性来组合的:

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

下一个 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
  },
}

不幸的是,我还没有想出如何在这个设置中使用@babel/plugin-transform-runtime ,所以它可能会在代码中吐出不少助手😞 希望 gzip 能解决它😆 😅


我认为如果 Next.js 可以给我们一个选项来正确地转换node_modules/以与您拥有的任何browserlist一起工作,那将会很棒。 似乎任何拥有企业用户的大型网站都依赖于此来正确支持旧浏览器。

作为next-transpile-modules的维护者(基于@jamesgorrie 的出色工作),我很高兴在这里帮助任何遇到此问题的人。

我已经使用这个插件从事专业项目一年多了,到目前为止它运行得很好。

Next.js 的原生支持当然很棒,我很乐意帮助将此功能集成到next包中。 我知道蒂姆有一些他想尝试的想法,但无论如何。

干杯!

@martpie我很快查看了您的项目,但没有找到一种快速转换 _all_ 模块的方法,这可能吗? ☺️

另外,我看到您正在选择options.defaultLoaders.babel并将其用作 babel 加载器。 在使用 Next.js 8.x 执行此操作时,我遇到了一些模块在此之后无法正确识别为 CJS 模块的问题,然后其他库将无法导入它们,例如:

./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'.

这就是为什么我转而为node_modules/提供自定义 babel 配置,它只使用preset-env转换代码,并跳过 Next.js 特定的转换。 您如何看待这种方法?

干杯🍻

@LinusU也许试试transpileModules: ['(.*?)']并告诉我它是否有效?

但它可能在未来的主要版本中不起作用,所以要小心。

更一般地说,我不建议(阅读“非常不鼓励”)转译整个node_modules文件夹,编译将花费很长时间,并且包应该提供与 ES3 兼容的代码(因此与 IE11 兼容)。

只转译你需要的模块! (如lodash-es ,本地模块等...)

包应该提供兼容 ES3 的代码(因此兼容 IE11)。

这不是我所看到的现实,我实际上并不同意。 模块作者永远不会确切知道我的目标浏览器,如果他们发布旧代码,他们可能会惩罚以现代浏览器为目标的用户。

编译需要很长时间

对我来说启动时有点慢,但在那之后,它似乎被缓存了,当对特定页面进行更改时,我看到近乎即时的重新加载。

只转译你需要的模块!

这将要求我确切地知道哪些包与 IE11 兼容,哪些不兼容,以及在任何依赖项(甚至是瞬态依赖项)发生变化时随时更新此信息。 我不明白这是多么现实🤔

重要的是 package.json module中提供的 ESM 入口点通常是ES5和 ES6 导入/导出,用于摇树。 因此,除非另有说明,否则这是打包器 (Webpack) 而不是转译器 (Babel) 的工作。 许多维护良好的软件包已经具有 ESM 入口点,例如 OP 提到的 Redux 的redux/es

如果您正在考虑使用next.config.js : module.exports = { webpack: (config ,那么config.module.rules有一些事情,看起来您需要更改其中一项规则,还是添加一项? :

  { 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: [] } } ]

期待更简单的语法建议。

对我来说很好用

{
    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']
    }
},

我在使用 Lerna mono repo 时遇到了这个问题,并且正在摸索原因是什么。 由于错误来自 webpack,除了缺少加载程序之外,它没有提供很好的细节,这没有帮助。 谢天谢地,我发现了这个 github 问题!

我将把我的解决方案留在这里,供其他搜索此问题的人使用,并且也在使用 Lerna:

为共享包创建一个预发布脚本,将源代码转换为 dist 目录,并在链接时告诉 Lerna 指向 dist 目录:

// 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"
}

现在,当您lerna bootstrap它会运行预发布脚本并转译源代码,以便 Next 可以使用它。

如果您使用lerna您可以制作符号链接以使用next-transpile-modules 进行转换。 如何使用带有lerna的包写在文档的底部。

对于在 NextJs 应用程序之间搜索共享代码的任何人,我只想报告@LinusU的解决方案在尝试在我的 Mono 存储库中的多个 NextJs 应用程序之间共享 React 组件和实用程序时对我有用:

// 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
        })
        }
    }
}

在撰写本文时,我正在使用最新版本的 NextJs。

@Lwdthe1我试过你的代码,最初得到这个错误:

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

做了一些调整,最后得到了这个:

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
  }
};

但是遇到了另一个错误:

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)
....

这似乎在 #2850 和 #883 之前遇到过。

所以似乎唯一的解决方案是: https :

据我所知,很快就会有 RFC 提出 Next.js 计划如何解决这个问题,但是如果有人现在需要修复它,我已经在 npm 上发布了我的解决方案https://github.com/ zeit/next.js/pull/10098您可以通过将以下内容放入 package.json 来使用它:

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

并遵循next.config.js:

  babelIncludeRegexes: [/turf/],

(在我的情况下,我需要使用 babel 预编译所有 turf 文件)

这个问题有什么进展吗?

我使用 next.js 9.2.0,但babelIncludeRegexes选项不起作用

这个问题有什么进展吗?

next-transpile-modules正是为了解决这个问题,你试过了吗?

@martpie

已经解决了我的问题 .babelrc 文件编辑。 我参考了这个问题

谢谢

@martpie我正在使用next-transpile-modules但是,我在尝试构建应用程序时仍然面临以下错误。 我正在使用带有共享代码库的 monorepo。 尝试从像“@myapp/shared/components/componentname.js”这样的共享访问组件。 我正在使用 nextjs 9.x 和自定义next.config.js

错误
`
模块解析失败:意外令牌 (12:4)
您可能需要一个合适的加载器来处理此文件类型,目前没有配置加载器来处理此文件。 见 https://webpack.js.org/concepts#loaders
| const Spinner = props => {
| const renderDefaultSpinner = (spinnerClass, { ...others }) => (
>


| );
|

发生构建错误
错误:> 由于 webpack 错误,构建失败
`

下一个.config.js
const withTM = require('next-transpile-modules')(['<strong i="26">@myapp</strong>']); module.exports = withPlugins([withTM, withBundleAnalyzer], { ... }

请帮助我在这里做错了什么。

@raghav1086你能在 repo 上打开一个问题吗? ;) 它会避免这里的人们的噪音。

+1

我有一个src/为我的项目目录和lib/的启动器框架,出口一些常见的utils的/包装,我整个重用了几个不同的应用程序nextjs(我的出发点)

当我启动开发服务器时,lib 不会被注意到。 lib/ 中的任何组件都不会通过加载程序并给出错误

我使用了@Lwdthe1解决方案的变体(https://github.com/zeit/next.js/issues/706#issuecomment-569041997)来修复我上面评论中的 src 和 lib 问题。 除了使用config.resolve.modules而不是循环遍历aliasPathsToResolve数组之外,基本相同。

  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],
    });

现在 lerna、nextjs 和 babel 的工作解决方案是什么?

我试图避免在导入之前预先编译我的库,而且我在这里的每个解决方案都遇到了麻烦。 这是我无法工作的内容:

  • next-transpile-modules
  • 重置预设环境设置。
  • 分别更新next-babel-loader includeexclude规则以通过/失败。

@mikestopcontinues next-transpile-modules使用 TypeScript 为我开箱即用。

@calebmpeterson@martpie (我看到你了!👀)。 转回插件,问题好像是没有办法引用子模块。 例如,模式 '@mono/components' 将不支持导入 '@mono/components/Div' 或其他任何内容。 并且指定 '@mono/components/Div' 作为模式也不起作用......并不是说我想为每个共享组件都这样做。 我还尝试对正则表达式生成进行逆向工程以创建匹配模式,虽然输出正则表达式有效,但在幕后发生的其他事情并非如此。

理想情况下,我只想指定“@mono”来处理所有事情,并让我的 package.json 成为我的每个应用程序所依赖的唯一真实来源。 同样,为了能够访问子模块,我想避免维护在我的每个库中导入/导出所有内容的索引文件。

回过头来,我相信如果有某种方法可以通过next-babel-loader传递rootMode: 'upward' next-babel-loader ,从而使 babel 可以处理转译逻辑,则可以完全解决当前的问题。 也许这会引发其他与 Next 相关的问题,但问题的根源似乎是 Next 与 webpack 和 babel 纠缠在一起的非典型方式。 当然,有办法将babel-loader与 Next 的附加逻辑分开吗?

只是next-transpile-modules前面的更新。 我误诊了这个错误。 如果您需要自定义.babelrc配置,则使用此方法(索引或子模块)无法导入。 自定义设置不会应用于所需的代码。 这又是一个rootMode: 'upward'问题。

@mikestopcontinues您需要将babel.config.js (全局配置)与next-transpile-modules ,而不是.babelrc (本地配置),常见问题解答中对此进行了解释;)

@martpie你不知道我有多尴尬。 在过去的几周里,我不得不把那句话读了十几遍,而且从来没有费心去点击这个问题。 那完全有效。 谢谢!

next-transpile-modules 为我打破了 React。 它现在抛出我使用无效钩子,而我转译了三个示例模块

有人可以重申什么是使转译工作的最佳配置。 我不明白我必须在 babel.config.js 中写什么

@masbaehr在大多数情况下只是将next-transpile-modules到您的 next.config 设置中

唯一的问题是next-transpile-modules不支持 Yarn 2 pnp。

此页面是否有帮助?
0 / 5 - 0 等级