You are loading the ES modules build of React Router on a page that is already running the CommonJS build...

2022-03-23 15:19:34 +08:00
 yazoox

项目太大没有办法分享出来。

最新新做了一个包,ui-components ,把 app 里面的一些共用的 ui 组件都放到这个包里。本来还好的,但是昨天,把一个文件 A (引用了 react-router-dom )的放到了 ui-components 包里,结果,在跑 app 的 unit test 的时候,就报这个错了。unit test 是用的 jest 。

但这个文件 A 对应的组件,是肯定要放到 ui-component 里面的。这个 A 组件,也是需要用到 react-router-dom 里面的组件,比如 Link.

那现在怎么办?是因为 jest 事先加载了一个 cjs 版本的 react-router-dom ,然后在调用到 A 的时候,又使用了一个 esm 版本的么?

可是,我尝试写了一个很简单的 test case ,引用 ui-component 里面一个纯组件(没有引入 react-router-dom ),运行,还是报这个错。

google 了一下,貌似很罕见,寥寥几条相关内容,看完,还是不是所云。

有没有什么想法或者头绪?谢谢!

1816 次点击
所在节点    React
8 条回复
duan602728596
2022-03-23 15:36:38 +08:00
报错原因都写了啊,你在 commonjs 环境中引入了 ESM 的包,所以报错啊。
然后像 react 、react-dom 、react-router-dom 这种包就不要放到 dependencies 里了,放 peerDependencies 里吧。
yyfearth
2022-03-23 15:49:41 +08:00
做 lib 的时候 这些东西要尽量放到 peerDeps 然后如果要打包 需要 external

另外就是 jest 的问题 主要是 jest 是用 nodejs 跑的 所以引入一些 esm 的包就会出现问题 可能需要转译一下才能跑
yazoox
2022-03-23 16:49:19 +08:00
@duan602728596 thx


@yyfearth 我们的 nodejs 已经是 14+ 版本了,应该可以支持 esm 了啊。
你说的转译是什么意思?是类似于 babel 么?不清楚怎么操作,有没有可以用于搜索的关键字或者文档?
谢谢
qqqqqcy
2022-03-23 16:58:03 +08:00
可以统一 jest 执行时,第三方依赖的模块规范选择。自定义一个 jest resolver

// build/resolver.js

const fs = require('fs')
const path = require('path')
const resolve = require('resolve')

function mapModuleFieldToMain (pkg, pkgDir) {
const moduleSrcPath = pkg.module
const isModuleFieldAvailable = moduleSrcPath &&
fs.existsSync(path.resolve(pkgDir, moduleSrcPath))

if (isModuleFieldAvailable) {
return Object.assign({ }, pkg, { main: moduleSrcPath })
}
return pkg
}

function defaultResolver (pathStr, options) {
return resolve.sync(pathStr, {
basedir: options.basedir,
extensions: options.extensions,
moduleDirectory: options.moduleDirectory,
paths: options.paths,
packageFilter: mapModuleFieldToMain
})
}

module.exports = defaultResolver

--------------------

// jest.config.js

// A path to a custom resolver
// 自定义一个 resolver ,优先读取依赖的 esm 入口。和 rollup 对齐
resolver: '<rootDir>/build/resolver.js'


---------

我之前先过一个 SDK 的脚手架工具,生成的 SDK 模板代码里用到了类似的逻辑 https://github.com/draftbookJs/cli 。不知道你碰到的是不是这种问题
yyfearth
2022-03-24 02:01:49 +08:00
@yazoox 转译就是指的 babel(或者 tsc) 因为 jest 是直接在 node 上面跑 所以一般情况下需要用 babel/tsc
但是 babel/tsc 一般只管 src 一般会把 node_modules 排除在外 这样就算用 node 14+ 也可能会碰到加载 esm 导致无法运行的问题

@qqqqqcy cjs 和 esm 的加载方式不一样 不用 babel 的话 node 14+ 自己能够处理好 esm 入口吗?
qqqqqcy
2022-03-24 11:22:27 +08:00
@yyfearth 我用的 preset: 'ts-jest/presets/js-with-ts-esm'。可以处理 ts 和 esm
yyfearth
2022-03-24 11:53:50 +08:00
@qqqqqcy 估计是 ts-jest 自动处理了
ts-jest 有 tsc 作为转译工具 和 babel 差不多
changehow
2022-08-11 18:17:13 +08:00
我也在单元测试中遇到这个问题了= - =

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/842363

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX