在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.exportsexports来导出模块。


这种规范适用于服务器端开发,在浏览器中使用时可能会遇到性能问题,因为同步加载可能会阻塞页面渲染。


例如:

// 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)开始引入,importexports 语法来导入和导出模块,与现代浏览器和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)、设置导入映射文件的路径


注意:设置导入映射文件的路径非常重要, 因为导入映射中的所有相对路径都是相对于导入映射文件路径。


通过编辑器顶部菜单栏的 项目 -> 项目设置 -> 脚本 中的 导入映射 进行设置。


CocosCreator3.8研究笔记(四)CocosCreator 脚本说明及使用(上)-LMLPHP


CocosCreator3.8研究笔记(四)CocosCreator 脚本说明及使用(上)-LMLPHP


设置完成后,导入映射功能开启,使用的导入映射将从指定的文件中读取。


(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 项目设置 中的 功能裁剪 进行启用或关闭。


CocosCreator3.8研究笔记(四)CocosCreator 脚本说明及使用(上)-LMLPHP


1、引擎模块使用


Cocos Creator 3.8 引擎api 都在cc 中, 使用标准的 ES6 模块导入语法将其导入,如下导入需要使用的类:

import {
    Component,  // 导入类 Component
    _decorator, // 导入命名空间 _decorator
     CCInteger, // 导入类 CCInteger
    EventMouse,	// 导入类 EventMouse
    input,			// 导入命名空间 input
    Node,			  // 导入类 Node
    Label,			// 导入类 Node
    Sprite			// 导入类 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)、执行环境:


(2)、调试级别:


调试级别使用如:

import { log } from 'cc';
import { DEV } from 'cc/env';

if (DEV) {
    log('I am in development mode!');
}

09-03 11:32