搞不懂他们的优先级标准…我认为这个比新增视觉效果要重要。视觉效果不行可以先凑活着发一版难看的,等有了再更新游戏版本,但是 npm 包加不进来,连游戏都没法开发了。
感谢分享,很不错的方案
多谢你的方案,你比官方更加 “官方”
谢谢,很高的评价!
发现帖子第一次被置顶了,开心hhh
那就顺便把最近其他的一些经验也写在这里吧
引入入口的优先级
首先是对于某个包,假如有多个引入入口(main
, module
, exports
等)如何看 Cocos 引入了其哪个入口文件:
首先 cocos 会去寻找类似这样的东西(某个包的package.json中):
{
"exports": {
"browser": {
"import": "xxx",
"require": "xxx",
"default": "xxx"
}
}
}
如果你是 import 引入的,那么对应入口就是 exports.browser.import,如果是 require 引入的(实际上不支持这种引入方式,不要使用),对应入口就是 exports.browser.require ,如果没有就会使用 exports.browser.default。
如果 exports.browser 是一个字符串,相等于是 exports.browser.default。
如果 exports.browser 也不存在,就会寻找 exports.default,如果 exports 是字符串也就相当于exports.default。exports 还支持不同路径不同入口等嵌套定义,但大同小异,具体的看文档:
如果没有 exports ,则 cocos 会去找 “main”。
CJS 包的引入,即 npm 大多数包的引入方式
不完全严谨的理解什么是 cjs 格式的包:用require引入、用 exports.xxx = … 导出的就是 cjs
对应的 esm 格式的包:用 import 引入、用 export const xxx = … 导出
那么打开大多数的包看一看入口文件,基本都是 cjs 的。而 cocos 对 cjs 的包引入存在缺陷。例如,我们假设有某个包 abc,其 package.json 包含如下内容:
"main": "./dist/1.js"
而 1.js 中:
console.log('Import from main');
console.log({ exports });
若干 Object.defineProperty(exports, ...);
若干 exports.xxx = ...;
console.log({ exports });
尝试在某个 Cocos 脚本中引入:
import { a, default as default_ } from 'abc';
console.log({ a });
console.log({ default: default_ });
则会在控制台打出:
Import from main
{ exports: {} }
{ exports: { 若干导出对象 } }
{ a: undefined }
{ default: { 若干导出对象 } }
继续之前帖子(想请教一下 Creator 3 对npm包的引入原理)的内容,可知在引入 node.js 这个文件时 exports 是正常的,但是真正拿出来之后,这个 exports 中的内容到了 exports.default 中,导致没办法正确导入所有的 CJS 格式的 npm 包。
所以我猜测引擎在进行 systemjs 打包的时候可能做了 exports = { default: exports }
这样的事情;只要把这个多套一层 default 的动作拿掉就可以了。不是很理解当时为什么要这样做。
另外,一般 webpack 等打包工具会将 export default xxx
打包成 exports.default
,即 exports.default 是为默认导出预留的。但这并不代表 import abc from 'abc';
再 abc.a
就完全没问题了,实现这一点需要 export default { a: ... }
,和 export const a = ...
是不同的。二者可以指向不同的东西。
综上,我于是采用了一楼提出的方案。
Cocos 目前(3.6.2) 仍不能和 pnpm 合用
另外还发现一个问题,cocos 无法和 pnpm 一起工作。我大概介绍一下 pnpm 的工作原理。其会在 node_modules 下创建一个 .pnpm 文件夹,里面大概是这样一些文件夹(实际上是硬链接,链接到 pnpm 的全局缓存):
registry.npmmirror.com+@rollup+plugin-json@4.1.0_rollup@2.79.1
registry.npmmirror.com+async@3.2.4
registry.npmmirror.com+axios@0.21.4
registry.npmmirror.com+axios@0.24.0
而在 node_modules 中的包,假如是 axios,就会软链接到 .pnpm/registry.npmmirror.com+axios@0.24.0
。
但是如果在 cocos 中使用 pnpm 做了包管理,就会出错。例如 axios 引入了 http-form 这个包,cocos 就没有办法在 node_modules 下找到这个包(报错无法在 xxxx.js 路径下找到模块'http-form'
),因为现在没有显式安装 http-form ,http-form 只被 axios 依赖,所以并不在 node_modules 中,而是在 .pnpm 中。
我不太清楚其他打包工具是怎么解决这个问题的,Cocos 后面可以参考一下其他打包工具的寻包方式,来兼容 pnpm,而现在姑且推荐开发者使用 npm 进行包管理。
点个赞给你,真的很不错
赞赞楼主,希望coco提升易用性。不要总提升画面效果了。小游戏用不上,重度项目更看底层工具。
好文,这个方法也不行了,import { get } from “…/…/node_modules/axios/dist/esm/axios.min.js”;也变成未导出了
这些本来是应该引擎做的…
想想我以前的回复(帖子找不到了),说想要无缝、正常使用npm包,但不包含某些原生无效的包
引擎开发者就回复说不支持fs等特属于某些平台的包,
大家都知道不能用,我想要的只是nodejs能正常导入使用的包(不包含原生不支持代码),
在creator能用同样的代码导入使用就行,可是官方却来了一套自己的导入方法,最开始其他人导入失败还要一个一个问这个包怎么正常导入,实在是忍不住吐槽
甚至现在还把自己的导入方法放在文档里…而不是想着解决问题,就突出一个特立独行
在我看来就是自己抛弃npm优势,只剩下一个性能底下的js
同样被导包折磨过,这一点很难受,论坛里面也经常看到问这一类的问题。其中 can i use npm in cocos 里面只有寥寥几个包,整个npm生态那么大,像玩具一样?能不能让开发者知道一个包的正确导入方式,不能用的话告知原因。
比如搞个编辑器插件,可以自动扫项目目录下的npm包,告知这个信息。(如果包的导入规则,即使不一样,但就像cocos文档说的那样明确,就能静态分析出来)
Creator 就是用的 node ESM 的那一套,如果:
-
你用的包不包含 node 内置模块;
-
你能直接能用
node xxxx.[m]js
去执行。
但在 Creator 里面引用不了,那就是 Creator 的问题。
Creator 现在相比 Node 少了一个功能就是 Modules: ECMAScript modules | Node.js v20.2.0 Documentation (nodejs.org) 里面的:
For better compatibility with existing usage in the JS ecosystem…
这个导致有些包得这么用 import buffer from 'buffer'; new buffer.Buffer()
。
这个有计划做。
大家都知道不能用,我想要的只是nodejs能正常导入使用的包(不包含原生不支持代码),
在creator能用同样的代码导入使用就行
开发者在 Creator 里遇到的有些问题,在 Node 里面执行也会报错,比如:
这个帖子 里面反馈 helper/TimerHelper.ts 为起点找不到模块 “dayjs/plugin/utc”
。
那么也可以在 Node 里试一下:node js (forked) - CodeSandbox
Node 也有这个报错:
cocos用npm太折磨人
我觉得这引擎再这样搞下去,要完蛋的,一堆问题,还在埋头加新的乱七八糟的效果,功能.
基本的都没夯实.
直接用 protobufjs 实验,tsconfig 一致,package.json 的 module 都为空,但是 creator 导入失败
tsconfig 配置
{
/* Add your custom configuration here. */
"compilerOptions": {
"target": "es6",
"lib": ["es2015", "es2017", "ES2020", "ES2022", "dom"],
"module": "commonjs",
"sourceMap": true,
"noEmit": true,
"strict": true,
"noImplicitAny": false,
"downlevelIteration": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
}
}
nodejs
creator 3.3.2
creator 3.6.3
Cocos官方要不要搞一个自己的包管理器,能支持脚本组件、Prefab等资源,这生态岂不是起飞么
扩展管理器之后就会是这样的
棒,我现在只是使用npm实现了一些简单的逻辑就已经感觉很好用了
一定得有私域部署的能力