Showing posts with label vue. Show all posts
Showing posts with label vue. Show all posts

Saturday, June 23, 2018

Scaffolding a new Vue.js component

I've been working for the past few months on a travel portal rewriting parts of it from old jQuery code to Vue.js - and learning a lot of stuff in the process. One thing that I learned the hard way is that scaffolding that's built in into Vetur is just not for me. It is too simple.

The naming convention we have for our component files is for them to have the same name as the file they exist in. So basically TestMe.vue becomes

<template>
  <div class="test-me">
    ...content
  </div>
</template>

<script>
import Vue from 'vue'
import Component from 'component'

@Component({})
export default class TestMe extends Vue {
}
</script>

<style lang="scss" scoped>
.test-me {
}
</style>

Makes sense?

The problem is that having to type this in every time I create a new component (and the number of those grows like creazy!) is tedious. So I finally got to it and created a snipped that works for me:

That's it! You type "sfc", press [Tab] and the component is ready to be worked on by magic of the VS Code templating engine.

The first thing that'll be edited is the name of the exported class. If it is OK then just press [Tab] to move to the name of the CSS class. Edit it if you must then press [Tab] again and you'll be able to select the processor for styles. The next thing that you get to customize is if the styles should be scoped. Once on it either press [Tab] to go with scoped styles or [Delete] and then [Tab] to go without scoped styles. Finally you arrive at the Hello, world! text where the editing of your component begins.

Have a nice day!

Saturday, June 16, 2018

Vue.js - editor components

When talking about creating applications in Vue.js it is not hard to find one that does something to data. Obviously for state management there's Vuex, Redux and other stores but in this post we're going to focus strictly on passing state via props to components that one could generally call controls - so more on the lines of custom inputs.

The 3 cases

There are 3 cases that we will encounter when passing data down to controls:

  • We're passing in primitive values (strings, numbers, booleans)
  • We're passing in complex reactive objects (think: list of people)
  • We're passing in a complex reactive object but we'd like to treat it as a primitive and have atomic changes to all its fields

Primitives

In the case of primitives the situation is dead simple: use v-model, you can react to changes by hooking up to the input event - done. The documentation is fantastic in that area so if you'd like to know more about it dig in!

Reactive complex objects

Imagine you have a data structure like this:

data = { firstName: 'John', lastName: 'Doe' }

In this case if you create a control (we'll call it DataEdit.vue) that you'd like to immediately edit the fields you could do something like that:

<template>
  <div>
    <input v-model="value.firstName">
    <input v-model="value.lastName">
  </div>
</template>

<script>
export default {
  props: {
    value: Object
  }
}
</script>

This means that if used in a parent component (ContactForm.vue) like so:

<template>
  <div>
    <h1>{{ person.firstName }} - {{ person.lastName }}</h1>
    <DataEdit :value="person" />
  </div>
</template>

<script>
import DataEdit from './DataEdit.vue'

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: 'John', lastName: 'Doe' }
    }
  }
}
</script>

then changes to values in inputs in DataEdit.vue component will immediately be reflected in ContactForm.vue. Vue's reactive system at its best.

Treating complex objects like a value

This is the trickiest one because even though we're passing on a complex, reactive object we'd like to get all the changes at once or none at all. You might ask why would you want such a thing? The answer is quite simple: you'd like to implement "OK/Cancel" functionality or (if the edits drive some kind of Ajax requests) limit the number of actions upon edits. It is quite obvious that there will be a need for a copy of the reactive object. For that I use cloneDeep method from Lodash and it works just great so far.

<template>
  <div>
    <input v-model="internal.firstName">
    <input v-model="internal.lastName">
    <button @click="$emit('input', internal)>Save</button>
  </div>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep'

export default {
  props: {
    value: Object
  },
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
</script>

Now if that component is used in the ContactForm.vue (note the change from :value to v-model)

<template>
  <div>
    <h1>{{ person.firstName }} - {{ person.lastName }}</h1>
    <DataEdit v-model="person" @input="personUpdated" />
  </div>
</template>

<script>
import DataEdit from './DataEdit.vue'

export default {
  components: {
    DataEdit
  },
  data() {
    return {
      person: { firstName: 'John', lastName: 'Doe' }
    }
  },
  methods: {
    personUpdated(newValue) {
      console.log('Person has been updated to: ', newValue)
    }
  }
}
</script>

you won't see any changes to the header until they are saved by clicking the Save button. Pretty neat, right? On top of that you can be notified when the change occurred so if some additional action needs to take place (like updating list of people from an external database) by listening to the input event. That is just pure awesome!

One more thing...

If the editor persists it will now share the internal and value objects which will make it behave like the case where everything is reactive. Not good - let's do something about it

<template>
  <div>
    <input v-model="internal.firstName">
    <input v-model="internal.lastName">
    <button @click="$emit('input', internal)">Save</button>
  </div>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep'

export default {
  props: {
    value: Object
  },
  watch: {
    value: {
      handler (newValue) {
        this.internal = cloneDeep(newValue)
      },
      deep: true
    },
  },
  data () {
    return {
      internal: cloneDeep(this.value)
    }
  }
}
</script>

The introduced watch updates the internal state so that it is again disconnected from the ContactForm.vue. Of course in a situation where the DataEdit.vue component is removed from DOM due to let's say closing a popup then the watch is completely unnecessary. It does however come in handy if there might be a possibility that the data object in question (or some of its parts) can be modified from the parent component. The internal state will be out of sync in such case. This might happen if some of the details come from an Ajax request or a timer. The watch covers both cases so it is basically a universal way for data synchronization on changes from parent component.

Working example

I know this is a lot to take in at once. Therefore I have prepared a test application for you that illustrates all the pieces. You can find it at https://github.com/padcom/vue-editor-components

That's it, folks!

Monday, April 9, 2018

Vue.js and functional single file components

Single file components (SFC) is probably the most powerful feature (structure-wise) in Vue.js. They are simple in nature but very powerful when it comes to bundling things together:

<template>
  <h1 class="my-header>Hello!</h1>
</template>

<script>
export default {
}
</script>

<style>
.my-header {
  color: red;
}
</style>

There are times when you want your component to be stateless. Such components are great for bundling together functionality that would otherwise be created by putting together other components. I call them template components, because they are predefined with places where you can override the defaults. Those components do not have state hence we call them stateless or functional.

The problem with SFCs is that unlike regular .vue components they don't pass data down. Especially the class and style properties are not passed automatically. To mitigate that I went through a few iterations to find the nicest solution. Here's what I came up with that seems to do the job very well. Let's assume we're creating a predefined component for animation. We want the styles to be bundled with the component so SFC is the right way to go.

<script>
export default {
  functional: true,
  render: (h, { data, children }) => (
    <transition-group { ...data } tag="ul" name="slide">
      { children }
    </transition-group>
  )
}
</script>

<style>
.slide-move {
  transition: transform 1s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
</style>

A quick explanation: { data, children } is a destructing assignment from the second parameter to 2 fields that we'll use later. Then the { ...data } means "apply all elements passed on (including but not limited to class and style).

That's all there is to it.

Thursday, December 7, 2017

POI and naming classes in CSS Modules

This will be a quick one. If you're trying to use CSS modules with POI in a Vue.js app and you want to exercise some control over what the names of the generated classes are then there is a configuration option in POI for that. It's a little bit hidden so it took mi like 5 minutes to figure it out - hence the post.

module.exports = {
  vue: {
    cssModules: {
      localIdentName: '[hash:base64:5]'
    }
  }
}

That weirdness stems from the fact that POI configures the css-loader indirectly via the vue when setting up the vue-loader. We can take advantage of the fact that it uses the Object.assign method and sneak in our configuration option.

Happy coding!

Saturday, November 25, 2017

Vue.js - the jQuery killer

Vue.js is awesome. It really is. There is however this notion that frameworks such as Angular or React are primarily for full-fledged, single-page frontend applications and that notion carries over to Vue. In this installment I am going to try to share with you a way to treat Vue as a better jQuery and to have more than a few micro-apps on one page.

The jQuery phenomena

There are more than a few reasons why jQuery became so popular. One of them was the need to target multiple browsers with one, coherent codebase. I think that this is exactly why there are so many jQuery developers out there and so few people (by comparison) that can actually use JavaScript and the DOM API. Fortunately enough, the browser wars led to standards being formed and implemented by most major browsers and now things like searching for elements in the DOM tree or toggling a class is not a challenge anymore. Let's face it: even Ajax (the biggest example of fallout from browser wars) is standardized these days! And I am not talking here about the XMLHttpRequest class but about the fetch API which makes jQuery pretty much useless.

Welcome to the 21st century

So where do frameworks like React, Angular or Vue fit in this new, jQuery-free world? Is there even a place for them? Well, as it turns out 2 things have changed over the past decade: not only browsers became more standardized but also the applications became way more demanding. It's not just a few plugins bashed together like it used to be back in the days. Now we see browsers as an operating system / development platform of its own that can target multiple hardware and deliver experiences (not "pages") wherever we go. That's the price to pay for being cool :)

For that reason the size of a codebase that use jQuery alone grows out of proportion trying to synchronize the state of multiple deeply nested components. This is not what jQuery was designed for and it's also where the scaling capabilities of it end. We need something that will match the new requirements. And so along came a long list of failures in the industry trying to solve the misery of big apps. At first it looked like the MVC pattern (so popular in the backend world) would be a good fit. I think the main reason was the overwhelming presence of design patterns in the late 2000s. And MVC was (along with Singleton) among the most recognized ones. Even good frameworks like ExtJS went to the dark side and implemented the MVC pattern. Such a shame!!!

That didn't solve the scaling problem. Apps were growing out of proportion of what was feasible at that time. It wasn't until about 2013 when Facebook's engineer Jordan Walke came up with this idea of shedding MVC in the frontend all together and replacing the ever growing connections between UI and data with mathematical precision and unidirectional data flow that we all now take for granted.

The framework problem

As it turns out the problem with frameworks is that they take control from you and let you react only when something happens. This is mostly great but sometimes it means global state needs to be maintained to gain access to the underlying data. React does away with this by embedding the state directly in components. This was, in my opinion, the biggest step forward after the definition of unidirectional data flow. However, with React came JSX (to make our life easier) and that came with Babel pre-processor or TypeScript and other goodness like webpack, gulp, grunt to be the main driver for the build process. In short: the build process became mandatory. Something you have never had to talk about when doing just jQuery. To make matter even more interesting now that we had the app it was usually so heavy (take angular 2 hello app built with the daemonic spin-off form Ember CLI) that having more than one app was virtually technically impossible.

To even approach the level of reusability jQuery provides we would need to get into the realm of tens or hundreds of apps on one page! That feels right down insane but if you come to think of it, it really opens up possibilities where previously only jQuery would fit.

The Vue

Such is the case with Vue.js. It is a small library (not necessarily a framework) that doesn't require any build steps, runs directly from the browser but if required it can grow to gigantic proportions by the share virtue of composition of components. Yes, that is right, if used with the component mindset it will easily grow beyond what was possible with jQuery (or plain old JavaScript for that matter). But it can do small bits as well! And it does it with such a grace it is absolutely stunning!

Let's see the simplest app that would run in the browser:

    new Vue({
      el: '#app',
      render: h => h({ template: '<h1>Hello, world!</h1>' })
    })

Assuming there is an element with id '#app' the app will replace that element with an H1 with the text Hello, world!. The el element doesn't need to be a CSS selector (if it would be it needs to point to one and only one element or the rest will be discarded). It can, however, be a DOM object, like so:

    new Vue({
      el: document.querySelector('#app'),
      render: h => h({ template: '<h1>Hello, world!</h1>' })
    })

Now assuming we would like to instantiate this application in every container with the class app applied we would need to do something that resembles this:

    [ ...document.querySelectorAll('.app') ].forEach(el => {
      new Vue({
        el,
        render: h => h({ template: '<h1>Hello, world!</h1>' })
      })
    })

Easy, right? Because the querySelectorApp returns an array-like object that doesn't provide the forEach method we're spreading that list over an array literal effectively creating a proper array from the list of found elements. Next, we apply the Vue application on each of the found placeholders. This is very much what jQuery was doing to us for all these years! Applying a transformation to all selected elements! Sure, it's true jQuery was less invasive (if there is anything present in the <div class="app">...</dic> Vue will go and nuke that content with its own content). But is it not like we would like to have less and less HTML managed by the backend (preferably just a placeholder for what is an app that is fully managed by the browser?

Of course the other question on the horizon is passing on information to those small apps. There is a few ways to do it (Ajax being one of them) that can help you here. My favorite is for the backend to use either a JavaScript object somewhere on the page that can be easily matched with the container. Other example (especially useful if there are just a few parameters you need to pass in) is to use the data-* attributes. Just don't go overboard with it!

Post mortem

I think that jQuery is one of the few frontend utilities that profoundly changed the way we think about software development. However the time is, finally, almost up because of the requirements new Internet applications. There is an obvious need for tools that solve problems that are not yet natively solved in the browsers in such a way that would be appropriate for the broad Internet developers audience. React and Vue are fitting nicely in that niche and do a fantastic job in being lean, focused. That gives the opportunity to do a lot more with Vue than was previously possible and to use those new tools in ways that would previously not even cross one's mind.

Happy coding

Wednesday, November 22, 2017

Writing unit tests with Vuejs and Poi

Poi is great. It's fantastic! It's one of the tools that were very much missing from the landscape. Now that we already have it let's explore what we can do with it. Let's get serious!

This time we're going to create a POI-based project that will support both Vue and unit testing.

First we need to have a project. A simple npm init will do. When asked to give the test command write poi test and you're done.

$ npm init
...
test command: poi test
...

Is this ok? (yes)

That was easy. Now let's install the required dependencies (there are quite a few of them but we'll go through the list and I will explain what each one does):

$ npm install --save-dev poi poi-preset-karma \
    webpack karma mocha chai karma-webpack karma-mocha karma-chai \
    vue vue-test-utils

poi is our build system so it is obvious it needs to be installed. poi-preset-karma is a preset for poi for it to know what to do when you execute poi test. It will use karma to run the tests.

webpack and karma-webpack allow to use webpack to bundle all the files

mocha is the testing framework giving you BDD-like tests with describe and it. karma-mocha is a package that allows easy integration of Karma and Mocha.

chai is a fantastic library for writing expectations. Similarly to Mocha, karma-chai makes it easy to integrate Karma with Chai.

And last but not least we top it with some Vue sauce. vue is our beloved frontend framework and vue-test-utils is a library that aids testing.

Let's write some tests

The default folder structure assumes unit tests to be located in test/unit folder and the files to be named like something.test.js. So let's create one:

test/unit/example.test.js

it('will pass', () => {
  expect(1).to.equal(1)
})

Easy, right? For Poi to know what to do when we run poi test we need to use a preset. To do that we'll create a poi.config.js file like so:

module.exports = {
  presets: [
    require('poi-preset-karma')({
      frameworks: [ 'mocha', 'chai' ]
    })
  ]
}

As you can see there we use Chai asserts. For Mocha to know about Chai we need to tell the Karma preset that both Mocha and Chai are to be used.

Now all that remains is to run the tests. There are 2 options for running:

  • Run just once and finish
  • Run continuously in the background and re-run tests when files change

To just run the tests and finish you issue the command

$ npm test

This works because test is a top-level npm command.

To run tests continuously with automatic re-running do this:

$ npm test -- --watch

Let's decipher the bits. npm test is pretty much obvious at this point. The double-dash is a way to tell npm hey, when you run the command specified in the scripts section then add all the parameters that follow to the execution. In our case the --watch parameter enables watching changes on files and automatic re-running of all the tests.

Poi and continuous integration server

Running tests in a real browser is great because they will be testing components in their natural habitat. It poses however a difficult problem when running them on a headless continuous integration server. This is a common problem and to address that Poi has a switch that uses ChromeHeadless instead of the regular Chrome:

$ npm test -- --headless

Of course you can combine them and run headless tests in watch mode on a remote machine via SSH using Vim or Emacs as your text editor - especially if your primary work computer is running Windows and you want things to go fast(er). The possibilities are endless.

Debugging

By default tests are being executed on Google Chrome. The page you'll see contains a little DEBUG button. When you click it a new tab will open where you can set breakpoints and examine your code. One thing to note is that by default there is a limit to how long one unit test can take (2s) and you will most likely exceed that limit if you pause in a test method. Don't be alarmed by that - just re-run your tests without breakpoints and you'll see if it works or not.

Please note that the tests in debug mode won't re-run by themselves when you change things in the sources. You need to refresh the page to start a new test run. This is done so that hot-module reloading doesn't kick in in the middle of your debug session. Very convenient!

Let's go Vueing

The time has come to make a real test that uses Vuejs. So let's create one in test/unit/components/Clicker.js that will check if upon clicking on the component a custom event will be emitted:

import Vue from 'vue'
import { mount } from 'vue-test-utils'

import Clicker from '@/components/Clicker.vue'

describe('Component: Clicker', () => {
  it('will emit "clicked" event when interacted with', () => {
    // given
    const wrapper = mount(Clicker)

    // when
    wrapper.vm.$el.click()

    // then
    expect(wrapper.emitted().clicked).to.deep.equal([ [ 'Here!' ] ])
  })
})

Now in the root folder let's create src/components and inside that let's create our component as a single-file component Clicker.vue:

<template>
  <h1 @click="$emit('clicked', 'Here!')">Hello!</h1>
</tempalte>

That's it! It is really that simple!

Post scriptum

This barely scratches the surface of what is possible with Poi but at the same time it does cover a lot of configuration that you don't need to write yourself. Just looking at the starter template for webpack-simple shows how much is being done behind the scenes.

Happy testing!

Saturday, October 28, 2017

Poi that!

You might already be familiar with Webpack. It's a great tool and a bastard when it comes to configuration. It's a beast! It's a daemon! It's one of those sons of bitches that you can't loose and that will hunt you down everywhere you go. Like a woman! Just look at the amount of configuration code that the vue-cli produces when used in combination with the webpack template. That is right down INSANE!!!

Although there's not much that can be done with woman, Webpack has received a shell that is finally making some sense! That shell is called POI and is created by a gentleman who goes by the name of Egoist. Let's take a closer look at what it does.

At first glance it is a simplified build tool. One that you would probably never look upon knowing what kind of power Webpack brings to the table. But if you look a bit closer it turns out it is just (easier said than done) a box around webpack configuring it to some standards using a set of predefined presets for the most common tasks. However, knowing what kind of a daemon sits in the guts of it, you'll be pleased to know that poking around that dragon is very much possible and easy at the same time.

So what does it look like to use it? First you need to know that Poi stems from the ashes of a slimming treatment of vue-cli. This means it will out-of-the-fricken-box work just perfect with Vue.js! All you need is a file that will bootstrap your application. Let's see the content of an index.js that does it.

import Vue from 'vue'
import App from './App.vue'

new Vue({
  el: '#app',
  render: h => h(App)
})

And then the single-file-component App.vue

<template>
  <h1>Hello, world!</h1>
</template>

You can obviously put everything else in there (the <script> and <style> sections for example).

Now let's see how do we actually use Poi with that nice application. First of all you need to install Poi. For the sake of this oversimplified and butt-ugly example we'll perform the worst voodoo magic ever and install Poi globally. But please, beyond demonstration purposes NEVER EVER EVER EVER DO THAT. EVER. Poi is your build system so it must be part of your project. You have been warned!

npm install -g poi

Now having index.js and App.vue in that same directory run the following command:

$ poi index.js

# some useless output here

                               Asset       Size  Chunks                    Chunk Names
abf8058814c81f7a160b.hot-update.json   44 bytes          [emitted]         
                           vendor.js     1.5 MB       0             [big]  vendor
                           client.js    13.6 kB       1                    client
                         manifest.js    31.2 kB       2  [emitted]         manifest
ff42074b3ef0f4f41971.hot-update.json   35 bytes          [emitted]         
                          index.html  578 bytes          [emitted]         

> Open http://localhost:4000
> On Your Network: http://127.0.0.1:4000

 DONE  Build 664748 finished in 141 ms!

That is it! Nothing more, nothing less! You have access to everything that you would expected: Hot module reloading, bundling app in separate files so that the part that actually changes is not the whole package, an index.html that is automatically generated for you to host your application - you name it!

There is much more to poi than just running the project. For example to be able to run unit tests you need to start using poi presets. That's not very hard - requires a few more packages though.

$ npm install poi-preset-karma karma-webpack karma-mocha karma-chai webpack mocha chai

With those packages installed we need to make Poi aware how to run tests. We do that by creating a poi.config.js like so:

module.exports = {
  presets: [
    require('poi-preset-karma')({
      frameworks: [ 'mocha', 'chai' ]
    })
  ]
}

That's really it! Nothing more! Just basically 4 lines telling that we would like to use karma with mocha and chai. Jeez! That is truly magnificent! Totally Vue.js-style! Now let's have the simplest test possible. All unit tests are to be stored in test/unit folder. This location can obviously be further configured but for now it will do just fine. So let's create test/unit/example.test.js like so:

import { expect } from 'chai'

it('will work', () => {
  expect(1).to.equal(1)
})

Having that in place let's run the tests!

$ poi test

# some useless output here

                    Asset    Size  Chunks                    Chunk Names
test/unit/example.test.js  925 kB       0  [emitted]  [big]  test/unit/example.test.js

 DONE  Build 78afa9 finished in 526 ms!

28 10 2017 13:22:30.310:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:5001/
28 10 2017 13:22:30.310:INFO [launcher]: Launching browser Chrome with unlimited concurrency
28 10 2017 13:22:30.314:INFO [launcher]: Starting browser Chrome
28 10 2017 13:22:30.892:INFO [Chrome 62.0.3202 (Linux 0.0.0)]: Connected on socket BUV....
  ✔ will work

Finished in 0.002 secs / 0 secs @ 13:22:31 GMT+0200 (CEST)

SUMMARY:
✔ 1 test completed

Now ain't that a pretty! I myself was looking to simplify the use of webpack for quite some time and it is only my bad luck that I didn't run into poi sooner. I would have saved a whole lot of time! Tumbling down the rabbit hole if you would like to run those tests in headless mode you can specify the browser to use. I like headless Chrome:

$ poi test --browsers ChromeHeadless

Boooom! Your tests can now be executed in headless environments like CI! That is so easy and soooo exciting!

Want to do some code coverage?

$ poi test --coverage

# some useless output here

                    Asset    Size  Chunks                    Chunk Names
test/unit/example.test.js  925 kB       0  [emitted]  [big]  test/unit/example.test.js

 DONE  Build 78afa9 finished in 508 ms!

28 10 2017 13:46:33.489:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:5001/
28 10 2017 13:46:33.489:INFO [launcher]: Launching browser ChromeHeadless with unlimited concurrency
28 10 2017 13:46:33.493:INFO [launcher]: Starting browser ChromeHeadless
28 10 2017 13:46:33.747:INFO [HeadlessChrome 0.0.0 (Linux 0.0.0)]: Connected on socket 9Xjcc...
  ✔ will work

Finished in 0.006 secs / 0.001 secs @ 13:46:33 GMT+0200 (CEST)

SUMMARY:
✔ 1 test completed
----------|----------|----------|----------|----------|----------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
----------|----------|----------|----------|----------|----------------|
----------|----------|----------|----------|----------|----------------|
All files |      100 |      100 |      100 |      100 |                |
----------|----------|----------|----------|----------|----------------|

So one last thing that we need is to deliver our super duper app to some hosting. scp-ing files is not the task for Poi but building those files is and Poi does it very well:

$ poi build index.js

You will end up with the dist folder containing everything. One property of the created files is that they use absolute paths for resources like scripts and styles. It's great when it comes to hosting but trying it out using the file:// protocol (simply opening the index.html file in the browser) won't work. But it is very easy to fix. In poi.config.js add the webpack method like so:

module.exports = {
  // ...
  webpack(config) {
    config.output.publicPath = ''
    return config
  }
}

Now run the build again and open the resulting index.html file in the browser. Boom! It works!

There is way more to Poi than that. Check out the official documentation at http://poi.js.org and the GitHub page at http://github.com/egoist/poi. You will be amazed what's in store!

Happy... poi'ing!

Sunday, September 10, 2017

DotNet core and vuejs - a quick recipe

The problem

So you're stuck in .NET world (maybe with Sitecore or some other God forsaken creation) and you need to do some front-end code. How the hell do you get started?

The solution

Use dotnet core 2.0.0. Scaffold your application, install all the required dependencies and start the application in development mode

    $ sudo apt-get install dotnet-sdk-2.0.0
    $ dotnet new --install Microsoft.AspNetCore.SpaTemplates::*
    $ dotnet new vue -n hello-world
    $ cd hello-world
    $ dotnet restore
    $ npm install
    $ ASPNETCORE_ENVIRONMENT="Development" dotnet run

Happy coding

Sunday, May 28, 2017

Vue.js cheatsheet

If you ever wondered why Vue.js is so easy take a look at this cheatsheet!