OSX 上初步尝试 asp.net 5

去年微软最令开源界振奋的消息就是 ASP.NET 的开放与开源这一消息了。

根据微软的介绍,与我之前的一些总结,可以看到 ASP.NET 以及 .NET 平台会有下面几个变化:

  • 代码使用 Apache 协议开源,并且托管于 Github 上。
  • 新的 C# 编译器 Roslyn
  • 一个新的跨平台的 CLR(对应 Java 平台的 JVM)。
  • 新的项目组织与构建工具KVM
  • 基础库 corefx

这些概念都有点让人觉得云深雾绕,仔细研究就会发现,其实 ASP.NET 借鉴了大量 node.js 与 Ruby 社区的概念与架构。对应如下:

KVM

对应 Ruby 社区的 RVM,与 node.js 社区的 NVM / N。可以管理你的 ASP.NET 的执行环境(CLR),比如指定使用 coreclr 还是 mono,以及它们的具体版本。使用上也很像。

KPM

对应 Ruby 社区的 gem,与 node.js 社区的 npm。可以管理你的第三方包依赖。但是实际实现上,还是复用先用的 NuGet,包也是 NuGet 的包。但是不同的是,使用了 Project.json 文件格式作为依赖声明,并且也会自动帮你管理循环依赖。这个简直就是直接把 npm 借鉴了一遍,格式都很像。

coreclr

一个新的精简版跨平台的 CLR,(据说继承自 silverlight?),使用 C++ 实现,并且十分精简(只有几 M 大小),因此可以直接在 Project.json 里面指定使用哪个版本,构建的时候直接在线下载。当然大家一直关心的 mono 也在这里找到了自己的角色,你也可以选用 mono 作为执行环境(现阶段 coreclr 还没有 production ready,mono是比较好的选择)。当然你也可以使用传统的 CLR 来作为运行时(现在称为 full .NET CLR)。

Roslyn

使用 C# 写的 C# 编译器,更加开放和组件化,主要是帮你编译你写的代码以及第三方依赖的代码。并且目测会在代码补全和代码重构方面发力,因为微软并没有打算把 Virtual Studio 给 Linux 和 OSX 用户用,C# 这种静态类型语言毕竟还是比较依赖代码补齐的。

corefx

coreclr 只是一个 CLR,C# 中字符串等基本的功能还是使用 C# 编写的,还有很多其它的基础库,这部分代码就作为 corefx 存在了,并且绝大部分代码都是跨平台的。其中包括 IO,线程,Linq,集合等等一系列类库。这样不管你的代码是运行在 coreclr 还是 mono 环境中,兼容性都会有一定的保证。

kestrel

微软也没打算把 IIS 跨平台到 Linux 和 OSX,因此有了 kestrel 这个 HTTP Server,基于 libuv。说是给开发环境用,但是估计以后也能达到线上服务的强度。


以上概念虽然多,但是 asp.net 5 安装和使用起来并不复杂,只要安装好 KVM 这一个工具就好了。

KVM 的项目是 https://github.com/aspnet/Home (这个项目名字真的有点让人摸不着头脑,直接叫 KVM 或者 K 不就好了),实际上就是几个 shell 脚本(bash / powershell)。

以下内容基于 KVM beta3

OSX 下直接用 homebrew 安装就好,微软已经做好了brew tap,以后正式 release 应该会提交给 homebrew。

brew tap aspnet/k  
brew install kvm  

安装时会有个 postinstall 的过程,自动帮你执行了 kvm upgrade,ASP.NET 相关文件很 Unix 地帮你放在了 ${HOME}/.k/ 目录下,并且自动使用 mono 作为 runtime:

tree ~/.k  
/Users/asaka/.k
├── alias
│   └── default.alias
└── runtimes
    └── kre-mono.1.0.0-beta3
        ├── bin
        │   ├── Microsoft.CodeAnalysis.CSharp.Desktop.dll
        │   ├── Microsoft.CodeAnalysis.CSharp.dll
        │   ├── Microsoft.CodeAnalysis.Desktop.dll
        │   ├── Microsoft.CodeAnalysis.dll
        │   ├── Microsoft.Framework.ApplicationHost.dll
        │   ├── Microsoft.Framework.Runtime.Loader.dll
        │   ├── Microsoft.Framework.Runtime.Roslyn.Common.dll
        │   ├── Microsoft.Framework.Runtime.Roslyn.dll
        │   ├── Microsoft.Framework.Runtime.dll
        │   ├── Microsoft.Net.Http.Client.dll
        │   ├── Newtonsoft.Json.dll
        │   ├── System.Collections.Immutable.dll
        │   ├── System.Reflection.Metadata.dll
        │   ├── k
        │   ├── klr
        │   ├── kpm
        │   ├── kre.host.dll
        │   ├── kre.mono.managed.dll
        │   └── lib
        │       ├── Microsoft.Framework.DesignTimeHost
        │       │   └── Microsoft.Framework.DesignTimeHost.dll
        │       ├── Microsoft.Framework.PackageManager
        │       │   └── Microsoft.Framework.PackageManager.dll
        │       └── Microsoft.Framework.Project
        │           └── Microsoft.Framework.Project.dll
        ├── kre-mono.nuspec
        └── package
            └── services
                └── metadata
                    └── core-properties
                        └── 5d2fd91bec5d411ca81c8c3df4d03749.psmdcp

12 directories, 24 files  

有一点很不 Unix 的就是,kvm 实现成了一个 shell 函数,而不是一个可执行文件,因此你每次使用的时候都要 source kvm.sh 一下(貌似 rvm 也是这样?)。可以在 .zshrc 一类的地方干这件事。

然后 kvm install 可以安装其他版本的 runtime,也会装到 ${HOME}/.k/ 目录下。kvm use 可以选择某个 runtime 作为当前 runtime。还有一系列 upgrade alias的命令,和 rvm/nvm 差不多。roslyn 也包括在 kvm runtime 之中,不过没有可执行文件来直接启动。

kvm 安装的 runtime 里面也包含 kpm、klr 和 k 三个命令行工具。klr 实际上是当前的 CLR,这里其实就是启动了 mono。kpm 其实是 NuGet,k 类似于构建工具,帮你设置好环境变量,编译代码,并且帮你启动你的代码。

刚才 KVM 的那个 repo 里面还有几个 sample,可以 clone 下来自己跑着玩。不过目前在默认 runtime 之下,除了 ConsoleApp 之外我这里都跑不起来,估计是很久没维护,依赖出了问题什么的。

跑项目的时候,需要使用 kpm restore 一下安装依赖。对于 ConsoleApp 类的项目,直接 k run 就可以运行你的代码,就是直接编译好了之久运行 Main 函数。

web 类的项目,需要使用 k web 来使用内置的 HTTP Server 运行。但是 sample 的那几个例子都跑不通。这里还使用 k kestrel 来启动 kerstrel 跑。


仔细观察就可以发现,现在如果写一个命令行工具,那只要写好 Project.json 来指定相关依赖,就可以任意想以自己的方式来组织代码了。但是对于 asp.net 项目,或者其他类似的项目,虽然现在已经没有了 web.config ,但是凭空去手敲出来一个项目框架还是很繁琐的。asp.net 中增加 Controller 一类的工作也是很繁琐的,之前 Virtual Studio 可以帮助我们做这些工作。

所以我们需要一个脚手架工具,这个在 rails 有比较完美的解决方案,rails 本身就可以帮我们做这些事情。后来 node.js 社区的 yo 项目把这个功能借鉴了去,可以生成各种前端以及 node.js 项目,并且 yo 也一直没有限定自己只在前端和 JS 社区,本身可以通过写新的 generator 来支持各种类型的项目。

因此就有了 generator-aspnet 这个项目。这个项目属于 OminiSharp 组织,非微软官方,但是发起人确实微软官方,所以你知道我在说什么。

装上 yo 和 generator-aspnet 就可以很方便的生成 asp.net 以及使用各种脚手架功能了。

npm install -g yo  
npm install -g generator-aspnet  

尝试一下:

yo aspnet

     _-----_
    |       |    .--------------------------.
    |--(o)--|    |      Welcome to the      |
   `---------´   |   marvellous ASP.NET 5   |
    ( _´U`_ )    |        generator!        |
    /___A___\    '--------------------------'
     |  ~  |
   __'.___.'__
 ´   `  |° ´ Y `

? What type of application do you want to create? (Use arrow keys)
❯ Empty Application
  Console Application
  Web Application
  Web API Application
  Nancy ASP.NET Application
  Class Library

现在支持的项目类型也比较完善,甚至还支持 Nancy 这个很像 sinatra 和 express 的轻量级 .net web 框架。

项目创建完成之后,可以进入项目根目录,如果是 Web Application(也就是以前的 MVC 框架),这样运行(restore之前最好先用 npm 装上 bower 和 grunt-cli,yo 生成出来的项目是依赖这两个来构建前端的,restore 过程中会执行构建过程):

kpm restore  
kpm build  
k kestrel  

当然不知为何,我这里用k kestrelk web 都跑不起来,应该还是因为 Beta 的原因吧。不过可以观察一下项目目录结构,发现构建前端的 grunt 和 bower 都已经配置好了,并且默认启用 Razer 做模板引擎,也使用了 Entity Framework 作为 ORM 框架,十分完善。

另外看 generator-aspnet 的文档,有如下脚手架:

aspnet:MvcController  
aspnet:MvcView  
aspnet:WebApiContoller  
aspnet:Class  
aspnet:StartupClass  
aspnet:BowerJson  
aspnet:CoffeeScript  
aspnet:Config  
aspnet:Gulpfile  
aspnet:HTMLPage  
aspnet:JavaScript  
aspnet:JScript  
aspnet:JSON  
aspnet:PackageJson  
aspnet:TextFile  
aspnet:TypeScript  

很好很强大。


Updated:

微软改名部后来可能觉得 KVM 等名字不太妥,把命令重名名为 DNxxx 了,比如 dnvm 以及 dnx

后来过了很久,微软改名部觉得这套工具链有点复杂,于是推出了全新的 dotnet 工具,有点类似 clojure 社区的 leiningen 以及 haskell 社区的 stack。相当于上面介绍的绝大部分工具的整合,可以通过单个命令管理依赖的语言版本,运行时版本,第三方依赖以及版本,还有创建项目的脚手架。这里就不细说了。