在Cocos Creator中,脚本代码文件分为模块和插件两种方式:
- 模块一般就是项目的脚本,包含项目中创建的代码、引擎模块、第三方模块。
- 插件脚本,是指从 Cocos Creator 属性检查器中导入的插件,一般是引入第三方引入库文件,目前 Cocos Creator 只支持 javaScript 脚本插件。Cocos Creator会向插件脚本内容中,插入一些代码,适配Creator,并且会屏蔽全局变量 model 、exports 、define 。
由于篇幅原因,CocosCreator 脚本说明及使用分为上、下两篇进行介绍, 这篇文章主要介绍脚本模块,下一篇结束插件脚本。
一、模块的概念
在目前前端开发中,模块化已成为一种不可或缺的开发方式。
JavaScript模块规范为开发者提供了不同的选择,以满足不同的项目需求和开发风格,每一种都有其独特的特点和适用场景。
在讲解CocosCreator 模块前,首先需要普及两个概念:CommonJS (CJS) 模块、ECMAScript Modules (ESM) 模块。
1、CommonJS (CJS)模块
相信熟悉Node 与 Javascript的朋友都知道, 早期的Node 与 Javascript 没有模块
这个概念。
为了方便对代码开发和管理,Node 首先提出了 CommonJS 模块规范。
它采用同步加载模块的方式,通过require
来引入模块,使用module.exports
和exports
来导出模块。
这种规范适用于服务器端开发,在浏览器中使用时可能会遇到性能问题,因为同步加载可能会阻塞页面渲染。
例如:
// tools.js
module.exports = function dosomething(data) {// todo
}// main.js
const dosomething = require('./tools.js')
CommonJs 是引入对象的一个拷贝,可以直接运行在后端环境中。因此 CommonJs 在浏览器环境中是无效的,必须要经过编译和打包后才能在浏览器环境中执行。
2、ECMAScript Modules (ESM)模块
(1)、ESM是什么?
ESM 是官方规定的JavaScript 模块规范,实现标准模块系统方案,从ES6(ES2015)开始引入,import
和exports
语法来导入和导出模块,与现代浏览器和Node.js 兼容。
例如:
// tools.js
export const dosomething () {// todo
};// main.js
const { dosomething } = import('./tools.js')
在 script 中可以直接引用 ESM 文件:
<script src="./main.js" type="module"></script>
设置type=module
,会将加载的文件视为模块文件,识别模块的import
语句并加载。
(2)、ESM 模块的特点
-
自身的静态化特点,在编译时加载,使得页面加载速度快。
-
真正意义上做到了按需使用。使用 import 并不会直接执行模块,而是生成一个动态的只读引用,等到真的需要用到时,才会到模块里面去读取。
二、CocosCreator 模块的规范
1、模块格式
Cocos Creator 原生支持并推荐使用 ECMAScript (ESM)模块。
Cocos Creator 引擎提供的所有功能都以 ESM 模块的形式存在。
例如:
import { _decorator, CCInteger, Component, EventMouse, input, Node,Label, Sprite} from 'cc';
const { ccclass, property,type,integer} = _decorator;
Cocos Creator 项目资源目录中以 .ts
作为后缀的文件都视为 ESM 模块。
例如:
assets/scripts/PlayerControl.ts
对于除.ts 外的其它模块格式,Cocos Creator 按以下规则来进行鉴别:
ESM 格式
- 以
.mjs
为后缀的文件; - 以
.js
为后缀的文件,并且与其最相近的父级package.json
文件中包含一个顶级的"type"
字段,其值为"module"
。
CommonJS 模块格式
- 以
.cjs
为后缀的文件; - 以
.js
为后缀的文件,并且与其最相近的父级package.json
文件中包含一个顶级的"type"
字段,其值为"commonjs"
。 - 不在上述条件下的以
.js
为后缀的文件。
二、CocosCreator 模块说明符和模块解析
在 ESM 模块中,通过标准的导入导出语句与目标模块进行交互。
import { PlayerControl } from './PlayerControl';
export { PlayerControl } from './PlayerControl';
导入导出语句中关键字 from
后的字符串,称为 模块说明符。
模块说明符也可作为参数出现在动态导入表达式 import()
中。
模块说明符用于指定目标模块,从模块说明符中解析出目标模块 URL 的过程称为 模块解析。
Cocos Creator 支持三种模块说明符:
1、相对说明符
像 './PlayerControl'
、'../PlayerControl'
这样以 './'
和 '../'
开头的说明符。
相对说明符是以当前模块的 URL 为基础来解析目标模块项目路径。
例如,对于模块项目路径:
/assets/scripts/utils/PlayerControl
如果有相对说明符:
'./a'
这个url将解析为同目录下的 项目路径:
/assets/scripts/utils/a
2、绝对说明符
直接指定了目标模块的 URL。
例如:
/assets/scripts/utils/PlayerControl
3、裸说明符
像 PlayerControl、PlayerControl/a 这样既不是 URL 又不是相对说明符的说明符。
Cocos Creator 使用导入映射,控制 TypeScript/JavaScript 的导入行为,指定对裸说明符的解析。
导入映射使用方法:
(1)、设置导入映射文件的路径
注意:设置导入映射文件的路径非常重要, 因为导入映射中的所有相对路径都是相对于导入映射文件路径。
通过编辑器顶部菜单栏的 项目 -> 项目设置 -> 脚本 中的 导入映射 进行设置。
设置完成后,导入映射功能开启,使用的导入映射将从指定的文件中读取。
(2)、使用别名映射
假如有一个模块在项目中被很多其他模块使用,我们希望其他模块以别名的方式引用,而不用相对路径的方式,此时就可以使用别名映射。
例如,某个模块绝对路径为 :
/assets/lib/tools.ts`
我们希望可以用别名的方式引用:
import {} from 'tools';
操作步骤如下:
第一步,在项目目录下创建一个导入映射文件 import-map.json
:
// import-map.json
{"imports": {"tools": "./assets/lib/tools.ts"}
}
"imports"
:应用到所有模块的 顶级映射。"tools"
:要映射的模块名。"./assets/lib/tools.ts"
: 是相对路径, 此路径将解析为绝对路径项目目录/assets/lib/tools.ts
。
注意:导入映射中的所有相对路径都是相对于导入映射文件本身的位置的!
第二步,在任意模块中使用以下方式引用模块,'tools'
都将解析为模块的绝对路径。
import * as tools from 'tools';
(3)、使用目录映射
目录映射:允许映射指定目录下的所有模块。
例如,要映射项目 assets/lib/tools
目录下的所有模块,则导入映射的 json 文件如下所示:
{"imports": {"tools/": "./assets/lib/tools/"}
}
除了 "tools/"
指定的是我们要映射的目录,其余的与 别名映射 一致。
这样项目中的模块都能以 import {} from 'tools/...'
的形式来引用目录 tools
中的模块。
import * as a from 'tools/a';
import * as c from 'tools/b/c';
'tools/a'
将解析为模块 项目目录/assets/lib/tools/a.ts
'tools/b/c'
将解析为模块 <项目>/assets/lib/tools/b/c.ts
。
(4)、TypeScript 支持导入映射所需配置
在项目目录下的 tsconfig.json
文件中配置paths
字段:
// tsconfig.json
{"compilerOptions": {"paths": {// 注意:这里的相对路径是相对于 tsconfig.json 所在的路径// 由于本例中 tsconfig.json 和 import-map.json 位于同一目录,因此这里的相对路径也相似。"tools": ["./assets/lib/tools.ts"],"tools/*": ["./assets/lib/tools/*"]}}
}
三、CocosCreator引擎模块
引擎通过模块 'cc'
向开发者暴露功能接口,提供了所有引擎功能的访问,模块以 ECMAScript 模块形式存在。
模块 'cc'
的内容是动态的,可以在 CocosCreator 项目设置 中的 功能裁剪 进行启用或关闭。
1、引擎模块使用
Cocos Creator 3.8 引擎api 都在cc 中, 使用标准的 ES6 模块导入语法将其导入,如下导入需要使用的类:
import {Component, // 导入类 Component_decorator, // 导入命名空间 _decoratorCCInteger, // 导入类 CCIntegerEventMouse, // 导入类 EventMouseinput, // 导入命名空间 inputNode, // 导入类 NodeLabel, // 导入类 NodeSprite // 导入类 Node
} from 'cc';const { ccclass, property,type,integer} = _decorator;
@ccclass('PlayerControl')
export class PlayerControl extends Component
{}
如下整个 Cocos Creator 模块:
import * as modules from 'cc';
const { ccclass, property,type,integer} = _decorator;
@ccclass('PlayerControl')
export class PlayerControl extends Component
{}
2、引擎日志输出
import { log } from 'cc';
log('Hello world!');
3、代码优化常量
引擎模块 'cc/env'
暴露了一些构建时的 常量,这些常量代表执行环境、调试级别或平台标识。
(1)、执行环境:
BUILD | 是否正在构建后的环境中运行 |
---|---|
PREVIEW | 是否正在预览环境中运行 |
EDITOR | 是否正在编辑器环境中运行 |
(2)、调试级别:
名称(类型都为 boolean ) | 说明 |
---|---|
DEBUG | 是否处于调试模式。仅当构建时未勾选调试选项的情况下为 false ,其它情况下都为 true |
DEV | 等价于 DEBUG /EDITOR /PREVIEW |
调试级别使用如:
import { log } from 'cc';
import { DEV } from 'cc/env';if (DEV) {log('I am in development mode!');
}