@shrinktofit 您好,想了解一下在解决了您说的json引入问题之后,axios是不是就可以正常引入了呀,以及进一步的,其他包是不是也可以正常引入了呀?
如我所说,这是一个会影响开发生态的问题,而且看到论坛里经常有人在问类似重复的问题。谢谢!
(现在cocos是用什么做ts编译的呀?webpack、rollup、esbuild或者是团队自己拿tsc手撸?)我也很愿意帮你们团队以及大家多做一些相关的改进尝试,一起来解决这个问题,毕竟这个对我来说是刚需。
@shrinktofit 您好,想了解一下在解决了您说的json引入问题之后,axios是不是就可以正常引入了呀,以及进一步的,其他包是不是也可以正常引入了呀?
如我所说,这是一个会影响开发生态的问题,而且看到论坛里经常有人在问类似重复的问题。谢谢!
(现在cocos是用什么做ts编译的呀?webpack、rollup、esbuild或者是团队自己拿tsc手撸?)我也很愿意帮你们团队以及大家多做一些相关的改进尝试,一起来解决这个问题,毕竟这个对我来说是刚需。
您好,想了解一下在解决了您说的json引入问题之后,axios是不是就可以正常引入了呀
我们会再确认一下。
以及进一步的,其他包是不是也可以正常引入了呀
不是,其它有些包就是没法用。它们依赖了 node 内置模块比如 fs、http、os 等,Creator 是没有的。比如,你设想一下,你可以构建到微信、web、支付宝、快游戏,那么这几个平台哪里有 fs、http 这种模块呢?
现在cocos是用什么做ts编译的呀
在内部,Creator 使用 babel 进行编译。在非构建阶段,使用自研的工具进行“打包”。在构建阶段,使用 rollup 进行打包、tree shaking。
我们后面会继续进行 npm 包使用的优化,尽量做到“常见打包工具打包之后能用在浏览器上的库都能用在 Creator 上”
好的,我再补充一下我的问题哈,用在node环境的那些,比如fs,path这些无法引入这一点我是理解的。我是全栈,两种环境都会接触,所以理解你所说的,我也不会用到这样的包,非常感谢你的解释!
只需要支持那些纯前端包/有前端版本的包就可以啦。axios之所以特殊是因为它同时可以用在前端和后端,用此它本身会尝试导入nodejs环境的包,就会导致报错。大概只需要让它知道自己是在浏览器环境而非node环境就可以了,大概?
对于最后大佬所说的,未来会继续对npm包引入这一点,允我表示对cocos团队的感谢,因为这一点很重要!
听说最近大佬最近在忙动画图,所以npm这里如果有什么需要测试或者讨论的,可以直接找我!
OK,欢迎继续反馈,我们正需要你这样的深度用户
好的呢,另外想一下现在负责npm这一块的同学是哪位呀?
npm 的问题反馈给我好了
@_PP 您好,正好有另一个npm相关的问题想问一下:
我有一个自己构建的 npm 包,因为是放在私有源的,就不提供复现代码了,我尽量描述一下情况:
假设有一个叫api
包,其中是这样的:
// index.ts
export const apiBase = ...
我使用 npm 在cocos 项目中安装了这个包,并且将tsconfig.json
中的allowSyntheticDefaultImports
设为true
。接下来做如下测试:
import api from "api";
console.log({ api });
控制台正常,接下来将代码换成:
import * as api from "api";
console.log({ api });
将发现 default 重新出现了。进一步的,如果使用 deconstruct 语法进行引入:
import { apiBase } from "api";
console.log({ apiBase });
会导致循环引用并无法获得导出的对象:
进一步发现,这样引入同样是引入到了 default 对象中,即:
import { default as _default } from "api";
console.log({ _default });
同样的问题出现在另一篇帖子里:
请问npm包该如何引入cocos中使用? - Creator 3.x - Cocos中文社区
我也碰到这个问题。
大家可以一起 push 官方 如果有类似的问题或者解决办法或者思路可以跟帖~
3.5.2也出现,非常感谢老哥的鼎力支持,希望官方看下我们俩的2个帖子,找到修复方式
我猜测你这里 npm 包源码是 esm 格式的 ts 文件,是否还会通过 tsc 编译成 CommonJS 的 js 文件呢?如果是这样的话,应该会编译成
// index.js
module.exports.apiBase = ...
而编辑器的 build tool 只会处理 npm 包实际导出的 js 文件,即 index.js
这个 index.js 会被编辑器的 build tool 做多一次包装,包装成类似这样的模块
export const __cjsMetaURL = 'pack:///chunks/...';
export const default = {
apiBase: ...,
}; // 注意:这个 default 对象的所有属性是运行时动态赋值的,因为 CommonJS 并不能被很好地支持静态解析
// 所以目前也没有办法解析生成 `export const apiBase = ...` 这样的导出语句。
所以后面的一系列输出应该就可以理解了,
import api from "api"; // 其实就是 `import { default as api } from 'api'`, api 就是 default 对象
import * as api from "api"; // 输出就是 index.js 导出的所有对象,包括 __cjsMetaURL 和 default
import { apiBase } from "api"; // 就有问题了,因为 index.js 没有导出 apiBase 对象, 就报错了
// 这里可能报错信息有一些误导性,应该不是循环引用导致的,这个后续我们优化一下
import { default as _default } from "api"; // 同上 `import api from "api";`
所以可以被解决吗?因为npm上其他包也出现了类似的问题,我知道这样说有点委屈你们,但是无论原理上是什么样子,无法正常引入就可以算是cocos的bug 因为一个npm包没办法用正常的方式使用了。
我的包是用比较规范的方式构建的,cjs、esm格式都有。用的是字节的modernjs框架直接生成的包。如果有任何问题,需要我的都可以问我,我会尽量提供细节。
问一下目前 npm 包是否配置了条件导出呢,不太确定是不是我们的 build tool 对条件导出的解析有问题,如果解析到 cjs 的入口,可能就出错了
可以贴一下 package.json 下 exports 字段的相关信息吗
这样,我之前提到的另一个帖子中的 typedjson这个包也是同样的问题,如果方便的话可以测试一下。我一会儿也再找一些类似的例子看看。 package的信息我稍等贴出来
package.json相关内容:
"jsnext:source": "./src/index.ts",
"types": "./dist/types/index.d.ts",
"main": "./dist/js/node/index.js",
"module": "./dist/js/treeshaking/index.js",
"jsnext:modern": "./dist/js/modern/index.js",
构建结果:
modern 里面:
export const apiBase = ...
node 里面:
exports.apiBase = apiBase;
treeshaking 里面:
export var apiBase = ...
了解了,我这边也做了一些测试,node 上确实是能够支持 ESM 模块以具名导入的方式导入 CJS 模块的,但是支持也是相对有限,
例如下边例子中的变量 d
// main.mjs
import { a, b, c, d } from './test.cjs';
console.log(a, b, c, d)
setTimeout(() => {
console.log(a, b, c, d) // 这里的 d 依旧是 undefined,是不支持 live binding 的
}, 2000)
// test.cjs
module.exports.a = 'a';
module.exports['b'] = 'b';
Object.defineProperty(module.exports, 'c', {
value: 'c'
});
setTimeout(() => {
console.log('dynamic assign d');
module.exports['d'] = 'd';
}, 1000)
下边这种情况也不支持
// main.mjs
import { test } from './test.cjs';
console.log(test)
// test.cjs
module.exports['te' + 'st'] = 'test';
我们可以排期把前边 a b c 的情况支持掉
好的 非常感谢
以及请问cocos对多种导入模式的优先级是怎样的?
应该是以 conditional exports 为最高优先级,其次是 main 作为 legacy 方案
conditional exports 不支持 node 导出,因为 node 环境并不能实现跨平台
你的还没能使用吗?心痛1999