Cocos Creator 3.0 已全面支持 TypeScript 作为默认语言,不论是引擎提供的功能还是用户提供的脚本,所有代码都以模块的形式组织。
模块格式支持并推荐使用 ECMAScript(以下简称 ESM),也就是项目资源目录下以 .ts
作为后缀的文件。例如 assets/scripts/foo.ts。
但这不代表不支持 JavaScript 语言,毕竟 TypeScript 是 JavaScript 的超集并且 TypeScript 紧紧依赖 JavaScript。
因此,针对外部模块(例如:npm 模块)的使用,Cocos Creator 3.0 也在某种限度上支持了 CommonJS 模块格式(以下简称 CJS 模块格式)。
因此,清晰的了解 Cocos Creator 对模块格式的支持,可以更加方便地玩转 npm 里的海量资源。
01
模块
模块规范
目前主流的模块规范分别有:
UMD
CommonJS
ES6 module
在这里重点说一下与本文有关的 CommonJS 和 ES6 module。
CommonJS 模块规范
Node.js 环境所使用的模块系统就是基于 CommonJS 规范实现的,现在所说的 CommonJS 规范也大多是指 Node.js 的模块系统。
模块导出
使用的关键字 exports
和 module.exports
。
// foo.js
// 单独导出
module.exports.a = 10;
module.exports.b = function(){};
exports.c = 20;
// 整体导出
module.exports = { a: 10, b: funtion(){}, c: 20 };
// exports 与 module.exports都指向同一个地址,但是最终返回的是 module.exports
exports.a = 10;
module.exports = { b: function(){} };
// exports 不能单独导出,否则会失去和 module.exports 的关联性
exports = { a: 10, b: funtion(){}, c: 20 };
模块导入
使用的关键字 import
。
const foo = require('./foo.js')
接下来,了解一下模块导入(require)规则,假设文件目录为 src/project/index.js。
相对路径开头(假设此处要查找的模块是 moduleA)
在没有指定后缀名的情况下,先去寻找同级目录
src/project
是否有moduleA
文件。同级目录没有moduleA
文件,则会去找同级moduleA
目录src/project/moduleA
判断
src/project/moduleA
目录下是否有package.json
文件,如果有,返回main
字段定义的文件,如果没有main
字段,则尝试返回以下文件。src/project/moduleA/index.js
src/project/moduleA/index.json
src/project/moduleA/index.node
绝对路径跟 1 同理
react 没有路径开头
没有路径开头则视为导入一个包。优先判断 moduleA
是否是一个核心模块,如 fs
、path
。否则,会从当前文件的同级目录 node_modules
中寻找。寻找规则与 1 同理, src/project/node_modules
路径下以查找 moduleA.js
为例,moduleA.js
-> moduleA.json
-> moduleA.node
-> moduleA
目录 -> moduleA 下的 package.json main
-> index.js
-> ...
。如果没找到,继续向父目录的 node_modules
中找。
ES6 模块规范
模块导出
使用的关键字 export
。
foo.js
// 导出单个
export const a = 10;
export const b = function(){};
// 导出列表
export { a, b }
// 重命名导出
export { a as ma, b as mb, …, };
// 解构导出并重命名
export const { a, b: bar } = o;
// 导出模块合集
export * from 'export-name'; // 不能在当前模块(export-name)中使用。
export { a } from 'export-name' // 不能在当前模块(export-name)中使用。
// 默认导出
export default expression; // 一个模块只能有一个默认导出
模块导入
// 导入模块合集
import { a, b } from "module-name";
import * as moduleA from "module-name"