Front end development - Vue, Webpack and ASP.NET core 2.0

· by Raghu Rajagopalan · Read in about 6 min · (1153 words) ·

So the last week I have been delving into Vue.js. This wasn’t exactly intentional - with .NET core 2.0 being released, I wanted to give it a run and decided to start with one of the starter templates. I’ve been reading quite a bit of nice things about Vue so decided to create a project based on the Vue SPA template.

It’s also been a long while since I have done any sizable front end work so it was also a way to see what has changed in the forever in flux, a new framework everyday javascript land. To give you an idea, the last time around I’d worked on a sizable app was on a SPA website using Knockout with a myriad of other libraries including an event bus. It came out pretty nicely had had some pretty nice features - vendor and app minified bundles, cache busting, a minimalistic base app that dynamically loaded JS bundles when different areas of the app were activated and so on - but each of these were hand built as grunt tasks.

We also used React after this - circa 2015 - and while we had good results, the app complexity itself was much lesser in comparison though the dev experience was much better than with Knockout. In any case, given Vue’s component model and single file components, it seemed like a fun exercise.

Getting started

Getting off the ground was simple. Detailed instructions are here, but basically you

  1. Install the SPA templates

    dotnet new --install Microsoft.AspNetCore.SpaTemplates::*
  2. now if you run dotnet new you should see a bunch of SPA templates

    SPA templates
  3. Start a new project with Vuejs as your front end framework with dotnet new vue

This generates a ASP.NET Core 2 project with Typescript, Webpack and hot module reload all configured. The front end build of TS files into bundles is also integrated into the .NET project build by virtue of a Microsoft.AspNetCore.SpaServices middleware which automatically invokes webpack during builds. If you’re like me, while I appreciate templates that help me get off the ground quickly, I also don’t like them if there’s too much magical stuff happening. I like to see and know what’s happening under the covers. Generally MS templates are pretty opinionated about stuff and have too much magic going on - but this time it’s been a pleasant surprise as the

  1. templates are straightforward,

  2. Don’t try to reinvent the wheel,

  3. You can tinker with their initial setup as much as you want to make it work to your needs.

In any case, if you now run the app, you should see a nice SPA app at localhost:5000. If you need a detailed run-down of everything that happens behind the scenes, I recommend going through this post

The template was super helpful - as I had no clue about configuring webpack, haven’t worked on typescript or vue and basically, this was as good as looking at modern front end development for the first time around. But having a running app lets you start tinkering around and making small changes and seeing how things go.

Learning to walk

Vue’s documentation is first class and I spent some time learning concepts. Then it was over to learning typescript and ES5 and ES6 and various module systems, Vue, Vue router and babel and a bajillion more things  — all essentially leading to a brain freeze :)

However, I was able to get a few simple components added that did nothing beyond display text or render their props and so on - but it was invaluable to be able to make some changes and see them rendered. I also came to appreciate Hot module reload (note - this is still in hte magical zone for me - have to read their documentation more thoroughly to understand how they go about it.)

Tweaking

Importing .vue.html components

Things were hunky dory till I ran into an issue where I wanted a component to import another component defined in a .vue.html file. The template uses awesome-typescript-loader. This sent me down the path of figuring out webpack and loader configurations. I also came upon the other loader - ts-loader. Interestingly, ts-loader has an option called appendTsSuffixTo which lets the loader treat other file types as TS. This is exactly what I needed and it doesn’t look like awesome-typescript-loader has this feature as indicated by this issue

So - time to give ATL the boot and bring back Ts-Loader. This was pretty straightforward and after this, I was able to import a vue component into another one even if defined in a .vue.html file.

Code splitting

Code splitting basically dividing up your js files into multiple bundles to reduce initial payload. After that if you activate a UI element that needs some more JS, the webpack loader shim takes care of downloading the additional js chunk dynamically. Pair this with Vue’s async component feature and you have a powerful way of building large js apps.

Having rolled this out by hand in the knockout world and having had to jump through quite a few hoops before I could get this done, I was very interested in trying this out.

In any case, since we’re using typescript, defining an async component with the dynamic import statement doesn’t work - this is because the project template uses Typescript 2.3 while dynamic import only made it in TS 2.4. I updated NPM dependencies in package.json to the latest and after that dynamic import works as advertised.

Bundling multiple components into a single chunk - Named chunks.

However, I ran into another problem - now each component became it’s own chunk. Instead, I wanted to bundle multiple components into a single chunk. Turns out that this doesn’t seem possible yet with the import statement as this translates to a require call (and not a require.ensure call which takes a chunk name ). I’ve logged a ticket with the ts-loader repository here

So, if you want to put multiple components into a named chunk, your best bet is to stick to require.ensure and pass in a chunk name

By transpiling TS to ES2015 as target and using babel-loader to convert the ES2015 to ES5, you can use the dynamic import syntax.

// Module A
export default  {
    components: {
        'slot-comp': () => import(/* webpackChunkName: "comps" */"./slot-comp.vue")
    }
}

// Module B
    // ... component declaration elided
    components: {
        "todo-item": () => import(/* webpackChunkName: "comps" */ "./todo-item.vue")
    }

// Now the todo-item and the slot-comp component will both end up in named
// chunk called comps

Summing up

Once you get past the initial hurdles, getting productive is quick and solving through each problem is exactly what’s required to get a hang of the ecosystem and the tools and frameworks. I’ve thrown up the code on github here.

For now, I’ve had my fill of front end dev and am heading back to delving into .NET core.