是否可以创建仅编译为平台代码的电子应用程序?

分享于2022年07月17日 electron javascript typescript 问答
【问题标题】:是否可以创建仅编译为平台代码的电子应用程序?(Is it possible to create an Electorn application that compiles only to the platform code?)
【发布时间】:2021-12-27 21:57:49
【问题描述】:

我将针对一个非常具体的用例澄清我的问题。

假设我的代码设计如下:

Is it possible to create an Electorn application that compiles only to the platform code?

这是内容:

src/inner/inner.darwin.ts:

export default function logger() {
    console.log('Darwin Logger');
}

src/inner/inner.windows.ts:

export default function logger() {
    console.log('Windows Logger');
}

src/inner/inner.ts:

注意导出默认值 - 这是强制性的

import LOGGER from '???????????';

export default class A {
    public static logger() {
         LOGGER();
    }
}

所以基本上,当我编译 Windows 代码时,我想导入 inner.windows.ts 代码。使用 Mac 代码时 - inner.darwin.ts 代码。

我知道我可以控制 tsconfig.json 中的排除文件。 因此,当我要创建 Windows 应用程序时,我将编写代码:

"exclude": ["**/*.darwin.ts"]

我什么时候会创建 Mac:

"exclude": ["**/*.windows.ts"]

但是,它对解决导入问题没有帮助。

我知道我可以运行代码取决于使用 process.platform 的底层平台,但它不能完成这项工作。我希望输出的 Windows 应用程序更小 - 并忽略任何 Mac 代码。如果我使用这个 process.platform - Mac 代码仍将存在于底层 Windows 应用程序中。

有什么建议吗?

Webpack 能帮上忙吗? 我对任何代码更改持开放态度,只要代码定义明确并拆分,最终结果是我只有达尔文代码和 Windows 代码

  • "Mac 代码仍将存在于底层 Windows 应用程序中。"所以呢?您的应用程序的绝大部分大小将是可执行运行时,而不是您的 javascript 代码。我有一个 52MB 压缩的电子应用程序,有 1MB 的未压缩代码。您拥有的任何特定于平台的代码可能只是其中的一小部分。像 Electron 这样的跨平台框架的主要优点之一是您 不必 为每个平台进行这种自定义编译。相同的代码库只适用于所有平台。
  • @AlexWayne 这是一个很好的通知,但我仍然需要它
  • 你能解释一下为什么你需要这样吗? 2个版本有冲突吗?如果是这样,以一种可以共存的方式重构代码可能会更容易/更好。
  • @phuzi 我唯一的目的是使应用程序更小。就这样。这两个版本做同样的事情 - 但他们做的方式不同并且依赖于操作系统。但它们有着相同的逻辑。在上面的示例中,假设我会使用一些编造的命令 windows.logger('blabla') darwin.logger('blabla')
  • 您认为您会节省多少应用程序大小?

【解决方案1】:

所以解决方案很简单。我所要做的就是使用 Webpack 插件。 适合此任务的最佳插件是 NormalModuleReplacementPlugin ,它由 Webpack 本身开箱即用地提供。

tsconfig.ts 中的 exclude 在此解决方案中不再合理。

只需提供以下插件:

new webpack.NormalModuleReplacementPlugin(
    /darwin/,
    function (resource) {
    resource.request = resource.request.replace(
        /darwin/,
        'windows',
    );
    }
),

这会将任何对 darwin 文件的导入覆盖到 winodws 文件中。

现在,在开发中,这两个文件都存在 - 但在编译中 - 只有其中一个会存在。

inner.ts 简单地变成:

import LOGGER from './inner.darwin';

export default class A {
    public static logger() {
         LOGGER();
    }
}

当然,每次构建都进入 webpack.config.ts 会很麻烦,所以我们绝对可以运行一些额外的 webpack 脚本来决定使用哪个底层构建,例如:

 const appTarget = env.APP_TARGET || 'darwin'; 

然后简单地在插件中使用这个变量,并运行你的 npm 构建脚本,提供一个 APP_TARGET 参数。