如何使用 Webpack 改进编译速度

背景
白鹭已经在 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 脚本内部会执行如下操作:

  1. 根据项目的 tsconfig.json 文件,获取所有 .ts 和 .dts 文件;

  2. 将 libs 文件夹拷贝至新的路径;

  3. 遍历每个 ts 文件,为所有的类、全局函数和全局变量添加 export 关键字;

  4. 再次遍历每个 ts 文件,为所有类添加对应的 import 语句 5. 将这些 ts 文件重新生成至新路径。

步骤二:执行 TypeScript 编译检查
执行如下脚本

上述脚本的作用是调用 typescript 编译检查(不生成js文件),理论上执行完此代码后,不应该有任何报错,但是由于如下几个原因,可能会导致报错:

  1. 白鹭引擎之前的TypeScript编译器是2.4版本,而最新则采用3.9版本,新版本编译器会进行更严格的类型检查;

  2. 添加完 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

猜你喜欢

转载自blog.csdn.net/weixin_41926242/article/details/106897953