JSIL、Script#和SharpKit的比较

19

我正在考虑使用Script#、JSIL和SharpKit作为将C#编译为Javascript的工具,这样我就可以在Visual Studio中使用C#编写AJAX的客户端功能。

JSIL、Script#和SharpKit各有优缺点,请问它们分别是什么?

我的项目使用Razor引擎和C#,是一个MVC4项目。


请考虑使用SharpKit,http://sharpkit.net/。 - Wiktor Zychla
@WiktorZychla 谢谢。我也会研究SharpKit。您是否会提到它与JSIL和Script $#相比的优缺点? - Kyle
5个回答

21
如果你想直接与一个MVC项目集成,像Script#或SharpKit之类的工具可能是最好的选择 - 我知道Script#内置了一些东西,使这种集成更容易,所以我建议从那里开始。
如果你想尝试使用JSIL,它可能具备你需要的核心功能,但是你可能想要的诸如Visual Studio集成、自动化部署等功能并不存在。目前,它主要面向应用程序的交叉编译,因此在这方面它做得很好,但在其他用例方面则不太理想。
我将尝试总结一下为什么你可能会考虑JSIL而不是其他替代品的原因 - 我无法深入评论这些替代品的优缺点,因为我没有使用过它们。

JSIL对C# 4中可用的功能支持非常广泛。其中一些值得注意的功能(要么是因为其他工具不支持它们,要么是因为它们很复杂)包括:

动态, yield, 结构体, ref / out, 委托, 泛型, 可空类型, 接口, 和 枚举

当然,上述内容中有些并没有完整的支持。如果想要了解绝对能够工作的内容,您可以查看测试用例。每个测试用例都是一个小的、自包含的 .cs 文件,通过测试确保 JSIL 和本机 C# 产生相同的输出。

提供如此广泛的支持是因为我的目标是让 JSIL 能够将一个完全未修改的 C# 应用程序转换为可用的 JS。对于 JSIL 网站上的所有演示,这是真实的,并且我还有一些几乎完成的大型真实游戏移植项目,也符合这一点。


另一个原因是JSIL使得你的C#和JavaScript之间的交互相对容易。所有的C#类型和方法都通过一个尽可能友好的接口暴露给JavaScript。JS版本具有基本的重载解析和分发,以便在大多数情况下从脚本代码中调用本地C#接口就像它们是本地JS一样。除非你想要这样做,否则你不需要采取任何特殊的步骤来标记你希望向JS公开的方法或给它们命名等。当你想从C#调用JS时,可以使用几种方式:
  • JSIL.Verbatim.Expression 允许您直接将原始JavaScript插入到函数的翻译版本中。
  • JSIL.Builtins.Global 可以与dynamicvar结合使用,在C#函数体中直接编写类似于JavaScript的代码。
  • The JSReplacement attribute 可用于将C#函数的调用替换为带参数的JavaScript表达式。
  • 所有上述功能都可以与JSIL的类型信息更改机制(称为代理)相结合,以允许您更改所使用的库的类型信息,即使您没有源代码,也可以将其方法映射到您编写的JavaScript。
  • 最后,未被翻译为JS的C#方法会产生一个名为空的方法,称为External,您可以在运行时用JavaScript替换它以使其再次工作。您没有替换的任何External方法都会在运行时产生清晰的警告消息,以便您知道缺少什么。

JSIL会积极利用类型信息以及您提供的元数据,尝试安全地优化生成的JavaScript。在某些情况下,这可以产生比手写代码更好的等效JavaScript - 目前这种情况主要出现在使用结构体的代码中,但也可以适用于其他情况。
举个例子,在这段代码片段中, JSIL 能够静态地确定尽管代码隐含了多次结构体复制,但是这些复制实际上对于代码的正确行为并不是必要的。由此产生的 JavaScript 最终不会有任何多余的复制,因此它比你天真地翻译原始 C# 语义得到的结果运行得更快。这是在编写天真的基于结构体的程序 (比如无处不是的 Vector2s!) 和 完全疯狂地手动进行命名返回值优化 之间的完美折中,而后者,正如我过去所描述的那样,很容易出错

好的,现在让我们来谈谈一些缺点。请注意,这个列表不是详尽无遗的:

  • JSIL没有为.NET BCL的大部分功能提供实现。未来,可能会通过将整个Mono mscorlib翻译成JavaScript来解决这个问题,但我没有做到足够好,不能作为立即解决方案的倡导者。(对于游戏来说还可以,因为它们不使用BCL的大部分功能。)这个问题主要是由于与翻译Microsoft的mscorlib相关的IP问题引起的——如果我能在法律上做到这一点,我现在就会这样做——在我上次测试时它是有效的。
  • 如上所述,没有Visual Studio集成。JSIL非常容易使用——您可以提供一个.sln文件以自动获取一堆.js输出,并在项目旁边自动配置一个配置文件——但它远远没有Script#那么精致或集成。
  • 没有供应商或支持人员。如果您想昨天修复错误或遇到问题,目前我基本上是您唯一的选择(尽管有几个多产的贡献者正在帮助改善情况,并且更多的人始终受欢迎!)
  • JavaScript性能是一个充满看不见地雷的迷宫。如果你只想让应用程序工作,你可能不会遇到任何问题,但如果像我一样,你正在尝试让真正的游戏在浏览器中快速运行,JavaScript会让你的生活变得很糟糕,在某些情况下JSIL会让它变得更糟。我唯一能说的好话是,我正在努力解决这个问题。 :)
  • 不支持JavaScript缩小器和优化器,如Closure,因为它们需要您的代码生成器跳过一堆障碍。根据您打算如何使用代码,我可以看到这可能成为一个真正的阻碍。
  • 静态分析器仍然有点脆弱,并且语言支持还存在漏洞。我使用JSIL移植的每个大型应用程序通常都会揭示JSIL中的一个或两个错误——不是巨大的游戏破坏者,但肯定会破坏功能或使事情变慢。
希望这些信息能够对您有所帮助!感谢您的关注。

12

Script# 优点:

  • 免费
  • 开源
  • 生成干净的 JavaScript 代码

Script# 缺点:

  • 只支持 C# 2.0 语言的一个子集
  • 只能在一个独立的项目中进行编译,无法在客户端和服务器之间混合/重复使用代码
  • 更新版本的频率较低
  • 不提供技术支持
  • 第三方库支持有限,C# API 与 JavaScript API 不同
  • 不是开源的
  • 只支持 JavaScript 的调试

SharpKit 优点:

  • 商业产品
  • 支持完整的 C# 4.0 语言
  • 更新版本的频率较高
  • 提供技术支持
  • 可以在同一项目中混合和重复使用客户端/服务器代码
  • 广泛的第三方库支持,作为开源项目维护 - C# API 与 JavaScript API 完全相匹配
  • 支持 Chrome 浏览器的基本 C# 调试
  • 生成干净的 JavaScript 代码

SharpKit 缺点:

  • 有一个免费版本,没有时间限制,但仅适用于小型/开源项目
  • 不是开源的(只有库是开源的)

JSIL 优点:

  • 免费
  • 开源

JSIL 缺点:

  • 转换自 IL(中间语言),而不是 C#,这意味着代码已经处于较低的抽象层级。
  • 生成的 JavaScript 代码复杂 - 几乎像 IL,难以阅读和调试

反馈答案:

Kevin:JSIL 的输出并不糟糕,它只是为了实现完整的 .NET 行为而生成的,就像 SharpKit 的 CLR 模式一样。另一方面,SharpKit 支持本地代码生成,可以从 C# 生成任何本地 JavaScript 代码,就像手写一样。

SharpKit的干净生成的JavaScript代码示例:

http://sharpkit.net/Wiki/Using_SharpKit.wiki

开发人员可以选择创建更复杂的代码生成并获得更多功能,例如支持编译时方法重载。当指定时,SharpKit会为重载的方法生成方法后缀。

Script#需要.NET 4才能运行,但它不支持完整的C# 4.0语法,例如泛型、ref和out参数、命名空间别名等。


1
感谢您的总结。需要注意的是,Script#现在是开源的,并且有4.0版本。 - Kyle
你有JSIL生成错误输出的示例吗?我所知道的唯一情况是枚举器函数,这在JavaScript中通常无法实现,或者使用goto。 - Katelyn Gadd
1
另外,能够看到SharpKit代码质量的示例也是很好的。他们的网站上没有这样的示例,而他们链接到的演示中充满了像这样的噪音: function CodeRun$WebStudio$ApplicationModel$Session$SaveStateBeforeLogin(newUsername) { return this.__interceptor.ForceIntercept(this, "CodeRun.WebStudio", "CodeRun.WebStudio.ApplicationModel.Session", "SaveStateBeforeLogin", arguments); } - Katelyn Gadd
人们有不同的原因想要这个。例如,我完全不感兴趣将现有的工作C#代码转移到JavaScript上。我只想使用C#作为一种语言来针对本地JavaScript。有多种原因,但主要是我想使用C#中更好的重构支持(ReSharper),而JavaScript则无法进行重构。我不打算针对.NET Framework编码,而是针对DOM和其他JavaScript库进行编码。我只希望源代码是用C#编写的。为此,SharpKit胜出,而JSIL甚至不需要成为目标。 - zumalifeguard

8
另一种选择是WootzJs。 需要注意的是,我是它的作者。
WootzJs是开源的,并力求成为一个相当轻量级的交叉编译器,允许使用所有主要的C#语言特性。
支持的值得注意的语言特性包括:
- yield语句(生成一个高效的状态机) - async/await方法(生成类似于C#编译器的状态机) - ref和out参数 - 表达式树 - lambdas和委托(带有适当的捕获this) - 编译器和运行时都支持泛型(无效的强制转换到T将抛出强制转换异常) - 对于封闭变量,采用C#语义(而不是Javascript语义)
它使用Roslyn实现,这意味着它将首先利用未来的语言改进,因为那些改进将通过Roslyn本身实现。 它提供了一个自定义版本的mscorlib,所以您可以确切地知道在脚本中实际可用的库功能。
它的缺点是:
- 生成的Javascript不打算看起来“漂亮”。 它显然是机器生成的,但通过查看它们,单个方法应该很容易理解。 - 由于对核心库和反射的广泛支持,生成的输出不是最小的。缩小应该会产生一个大约100k的JS文件,但目前还不支持缩小。 - WootzJs毫不掩饰地使用函数污染本地类型,以封装仅在C#中才能找到的这些类型的行为。例如,所有System.String的方法都添加到本机Javascript String类型中。 - 目前很少支持绑定到第三方Javascript库。(目前仅支持jQuery)
与其他交叉编译器相比,WootzJs有以下特点:
  • Script#非常稳定,并且与第三方JavaScript库有广泛的集成。此外,它具有出色的Visual Studio集成,并提供mscorlib的自定义实现。这意味着您可以精确地知道在工具级别上实际实现了哪些功能。例如,如果未实现Console.Write(),则该方法将不可用于您的编辑器。

    但是,由于其自定义解析器,它仍然停留在C# 2.0(甚至没有该版本中找到的泛型)。这意味着现代C#开发人员正在放弃一个我们大多数人毫不犹豫地依赖的巨大的语言功能集,特别是前面提到的泛型以及lambda和LINQ。这使得Script#对许多开发人员来说基本上是无法启动的。

  • JSIL是一项非常令人印象深刻的工作,可以将IL交叉编译为JavaScript。它非常强大,可以轻松处理跨平台的大型3D视频游戏的交叉编译。缺点是,由于其完整性,生成的JavaScript文件非常庞大。如果只想要mscorlib.dll和System.dll,则需要下载约50MB。此外,该项目实际上并不是为在Web应用程序的上下文中使用而设计的,因此启动所需的工作量有点令人生畏。

    这个工具包也实现了自定义mscorlib,再次允许您知道可用的功能。但是,它的Visual Studio集成较差,强制您创建所有必要的自定义构建步骤来调用编译器并将输出复制到所需的位置。

  • SharpKit:这个商业产品致力于提供对大多数C# 4.0语言功能的支持。它通常能够成功,并且有很大的机会满足您的需求。它体积小(小型.JS文件),支持现代C#语言功能(泛型、LINQ等),通常可靠。它还有大量绑定第三方JavaScript库的功能。但是,您不可避免地会遇到一些不受支持的边缘情况。

    例如,类型系统是浅层的,不支持表示泛型或数组(即typeof(Foo[]) == typeof(Bar[])typeof(List<string>) == typeof(List<int>))。反射的支持有限,各种成员类型无法支持属性。表达式树支持不存在,并且yield实现效率低下(无状态机)。此外,没有自定义mscorlib,并且脚本C#文件和普通C#文件在项目中交织在一起,因此您必须使用[JsType]属性装饰每个脚本文件以将其与正常编译的类区分开来。


很棒的工作,继续努力!如果我没记错的话,这是迄今为止唯一基于Roslyn的js编译器。 - VibeeshanRC

5
我们使用SharpKit已经有两年了,我必须说它升级了我们编写代码的方式。我认为它的优点有:
  • 代码更加结构化 - 我们现在可以像在C#中一样开发基础架构,而不需要使用原型。
  • 很容易进行重构
  • 我们可以使用代码片段,这会提高生产力并减少开发时间
  • 您可以控制JS呈现的方式(您可以选择几种模式)。
  • 我们可以在浏览器中调试C#代码(目前仅支持Chrome,但仍然是一个优点)
  • 提供了很好的支持!如果您发送查询,您会很快得到回复。
  • 支持大量库和易于扩展

缺点:

  • 文档有些匮乏,不过一旦熟悉起来,您将提高开发效率。

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接