Three.js: 评估 TypeScript

创建于 2019-01-08  ·  28评论  ·  资料来源: mrdoob/three.js

评估 TypeScript

我使用 Ember.js RFC 的模板来记录这个问题。 我认为这是一个很好的模板,可以解决对更大变化的主要担忧。 有关他们的 RFC 流程的详细信息,您可以访问他们的 github 存储库: https :

概括

我想将所有 TypeScript 讨论集中到一个地方,因为现在关于 TypeScript 的所有优缺点都分散在几个问题、线程、拉取请求和讨论中。 这使得很难遵循,我认为如果我们不集中注意力,就不会有任何重大进展。 此外,我认为最近在https://github.com/mrdoob/three.js/issues/11552 中看到的关于 Three.js 和 TypeScript 的吸引力很大

动机

由于 TypeScript 在前端社区中变得越来越流行,我们可以开始考虑采用。 此外,如果您比较 npm 上@types/threethree包的每周下载量,似乎很多人已经在 TypeScript 中使用 Three.js。 在 2019-01-01 到 2019-01-07 的时间范围内, three下载量@types/three下载量three 40588(有关更多详细信息,请参阅:https://www.npmjs.com /package/@types/three 和 https://www.npmjs.com/package/three)。 此外,已经有很多工作分布在多个项目和存储库中。 因此,联合起来并在一个地方维护 TypeScript 的东西会很好。

在我看来,TypeScript 的优点多于缺点(当然,对于 JavaScript 中的类型和社区中的 TypeScript 有很多争议性的意见)

我看到的一些优点是:

  • 改善开发者体验的可能性,也适用于新的贡献者和三个库的用户
  • 类型可以帮助探索三个库的 api,它们可以帮助开发,而无需阅读文档
  • 不再有过时的@types/three定义
  • 为未来的转译优化留出空间(例如像tsickle这样的东西做得对,我认为将来会有更多这样的工具)。 像AssemblyScript这样的实验性工具也可以成为源代码中某些非常性能关键部分的选项
  • 类型有助于提高代码质量
  • 可以使用ECMAScript 标准的新特性并将源代码转换为不同的 ECMAScript 版本
  • 如果做得好,如果源代码是在 TS 或 JS 中维护的,那么对于 Three 库的用户来说没有任何区别
  • 使用编译器标志declarationDir我们能够从我们的源代码生成d.ts文件,因此所有类型总是最新的

详细设计

我们应该首先完成 ES6 的所有工作,因为它们构成了 TypeScript 的基础。 此外,从 ES6 到 TypeScript 的过渡也不会那么困难(因为 TypeScript 读起来很像带有类型的现代 JavaScript)。 要使用 TypeScript,我们只需要添加 rollup-plugin-typescript(我建议使用rollup-plugin-typescript2 )。 然后我们需要创建一个tsconfig.json并根据我们的需要设置所有的 TypeScript 编译器设置。 也许我们也应该添加tslint (还有一个汇总插件,称为rollup-plugin-tslint )。 构建完成后,我们可以合并在@types/three和其他项目(如three.ts)中完成的类型

我们如何教这个

首先,我们需要为新贡献者记录正确性。 对于 Three.js 的用户来说,一切都保持不变(因为 TypeScript 被转换为 JavaScript)。 经过一些迭代后,在 TypeScript 和 JavaScript 的文档中提供代码示例是有意义的。 如何做到这一点的一个很好的例子是Stripe API 文档

缺点

构建管道变得更加复杂,并且添加了更多依赖项。 此外,我不确定迁移测试套件和测试运行程序有多容易。 此外,新贡献者(不是库用户)的进入门槛可能会变得更高,因为他们需要了解 TypeScript。 添加类型时,非常通用的代码可能会变得非常冗长。 使用 TypeScript,我们更远离“平台”,因为中间有一个转换步骤,我们不能完全控制转换(当然我们可以编写自己的转换,但这非常乏味)

备择方案

坚持使用纯 JavaScript 但这也意味着我们忽略了像@types/three这样的项目已经完成的所有工作。 对于使用 TypeScript 的 Three.js 的所有用户来说,这意味着他们需要依赖非官方的 Three 类型。

未解决的问题

  • 我们真的想要这个吗?
  • 什么时候开始(现在或在 ES6 完成之后)?
  • 如何开始? 我们应该首先从d.ts文件开始还是完全跳入 TypeScript?
  • 谁能做到这一点,或者让我换个说法,谁有动力开始这个?

最有用的评论

在浏览器本身不支持 TypeScript 之前,我更喜欢专注于 JavaScript ES6。

我知道它可以编译为 .js,但我们才刚刚开始能够直接从 src 导入,我认为这比转换为 TypeScript 对项目更有帮助。

https://github.com/mrdoob/three.js/blob/dev/examples/webgl2_sandbox.html#L37 -L48

并排添加 *.d.ts 文件听起来不错,但需要有人拥有它并使其保持最新状态。

所有28条评论

从运行时性能来看,我感兴趣的是

像 AssemblyScript 这样的实验性工具也可以成为源代码中某些非常性能关键部分的选项

我一直在做 Three.js core + WASM 实验。

https://github.com/takahirox/three.wasm-experimental
https://twitter.com/superhoge/status/1071132448426262529

从实验中我意识到将整个核心移植到 WASM 可以提高运行时性能,在我的示例中快 1.5 倍,而部分移植小部分,例如数学代码(Vector3,Matrix4,...),没有任何好处,因为巨大的 JS-WASM 开销。

但是我认为将整个 Three.js 核心重写为 C++ 或 Rust 供贡献者使用并不是一个好主意,因为维护困难,所以我一直在寻找替代方法。 我感兴趣的是 TypeScript + AssemblyScript 是否适用于 Three.js。

如何开始? 我们应该首先从 d.ts 文件开始还是完全跳入 TypeScript?

我们将提交一个 PR,将 *.d.ts 文件添加到 Three.JS,主要基于 @types/three(从而重用该工作。)这是一个很好的起点,让我们现在继续使用 JS。 它也可以逐步完成。

@takahirox 干得好 :-) 我总是着迷于 Three.js 周围发生了多少创新工作。 遗憾的是,这些概念验证得到的关注如此之少。 我也认为用 C++ 或 Rust 重写所有内容都不是一种选择。 也许AssemblyScript是,但我没有尝试过AssemblyScript,所以我可以谈谈我读到的关于AssemblyScript的内容。 但也许我们也应该考虑 AssemblyScript,因为据我所知,它或多或少是 TypeScript 的一个子集

@bhouston我不确定将d.ts文件从@types/threethree库是否有意义。 特别是因为这些d.ts文件可以从 TypeScript 文件生成,然后它们总是同步的。 有没有办法确保d.ts文件始终以自动方式与 js 文件同步? 如果是,那么我认为将d.ts文件放入three库可能是有益的。 另外我认为这取决于维护者的决定。 如果他们不想采用 TypeScript,也可以选择d.ts文件。 此外,如果他们决定在几年内添加 TypeScript,我们可以在这一次使用d.ts文件进行桥接。 否则恐怕收益少,工作多。 但也许我只是忽略了一些东西

@bhouston我不确定将 d.ts 文件从 @types/three 移动到三个 repo 是否有意义。 特别是因为这些 d.ts 文件可以从 TypeScript 文件生成,然后它们总是同步的。

如果我们直接使用 TypeScript,则不需要 *.d.ts 文件。 问题是目前@types/three 项目对于 Three.JS 来说总是有点过时,因为它是单独维护的。 并且它反映了three.js的构建结构而不是单个文件,因此不能支持摇树和其他形式的优化。 因此,添加 *.d.ts 文件大大改善了项目的当前状态,但不如直接移动到 *.ts 文件好。

如果我们可以直接移动到 *.ts 文件,那是更好的选择。 我不确定是否有支持。

我知道 Three.JS 喜欢以增量方式做事,因此这是一个增量选择,而不是大爆炸。

@bhouston我完全同意你的看法。 而且我也认为大爆炸重写是不可能的,所以我们需要逐步采用。 但是如果我阅读 TypeScript 文档,似乎我们可以并排放置 ts 和 js 文件。 所以我们可以开始将单个文件转换为 ts。 有关更多详细信息,您可以阅读此博文: https :

但是如何处理 TypeScript 应该由维护者之一决定。 我认为这两个选项( d.ts文件或混合 ts 和 js 文件)都是可行的。 这或多或少是个人喜好和风格的问题。

@tschoartschi我想推进这个问题。 @mrdoob已批准并排 *.d.ts 文件。 我想去那里,因为它不会立即强制人们使用 TypeScript,我们可以退出它而无需在 *.ts 阶段重写所有贡献。 然后我们仍然可以将 *.js 文件逐渐转换为 *.ts 文件,主要是我将它们与并排的 *.d.ts 文件合并。

我认为并排的 *.d.ts 文件是非常好的第一步,而且很容易做到。 我宁愿不要让“完美”阻碍我们取得渐进的进步。

@bhouston很酷😎我也可以帮忙。 我认为你和其他人一起开始是有意义的,然后我可以加入。也许我们也可以与@types/three的维护者交谈。 我们应该在 Three.js 工作区中创建一个 Slack 频道吗? 因此,我们可以更快地进行调整,并且不会通过类似聊天的对话来污染这个问题。 不过,我会稍等片刻,直到@mrdoob添加他的观点。 因为如果他反对 TypeScript,我认为我们不应该投入时间。

一旦得到@mrdoob 的祝福,我愿意投入时间到港口。

在浏览器本身不支持 TypeScript 之前,我更喜欢专注于 JavaScript ES6。

我知道它可以编译为 .js,但我们才刚刚开始能够直接从 src 导入,我认为这比转换为 TypeScript 对项目更有帮助。

https://github.com/mrdoob/three.js/blob/dev/examples/webgl2_sandbox.html#L37 -L48

并排添加 *.d.ts 文件听起来不错,但需要有人拥有它并使其保持最新状态。

@mrdoob我不认为等待浏览器支持 TypeScript 是一种选择。 我没有听到任何浏览器供应商有任何实施 TypeScript 的意图。 但是我看到了您的担忧,尤其是在示例中。 我没有看新的例子。 可以只导入示例中的源文件,真是太棒了。

我不确定在 TypeScript 中编写库的最佳解决方案是什么,并且仍然可以从 src 导入 JavaScript。 当然,我们可以转换 TypeScript 文件,然后并排放置相应的 JavaScript 文件(这是 TypeScript 编译器的标准设置),但这可能会使代码版本控制等复杂化。文件夹结构可能如下所示

three/
├── src/
    ├── cameras
        ├── PerspectiveCamera.ts // authored code
        ├── PerspectiveCamera.js // generated code by TS compiler

尽管如此,这对我来说似乎有点尴尬,因为转换后的代码应该放在distbuildbin文件夹中。 但这只是一种观点,并非铁定的事实。 也许有一些 TypeScript 极客知道更好的解决方案。

另一个选项是@bhouston 建议的d.ts文件。 但正如@mrdoob提到的,保持d.ts文件最新可能很棘手。 尤其是从长远来看。 让它们在未来几年保持最新状态真的可以管理吗? 我可以帮助设置d.ts文件,但我不能保证我会一直参与更新它们。 对我来说,连续投入时间比阻塞一个时间段并完成一些事情要困难得多。 我仍然不确定是支持@types/three项目还是将d.ts文件直接添加到three项目中更好。 @types/three项目已经在运行,并且满足与d.ts方法相同的需求。 它也有类似的挑战。 这基本上是保持最新状态。

所以我的结论是,在未来的中期,对于 Three.js 中的 TypeScript 来说,它看起来不太好。 对我来说这很好,尽管我希望看到更多的 TypeScript 被采用。

只是另一个建议:
Phaser 游戏框架使用其注释自动生成类型定义。 我认为该工具是开源的。 因此,可以通过以正确方式在函数上方添加 /** 注释 */ 来生成 TS 定义。

Phaser 游戏框架使用其注释自动生成类型定义...

参见https://github.com/mrdoob/three.js/issues/11550https://github.com/mrdoob/three.js/issues/4725#issuecomment -41833647。

尽管如此,从*.d.ts文件中的注释生成文档可能很有趣。 🤔

并排添加 *.d.ts 文件听起来不错,但需要有人拥有它并使其保持最新状态。

如果可以以编程方式根据源代码检查类型,我就可以了。 如果没有,并且我们不打算最终用 TypeScript 重写代码库,我认为将类型移到存储库中不是一个好主意。 如果有的话,我们不太准备在这里维护它们——至少当前的维护者自己正在使用 TypeScript。

还有这个项目https://github.com/semleti/three.ts
也许值得一看并将其升级到 v100 而不是开始一个新的?
因为我没有看到 Three.js 被用 TypeScript 重写,除非很明显,为这样一个庞大的项目使用类型会更好......而且我很理解为什么它可能永远不会发生,因为它会依赖于一种语言这不是浏览器内部的标准。

@schoening我开始这个讨论是因为有一些 Three.js 的概念验证 TypeScript 版本。 这是你链接的repo,或者@flyover完成的@types/three项目保持同步。 我认为我们应该在那里联手。

如果 Three.js 将在遥远的未来某个时候支持 TypeScript,那么想想这种转变如何成功会很棒。 正如@donmccurdy提到的,有几种方法可以实现更好的 TypeScript 兼容性。 我认为 JSDoc 可能是一种可行的方法。 我仍然不相信*.d.ts文件,因为我认为让它们保持最新比 JSDoc 评论更难。 此外,我认为没有一种方法可以使用*.d.ts文件以编程方式检查源代码。 但也许@bhouston可以概述他的方法,尤其是关于保持最新状态的担忧。 也许有一些聪明的解决方案可以解决这个问题。

目前对我来说最好的体验是 vscode + d.ts + JSDoc,都在同一个项目中,所以很容易保持同步。

最新的 vscode 版本改进了checkJs支持(可以在tsconfig.json启用),这基本上是 TypeScript 编译器检查 JavaScript 文件,使用来自 JSDoc 的类型加上从d.ts合并的声明对于更“高级”的类型,这在 JSDoc 语法中会很丑陋。

由于 vscode 可以派生所有类型它也可以检测各种类型错误,因此无论何时重构完成,都可以轻松查看和编辑d.ts的“错误/旧”类型,因此它会保持同步.

TypeScript 最糟糕的事情是额外的转译步骤,每次更改代码都可能需要几秒钟。 简而言之,vscode 中的 JSDoc + d.ts具有类型的所有优点,但没有额外慢转译步骤的缺点。

唯一的问题是向所有内容添加 100% 正确的 JSDoc 类型,因此 vscode 可以依赖它(就像@constructor<strong i="16">@enum</strong> {number}<strong i="18">@param</strong> {number} n Number of steps

我还想在这里补充一点, @bhouston@LuWangThreekit*.d.ts文件创建了一个 PR。 有关更多详细信息,请查看他们的注释: https : https://github.com/mrdoob/three.js/pull/ 15597

旁注:如果Deno (一个基于 V8 和 Rust 构建的 TypeScript 解释器,在 GitHub 上拥有 32,000 颗星)被证明是值得的,那么浏览器中的 TypeScript 可能不会太远。

由于我们为核心和示例模块添加了类型声明文件,我认为现在可以关闭问题。 TS用户的开发体验肯定比去年好。

对于任何对 TypeScript 感兴趣的人...

这个受 Three.js 启发的库@bhouston正在开发中,可能正是您要找的:

https://threeify.org/

Threeify@bhouston似乎是一个伟大的工程🤩有SemVer和使用语义释放。 它建立在 TypeScript 之上,其核心价值似乎是 Tree Shaking、Small Build Files 等。我们许多人也希望在 Three.js 中看到所有这些。 所以我真的很重视Threeify的工作👍

@bhouston @mrdoob但是真的有必要创建一个新项目吗? 分裂社区有意义吗? 许多大型前端框架都设法过渡到 SemVer、TypeScript、Tree Shaking 等,而无需对其代码和社区进行分叉。

我认为@pailhead写了一篇关于使用 Three.js 的有趣文章,我认为是以下内容:使用不同的three.js 版本。 所以我认为社区中有人愿意帮助采用Threeify尝试实施的一些东西。 我认为加入这些力量并改进 Three.js 而不是创建一个新库会很棒。

和网上的很多文章一样,Pailhead 的文章是有偏见的。 不考虑库的其他用途。

我认为不可能在不干扰彼此开发工作流程的情况下制作一个满足所有类型的 js 开发人员的库。

我们与@pailhead有着非常相似的经历,我不认为他的工作流程是一个小众的工作流程。 我认为他的工作流程对于使用VueEmberReactSvelteAngular等现代前端框架的开发人员来说非常常见……

也许我们应该看看Vue是如何做到的。 它的用户群范围从只想增强网站的 PHP 程序员到开发复杂网络应用程序的人。 它很好地弯曲了这些不同类型用户之间的曲线。

另外关于在不破坏每个人的体验的情况下升级现有代码库,那里有很好的例子。 我们可以看看Ember如何与 Web 社区及其行业标准一起持续发展。

我不会认为跟上现代 Web 开发的步伐是不可行的。 但我完全同意这需要付出很多努力,我们需要在这些事情上花很多心思。 这就是为什么我认为合作创造现代体验比创建几个新项目更好。

当你浏览这个线程时,已经有两个不同的项目,Three.ts 和 Threeify,可能还有更多。 我真的相信如果我们一起工作而不是创建分叉和单独的计划,对整个 Three.js 社区会有巨大的好处。

@mrdoob ,如何进行调查以收集一些数据? 使用打字稿是一回事,我相信还有其他定性变量我们可以尝试进行估计。

@roomle-build 你能列出将库转换为 TypeScript 的缺点吗?

我没有看到逐渐为库采用 TypeScript 的真正缺点。 相比之下,我认为它会带来很多好处(这就是为什么许多项目都在转换为 TypeScript)。 尽管如此,当然也有一些挑战,例如:

  • 我们如何为非 TS 用户提供良好的体验?
  • 没有内置步骤的用户如何使用库
  • 当然还有我没有想到的所有其他事情

但正如我之前所说,这些问题也可以在其他项目中解决,我们可以从那里复制这些解决方案(例如VueEmber )。

但我想指出的主要事情是,我认为如果社区分裂并且我们有几个不同的项目并且分叉的分叉,我认为这是危险的。 我不喜欢碎片化,我认为一起工作比相互对抗更好。 当然,还有其他人会争辩说竞争是巨大的,这也会在 Three.js 项目中促进创新,但我更相信合作🙂

我认为three.js的最大优势之一是它的可访问性。 @roomle-build 列出的要点会降低引擎的易用性(尤其是在初学者的情况下)。 我投票支持继续使用 JavaScript,除非浏览器本身支持另一种编程语言。

我不喜欢碎片化,我认为一起工作比相互对抗更好。

在 Web 中拥有更多 3D 引擎并不意味着开发人员会相互对抗。 有时,如果不同的项目专注于不同的事情,实际上会更好。

我认为three.js的最大优势之一是它的可访问性。 @roomle-build 列出的要点会降低引擎的易用性(尤其是在初学者的情况下)。

我不这么认为,因为其他项目在 TypeScript 中编写他们的代码而对可访问性没有任何影响。 我之前提到过 Vue 和 Ember 作为例子。 也许回顾一下反对 TypeScript 的立场是有意义的? 我们不需要发明一些东西,我们只需要复制其他项目的成功方法。 此外,我认为 TypeScript 的好处是three.js对贡献者来说更容易访问,因为 IDE 可以帮助他们更快地了解整个项目。

我投票支持继续使用 JavaScript,除非浏览器本身支持另一种编程语言。

我认为这在可预见的未来不会发生,因此我认为我们应该对 TypeScript 有更务实的看法。 正如我上面写的,我认为这只是项目和回购的组织方式的问题,而不是易用性和开发体验之间的权衡。

我想我们已经表明了我们的立场。

此页面是否有帮助?
0 / 5 - 0 等级