javascriptservicestacksingle-page-applicationbundling-and-minificationcassette

Serving bundled JavaScript with a pure AppHost implementation of ServiceStack


I would like to use ServiceStack as a pure AppHost implementation without using MVC. I want to use it to drive a Single Page App.

Serving the SPA's single HTML shell page is straightforward enough and I've found plenty of examples on doing that. However, I also need to serve a number of JavaScript files and I'm assessing the best way of doing this. I can simply put script tags in the HTML shell page but then I don't get the benefits of bundling and minification, and I would have to maintain this every time I add a new JavaScript file.

All these problems are solved with bundling solutions such as Cassette or ASP.NET MVC4 Bundles. But how would I use these with ServiceStack AppHost?

The ServiceStack.Bundler project is great but it seems to have dependencies on ASP.NET MVC, e.g. as a base for the HTML Helpers which render the JavaScript tags in the HTML.

I'd like to be able to do this without any dependency on MVC, if possible.


Solution

  • It seems neither Cassette nor Microsoft.AspNet.Web.Optimization (the bundling solution included with MVC4 projects by default) have dependencies on ASP.NET MVC. Therefore either solution can be made to work with an AppHost implementation of ServiceStack.

    For Cassette:

    It all works just fine if, from NuGet, you install:

    ServiceStack.Host.AspNet

    ServiceStack.Razor

    Cassette.Aspnet

    ... and then use Cassette from a Razor 'cshtml' file as usual.

    One small gotcha which did cause me to scratch my head for a few minutes:

    The order in which the HttpHandlers are listed in your web.config is important. The ServiceStack.Host.AspNet package adds an HttpHandler path which uses a wildcard meaning any further HttpHandlers, such as that for Cassette.axd, are never reached.

    Simply changing the order in my web.config from:

    <httpHandlers>
      <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
      <add path="cassette.axd" verb="*" type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet" />
    </httpHandlers>
    

    to:

    <httpHandlers>
      <add path="cassette.axd" verb="*" type="Cassette.Aspnet.CassetteHttpHandler, Cassette.Aspnet" />
      <add path="*" type="ServiceStack.WebHost.Endpoints.ServiceStackHttpHandlerFactory, ServiceStack" verb="*" />
    </httpHandlers>
    

    fixed the problem. I don't know if installing Cassette.Aspnet from Nuget first would have prevented this issue from occurring in the first place.

    For Microsoft.AspNet.Web.Optimization:

    From NuGet, you install:

    ServiceStack.Host.AspNet

    ServiceStack.Razor

    Microsoft.AspNet.Web.Optimization

    Having done this, you can use Microsoft.AspNet.Web.Optimization bundling and minification as normal.

    I added a BundleConfig.cs file, followng the convention you'd find in a default MVC4 project. I then call BundleConfig.RegisterBundles(BundleTable.Bundles); from the ServiceStack AppHost file.

    Thereafter, all @Scripts.Render() statements in Razor files work just fine.