背景
白鹭已经在 5.3.6 版本中加入了对 Webpack 的支持,通过 webpack ,开发者可以大幅改善项目的增量编译效率,并可以充分使用 npm 上丰富的 JavaScript 第三方库。
白鹭引擎团队将 webpack 封装为了两个白鹭引擎的构建管线插件,分别称为 WebpackDevServerPlugin 和 WebpackBundlerPlugin。所有白鹭项目均可以使用这两个插件。
这两个插件在执行构建时,包含了一个 typescript.mode的字段,可以设置为 legacy 或 modern,这分别对应着两种不同的编译模式,前者更适用于兼容现有老项目,后者更适用于新项目。以下表格为这两种模式以及传统模式这三者的对比。
legacy 模式步骤
步骤一:替换现有的编译命令
使用白鹭引擎 5.3.7 版本创建一个新项目,然后将scripts/plugins文件夹拷贝至现有项目同级目录下。
将 scripts/config.ts 中的 IncrementBuildPlugin 和 CompilePlugin 替换为 WebpackDevServerPlugin 和 WebpackBundlerPlugin 。
步骤二:设置编译参数
WebpackDevServerPlugin 和 WebpackBundlerPlugin 内部实现均是调用了 @egret/egret-webpack-bunlder 中的相关方法,调用这些方法需要传递参数,通常按照默认值设置即可,主要需要注意的参数是 typescript.mode,如果是现有项目请确认设置为 legacy。
步骤三:执行构建
修改完上述代码后,执行 egret build 即可。编译后可能会报错,这是因为白鹭引擎之前的TypeScript编译器是2.4版本,而最新则采用3.9版本,新版本编译器会进行更严格的类型检查。修复这些错误后即可顺利运行您的项目。
modern 模式步骤
除了 legacy 模式以外,我们还提供了 modern 模式。如上文所述,这种模式下编译速度更快,但是需要进行较复杂的转换,白鹭引擎在后续版本的创建新项目时默认模板将改为 modern 模式。
如果您想将现有项目转换为 modern 模式,请按照如下步骤
步骤一:执行转换脚本,生成一个新的 TypeScript 项目
首先安装转换脚本
npm install @egret/convert-egret-project-to-es6 -g
convert-egret 脚本内部会执行如下操作:
-
根据项目的 tsconfig.json 文件,获取所有 .ts 和 .dts 文件;
-
将 libs 文件夹拷贝至新的路径;
-
遍历每个 ts 文件,为所有的类、全局函数和全局变量添加 export 关键字;
-
再次遍历每个 ts 文件,为所有类添加对应的 import 语句 5. 将这些 ts 文件重新生成至新路径。
步骤二:执行 TypeScript 编译检查
执行如下脚本
上述脚本的作用是调用 typescript 编译检查(不生成js文件),理论上执行完此代码后,不应该有任何报错,但是由于如下几个原因,可能会导致报错:
-
白鹭引擎之前的TypeScript编译器是2.4版本,而最新则采用3.9版本,新版本编译器会进行更严格的类型检查;
-
添加完 export / import 后可能有一些语法错误;
cd {output-path}
tsc --noEmit
步骤三:将这个新项目中的 TypeScript 代码替换到现有项目中
这一步需要将现有项目的 src 代码全部删除,然后将新项目的代码拷贝进来,强烈建议做好备份
步骤四:在现有项目中添加 WebpackBundlerPlugin
您可以使用引擎 5.3.6 创建一个新项目,然后将 scripts/plugins 文件夹拷贝至现有项目同目录,然后在 config.ts 中添加 new WebpackDevServerPlugin() ,代替掉 IncrementBuildPlugin()。 添加该插件后,执行 egret build 命令,WebpackBundlerPlugin 会自动进行 webpack构建、启动服务器、打开浏览器相关功能,可以代替 egret run 命令。
步骤五:修复因循环依赖而产生的诸多问题
这一过程比较复杂,构建成功后,打开浏览器控制台,您很大概率会发现项目无法运行并存在一些报错,通过堆栈可以判断其大意是某个类继承了一个 undefined 的类。这种问题是循环依赖导致的,具体原因如下:
// index.ts
import { MyComponent } from "./component";
import { MyComponent2 } from "./component2";
export class MyApp {
constructor() {
const myComponent = new MyComponent(this);
const myComponent2 = new MyComponent2();
}
}
export class BaseObject {
}
// component.ts
import { MyApp } from ".";
export class MyComponent {
constructor(app: MyApp) {
}
}
// component2.ts
import { BaseObject } from ".";
export class MyComponent2 extends BaseObject {
constructor() {
super();
}
}
上述代码中,只要在MyApp中引用MyComponent不会报错,但是如果引用了 MyComponent2,就会报错。 这是因为 index.ts 中的 import { MyComponent2} from ‘./MyComponent2’ 中执行时,class BaseObject 还没有生成,而MyComponent2 继承了 BaseObject,就会出现这个问题。
上述问题解决后,您就可以使用 modern模式进行项目开发了。
其他
使用 npm 脚本代替白鹭构建管线
除了通过 egret build 命令运行,egret-webpack-bunlder 也可以直接使用 npm 脚本执行,不采用白鹭的构建管线,具体方式如下:
使用标准 npm 方式添加 webpack / webpack-devserver 等脚本,不再赘述
安装 @egret/egret-webpack-bundler ,版本号1.1.5 以上
修改如下 webpack.config.js,如下所示
//@ts-check
const path = require('path');
const bundler = require('@egret/egret-webpack-bundler');
const config = bundler.generateConfig(__dirname, {
libraryType: 'debug'
}, 'web', false)
module.exports = config;
升级 egret-webpack-bundler 版本
我们已将 egret-webpack-bunlder 托管到 npm 上,如果您需要更新最新版本,可以在 scripts/plugins 文件夹下执行以下脚本:
npm install @egret/egret-webpack-bundler@next --save --registry https://registry.npm.taobao.org