{"action":"created","comment":{"url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/comments/261861029","pull_request_review_id":209903751,"id":261861029,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI2MTg2MTAyOQ==","diff_hunk":"@@ -0,0 +1,1339 @@\n+---\n+layout: post\n+authors: [elke_heymans]\n+outbound: [tech_blog_vue-with-typescript]\n+title: 'Vue with TypeScript'\n+image: /img/vue-with-typescript/vue-plus-typescript.png\n+tags: [Vue,TypeScript,JavaScript,VueJS,VueCLI]\n+category: Vue\n+comments: true\n+---\n+\n+# Table of contents\n+1. [Vue with TypeScript, an introduction](#1-vue-with-typescript-an-introduction)\n+2. [Creating a Vue project with TypeScript](#2-creating-a-vue-project-with-typescript)\n+3. [A look into the files created by the Vue CLI](#3-a-look-into-the-files-created-by-the-vue-cli)\n+4. [How to write your first component](#4-how-to-write-your-first-component)\n+5. [Using your first plugin](#5-using-your-first-plugin)\n+6. [Your first deployment](#6-your-first-deployment)\n+7. [Conclusion](#7-conclusion)\n+8. [Resources and further reading](#8-resources-and-further-reading)\n+\n+# 1. Vue with TypeScript, an introduction\n+With the release of the Vue CLI 3 in August 2018, Vue now officially supports development in TypeScript.\n+In September 2018, Evan You even announced that [the next version of Vue will be rewritten in TypeScript](https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf){:target=\"_blank\" rel=\"noopener noreferrer\"}.\n+This does not mean that you are forced to use TypeScript, it will still be an option.\n+TypeScript has numerous advantages such as static typing and transpiling of the latest ECMAScript features for full compatibility with older browsers.\n+Especially the static typing is a very interesting feature for projects in a professional environment as it helps define more strict interfaces.\n+With the use of types, you inherently provide documentation to other developers on how to use your code as it offers guidance on how to use your functions, components and so on.\n+\n+In this tutorial we will make a really simple blog system to showcase how you create a project, create a component, install a plugin and do calls via HTTP.\n+Our little project will be called `wordvue`.\n+At the same time we will explain some tips and tricks and give some background information about Vue with TypeScript so that you fully understand what the purpose is of each line of code.\n+The project can be found in a [GitHub repository](https://github.com/ordina-jworks/vue-typescript-wordvue){:target=\"_blank\" rel=\"noopener noreferrer\"} so you can see a working version.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-plus-typescript-small.png\" class=\"image\">\n+</div>\n+\n+# 2. Creating a Vue project with TypeScript\n+\n+## Using the Vue CLI\n+Thanks to the Vue CLI, it is the easiest way to create a new Vue project.\n+First make sure you have the latest version of the CLI installed with NPM:\n+\n+```text\n+$ npm i -g @vue/cli\n+```\n+\n+After that we create our project:\n+\n+```text\n+$ vue create wordvue\n+```\n+\n+The CLI knows some presets but we will go through the manual mode to be sure we select the TypeScript version, at the time of writing the current default language for Vue is JavaScript.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-1-manually-select.png\" class=\"image\">\n+</div>\n+\n+### Babel + TypeScript\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-2-selected-features.png\" class=\"image right fit\">\n+</div>\n+\n+We check the TypeScript option and for the purpose of this article we will not look in detail at the other features of this screen and leave on the defaults.\n+I also checked CSS Pre-processors just because I like SCSS.\n+Make sure you have Babel selected, Babel will automatically add multiple pollyfills.\n+The pollyfills will help with having backwards compatibility of ECMAScript features.\n+\n+### Using the class-style component syntax\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-3-class-style-component-syntax.png\" class=\"image fit\">\n+</div>\n+\n+In the next screen we will get the question if we want class-style component syntax, for which we answer yes.\n+With this, we actually install the decorators that can be found in the [Vue Class Component package](https://github.com/vuejs/vue-class-component).\n+We will now explain the difference between using the class-style coomponent syntax and using the classic Vue syntax.\n+\n+#### The classic Vue Syntax\n+If you do not use the class-style component syntax, your components will look exactly as if you have rendered them with Vue with JavaScript, but with the addition of types:\n+\n+```typescript\n+import Vue, { VNode } from 'vue'\n+\n+export const HelloComponent = Vue.extend({\n+    data () {\n+        return {\n+            message: 'Hello',\n+        }\n+    },\n+    methods: {\n+        greet (): string {\n+            return this.message + ' world';\n+        }\n+    },\n+    computed: {\n+        greeting(): string {\n+            return this.greet() + '!';\n+        }\n+    },\n+    render (createElement): VNode {\n+        return createElement('div', this.greeting);\n+    }\n+});\n+```\n+\n+As you can see, you'll still have the data function, the methods, computed properties and the render function that you can use in regular Vue.\n+\n+#### Class-style component syntax\n+With the class-style component syntax, we would write the same component like this:\n+\n+```typescript\n+import Vue from 'vue'\n+import Component from 'vue-class-component'\n+\n+@Component({\n+    template: '<div>{{ greeting }}</div>'\n+})\n+export default class HelloComponent extends Vue {\n+    message: string = 'Hello'\n+    greet(): string {\n+        return this.message + ' world';\n+    }\n+    get greeting() {\n+        return this.greet() + '!';\n+    }\n+}\n+```\n+\n+When you compare it to the previous version, the data property message is now a regular property in our component class. Methods are present as class methods. And the computed properties can be defined as a getter.\n+\n+### The other settings\n+After you've replied `Yes` to the \"Use class-style component syntax?\" question, you can continue with the default options.\n+\n+For the CSS pre-processor, you either choose between Stylus, Less and SCSS. We choose the default `Sass/SCSS (with node-sass)`.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-4-css-preprocessor.png\" class=\"image fit\">\n+</div>\n+\n+As for the linter, you can either choose between TSLint or ESLint with a bunch of configurations.\n+I opt for the default `TSLint` option as the support for TypeScript in ESLint is (at the time of writing) fairly recent.\n+But ESLint is certainly a valid option as the TypeScript has announced in their [January to June 2019 roadmap](https://github.com/Microsoft/TypeScript/issues/29288) that ESLint will be their own focus.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-5-linter.png\" class=\"image fit\">\n+</div>\n+\n+We can choose for the `Lint on save`option as we want to see immediately the effects of our linter.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-6-lint-on-save.png\" class=\"image fit\">\n+</div>\n+\n+Finally we have to choose if we want the configurations in dedicated files or all bundled together in our package.json. We opt for `In dedicated config files` as we prefer to not clutter the package.json with a lot of configurations.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-7-dedicated-config.png\" class=\"image fit\">\n+</div>\n+\n+The Vue CLI will now create the project with a Git repository, perform an NPM install and generate a README.\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-8-project-generated.png\" class=\"image fit\">\n+</div>\n+\n+## Launching your first Vue project\n+After the Vue CLI has created your Vue project, you can go with the terminal to the root folder of the project and launch it with:\n+\n+```text\n+$ npm run serve\n+```\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-default-page.png\" class=\"image fit\">\n+</div>\n+\n+As you will see, the CLI starts the development server, starts the type checking and linting service.\n+By default the project runs on http://localhost:8080 but if there's already something running on port 8080, he will pick port 8081 or the next one available.\n+This way you don't need to specify a free port.\n+\n+A default Vue project looks like this:\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-serve.png\" class=\"image fit\">\n+</div>\n+\n+# 3. A look into the files created by the Vue CLI\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-cli-generated-files.png\" class=\"image right\">\n+</div>\n+\n+The files that the Vue CLI generated are mainly all the configuration files that we wanted separately.\n+So we have a configuration file for Babel with babel.config.js, PostCSS (which contains the configuration for SCSS) with postcss.config.js, TypeScript with tsconfig.json and TSLint with tslint.json.\n+You will also find a node_modules folder for all your NPM packages with a package.json in which we define all the NPM packages that we need in our project.\n+If we would have opted for the `In package.json` option, we would have had a large package.json file.\n+\n+The main folders in which you will work are public and src. We will look at these more in detail later so you fully understand what their purpose is.\n+\n+## Public\n+Public is meant for static assets like images, favicons and more.\n+It also contains your index.html which is very basic:\n+\n+```html\n+<!DOCTYPE html>\n+<html lang=\"en\">\n+<head>\n+\t<meta charset=\"utf-8\">\n+\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n+\t<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n+\t<link rel=\"icon\" href=\"<%= BASE_URL %>favicon.ico\">\n+\t<title>wordvue</title>\n+</head>\n+<body>\n+\t<noscript>\n+\t\t<strong>We're sorry but wordvue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>\n+\t</noscript>\n+\t<div id=\"app\"></div>\n+\t<!-- built files will be auto injected -->\n+</body>\n+</html>\n+```\n+\n+It is only in rare cases that you should adapt the index.html.\n+One example situation would be to add Google Analytics, add more meta tags or adapt the title tag.\n+Vue will automatically inject the necessary generated JavaScript files right before the closing body tag.\n+This will include the transpiled version of your own code as well as vendor code.\n+The most important thing is the div tag with id app.\n+This should always be present in your index.html as this is the tag on which Vue will bootstrap the entire application.\n+\n+## Src\n+\n+### main.ts\n+```typescript\n+import Vue from 'vue';\n+import App from './App.vue';\n+\n+Vue.config.productionTip = false;\n+\n+new Vue({\n+\trender: (h) => h(App),\n+}).$mount('#app');\n+```\n+\n+When you look in the src folder, you will find a main.ts file.\n+This is the one that Vue will execute first.\n+As you can see this creates a new instance of Vue in which we only define a render function.\n+Vue will pass along `h` which is of type `CreateElement`.\n+`h` has been [chosen by the creator of Vue](https://github.com/vuejs/babel-plugin-transform-vue-jsx/issues/6){:target=\"_blank\" rel=\"noopener noreferrer\"} as it is short for `Hyperscript`, a term that is used in several virtual DOM implementations.\n+A hyperscript is a script that will generate HTML structures.\n+It takes one parameter: `App`.\n+Thus in a Vue project, `h` will generate the HTML for our App component.\n+App is our main component that was generated by the Vue CLI and we will dive into that after this section.\n+main.ts should only be adapted to plug in new core functionalities of your application.\n+For example, a main.ts of one of my own projects is this:\n+\n+```typescript\n+import Vue, { CreateElement, VNode } from 'vue';\n+import App from './App.vue';\n+import i18n from './i18n';\n+import './registerServiceWorker';\n+import router from './router';\n+import store from './store';\n+\n+Vue.config.productionTip = false;\n+\n+new Vue({\n+    router, // custom router configuration\n+    store, // custom store implementation\n+    i18n, // my translations\n+    render: (h: CreateElement): VNode => h(App),\n+}).$mount('#app');\n+```\n+\n+As you can see, I have added 3 core functionalities: a router, a store and an i18n library.\n+In each component that you make, these functionalities will be available.\n+The reason why these will be available is because the Vue type gets extended by each of these libraries.\n+For example in the typings of VueI18n (the i18n library that I use), we find:\n+\n+```typescript\n+declare module 'vue/types/vue' {\n+\tinterface Vue {\n+\t\treadonly $i18n: VueI18n & IVueI18n;\n+\t\t$t: typeof VueI18n.prototype.t;\n+\t\t$tc: typeof VueI18n.prototype.tc;\n+\t\t$te: typeof VueI18n.prototype.te;\n+\t\t$d: typeof VueI18n.prototype.d;\n+\t\t$n: typeof VueI18n.prototype.n;\n+\t}\n+}\n+```\n+\n+This means that we will have a \\$i18n property available and 5 different functions.\n+If you would use a different i18n library, you will have most of these things also readily available.\n+For example vue-i18next defines \\$i18n as: \n+\n+```typescript\n+declare module \"vue/types/vue\" {\n+    interface Vue {\n+        readonly $i18n: VueI18Next;\n+        $t: TranslationFunction;\n+    }\n+}\n+```\n+\n+Vue itself does not provide an i18n implementation nor a store nor a router nor does it even support HTTP calls by default.\n+Vue is designed to be as light as possible so that developers can keep a project as lightweight as possible.\n+Vue does officially support specific NPM packages for these core functionalities.\n+Other packages will follow the same naming conventions as the official supported libraries for convenience sake.\n+Like said before we will only focus on the basic Vue functionalities and HTTP calls.\n+The other topics will be for a future article.\n+\n+### App.vue\n+The App.vue file is our first component that Vue bootstraps through our main.ts file.\n+It is considered to be the root component.\n+The Vue CLI generates the App component with one child component.\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t<img alt=\"Vue logo\" src=\"./assets/logo.png\">\n+\t\t<HelloWorld msg=\"Welcome to Your Vue.js + TypeScript App\"/>\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+import HelloWorld from './components/HelloWorld.vue';\n+\n+@Component({\n+\tcomponents: {\n+\t\tHelloWorld,\n+\t},\n+})\n+export default class App extends Vue {}\n+</script>\n+\n+<style>\n+#app {\n+\tfont-family: 'Avenir', Helvetica, Arial, sans-serif;\n+\t-webkit-font-smoothing: antialiased;\n+\t-moz-osx-font-smoothing: grayscale;\n+\ttext-align: center;\n+\tcolor: #2c3e50;\n+\tmargin-top: 60px;\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+Each page and part of a page that you will create, is a component that is a child of the root component.\n+Together, your whole application should have a component structure which should look like a tree:\n+\n+```text\n+App\n+\t- HomePage\n+\t\t- HelloWorld\n+\t- NewsPage\n+\t\t- NewsArticle\n+\t\t\t- Reaction\n+\t- ContactPage\n+```\n+\n+Each node of the tree is a component.\n+With the use of the `@Component(...)` decorator, we define which components can be child components of the component that we're defining.\n+For example in our App component, we want the HelloWorld component (through the HelloWorld tag), thus we add the components option with HelloWorld in there.\n+These components are local components.\n+If you would want to write a component that is global, you have to register it like this:\n+\n+```typescript\n+Vue.component('my-component-name', {\n+\t// ... options ...\n+})\n+```\n+\n+A global component can be accessed anywhere.\n+Try to avoid this as much as possible as it fills up the global namespace.\n+An example of a use case that is justified would be an icon library like Font Awesome:\n+\n+```typescript\n+library.add(\n+    faBars,\n+    ...\n+    faCameraRetro,\n+);\n+Vue.component('font-awesome-icon', FontAwesomeIcon);\n+```\n+\n+After this we can access the font-awesome-icon tag from everywhere.\n+\n+```html\n+<font-awesome-icon icon=\"arrow-down\" />\n+```\n+\n+# 4. How to write your first component\n+We will keep the project as simple as possible for now.\n+Firstly I will explain the basics of a Vue Component so that you will fully understand what happens when we write our first real component.\n+\n+## The structure of a .vue file\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t...\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+import HelloWorld from './components/HelloWorld.vue';\n+\n+@Component({\n+\tcomponents: {\n+\t\tHelloWorld,\n+\t},\n+})\n+export default class App extends Vue {}\n+</script>\n+\n+<style lang=\"scss\">\n+#app {\n+\t...\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+The standard way to write a Vue component is by using the .vue file extension.\n+In a .vue file, we define 3 optional tags: `template`, `script` and `style`.\n+According to the Vue documentation, you should always [order the tags consistently](https://vuejs.org/v2/style-guide/#Single-file-component-top-level-element-order-recommended){:target=\"_blank\" rel=\"noopener noreferrer\"} with style being the last one.\n+\n+### \\<template>...\\</template>\n+This is the visual part of your component, in here you define the HTML that will be used to display your component.\n+Note that your custom HTML should always be surrounded by a div tag.\n+The reason for this is that it allows Vue to encapsulate your custom CSS without unknowingly affecting the styling of your whole site.\n+You can use this to add a custom id or class to the tag to help you identify the component in for example your e2e tests.\n+Note that a .vue file can contain at most one template tag.\n+\n+### \\<script lang=\"ts\">...\\</script>\n+In the script tag, you can add your custom TypeScript code.\n+The lang attribute is not required but if you do not add it, the default language will be JavaScript.\n+In order for TypeScript to be available, you need to add `lang=\"ts\"`.\n+All of our TypeScript code should be present in this script tag, even the import statements.\n+Note that a .vue file can contain at most one script tag.\n+\n+### \\<style>...\\</style>\n+In the style tag we can define our own SCSS specific for this component.\n+By default, all the styles you define in a style tag are global.\n+By adding the scoped attribute to our style tag, our custom SCSS will be specific for that component.\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t<p>Hello World!</p>\n+\t\t<ChildComponent></ChildComponent>\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+...\n+</script>\n+\n+<style scoped>\n+#app {\n+\tp {\n+\t\ttext-style: italic;\n+\t}\n+}\n+</style>\n+\n+<style>\n+#app {\n+\tp {\n+\t\tcolor: red;\n+\t}\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+In the example above, the `style` tag with the scoped attribute will only affect the p tag in our component and not the one in our child component.\n+The `color: red` styling however will affect also the styling of p tags in `ChildComponent`.\n+So it is best to be aware of the implications as it can have unwanted side effects.\n+For a good way to structure your CSS, check out the [BEM methodology](http://getbem.com){:target=\"_blank\" rel=\"noopener noreferrer\"} as it will help with avoiding conflicts and will guide you in having clean CSS selectors.\n+\n+Be careful though as the scoped attribute leads to a certain performance hit.\n+Simply by adding the same class or id that we used in the template, we avoid this performance hit and still can have some scoped SCSS.\n+Note that this will also style the child components.\n+A .vue file can contain more than one style tag.\n+\n+If you want to use global styles, you can either put them in App.vue or create your own CSS file that you import either directly in index.html or in App.vue.\n+\n+### Should you put everything in a .vue file?\n+For small components, a .vue file will be very interesting as you have all the elements that make up your component into one specific file.\n+But what if you have for example lots of lines in the template tag?\n+Or what if you just want to split up the file?\n+One tactic you can use is the src attribute on the template, script and/or style tags.\n+\n+```vue\n+<template src=\"./mycomponent.html\"></template>\n+<script lang=\"ts\" src=\"./mycomponent.ts\"></script>\n+<style src=\"./mycomponent.scss\"></style>\n+```\n+\n+Personally I avoid using the src attribute as I like to force myself to keep my .vue files as small as possible.\n+There's also no performance difference between putting the HTML/SCSS separately or in the same .vue file.\n+The Vue CLI will generate the same compiled code.\n+\n+## How to organise your files\n+\n+### The basic structure\n+The basic project structure in Vue is very simple:\n+\n+```text\n+/public\n+\t/index.html\n+/src\n+\t/assets\n+\t/components\n+\tApp.vue\n+```\n+\n+The idea behind this is that you add all your custom components into /components and any assets that also need to be transpiled/compiled into /assets.\n+For example a global stylesheet or an icon library that you want to [treeshake](https://webpack.js.org/guides/tree-shaking/){:target=\"_blank\" rel=\"noopener noreferrer\"} fits perfectly into /assets.\n+In the public folder we put all things static that don't need to be parsed and treeshaked: the logo, the favicons, images, ...\n+\n+### A more advanced structure\n+The basic structure is enough for a simple single page application.\n+But once you start to have complex pages, things will quickly need to be changed to accommodate the amount of files that you will create.\n+In a more advanced project (like a personal project of mine), the structure could be like this:\n+\n+```text\n+/public\n+\t/index.html\n+/src\n+\t/assets\n+\t/components\n+\t/i18n\n+\t/models\n+\t/store\n+\t/views\n+\tApp.vue\n+```\n+\n+In this project structure, both /public and /assets provide the same purpose.\n+I use /assets for some local .json files that contain some of my data that is needed in the application.\n+In /components I keep all my generic components that can be used by pages and other components.\n+This is what you would put in a SharedModule in Angular for example.\n+/i18n contains all my translations of my website as well as the initialisation of an i18n library.\n+Same goes for the /store that contains my implementation of a store.\n+I had based myself on the [structure proposed in the Vuex library](https://vuex.vuejs.org/guide/structure.html) where they group everything store related into /store and applied the same principle for other libraries.\n+\n+### Modules\n+Vue is designed to be as lightweight as possible and this can be seen in how the basic project is structured: no modules are present.\n+Vue does support modules but not in the way like we know them from other frameworks like Angular.\n+Vue modules are simply ES6 modules.\n+\n+## BlogPost component\n+\n+### The basic file\n+Our first component we will write is a BlogPost component in `components/BlogPost.vue`.\n+In a first stage of our little project we will just hardcode a blogpost.\n+The BlogPost component is small:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div class=\"blogpost\">\n+\t\t<h2>{{ post.title }}</h2>\n+\t\t<p>{{ post.body }}</p>\n+\t\t<p class=\"meta\">Written by {{ post.author }} on {{ date }}</p>\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Prop, Vue } from 'vue-property-decorator';\n+\n+export interface Post {\n+\ttitle: string;\n+\tbody: string;\n+\tauthor: string;\n+\tdatePosted: Date;\n+}\n+\n+@Component\n+export default class BlogPost extends Vue {\n+\t@Prop() private post!: Post;\n+\n+\tget date() {\n+\t\treturn `${this.post.datePosted.getDate()}/${this.post.datePosted.getMonth()}/${this.post.datePosted.getFullYear()}`;\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+div.blogpost {\n+\th2 {\n+\t\ttext-decoration: underline;\n+\t}\n+\tp.meta {\n+\t\tfont-style: italic;\n+\t}\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+As you can see the template is rather small.\n+We've grouped all the elements in a div with class blogpost.\n+Vue expects us to wrap the content in one tag and by convention, they advise to use a div tag.\n+\n+Within the script tag you'll notice that we have created a small Post interface to wrap our data.\n+On the component itself, we have a member that is decorated with `@Prop()`.\n+With the decorator, we allow the use of the BlogPost component with the attribute post that should have type Post.\n+You'll notice we've added a `!` behind `post` so we end up with `post!`.\n+The exclamation mark is the [non-null assertion operator](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#non-null-assertion-operator){:target=\"_blank\" rel=\"noopener noreferrer\"} which tells the browser that `post` will eventually be filled in with a value and that it shall never be `null` or `undefined`.\n+\n+```html\n+<BlogPost :post=\"blogPost\" />\n+```\n+\n+Where `blogPost` is an instance of `Post` in our component.\n+\n+After that we have a date member which is a computed property.\n+\n+Sadly there is no full type checking going on at the moment.\n+If we were to use the BlogPost component, we can always pass along another object into the post attribute.\n+We can pass along a type attribute in the Props decorator but even that is not that stable.\n+\n+```typescript\n+@Prop({type: Object as () => Post})\n+```\n+\n+We end the component with our styling in which we make use of SCSS to nest all our styling.\n+\n+## Using the BlogPost component\n+So we have created the BlogPost component but how are we going to actually use it?\n+We adapt App.vue to this:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t<h1>Elke's fantastic blog</h1>\n+\t\t<BlogPost v-for=\"blogPost in blogPosts\" :post=\"blogPost\" :key=\"blogPost.title\" />\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+import BlogPost, { Post } from './components/BlogPost.vue';\n+\n+@Component({\n+\tcomponents: {\n+\t\tBlogPost,\n+\t},\n+})\n+export default class App extends Vue {\n+\tprivate blogPosts: Post[] = [\n+\t\t{\n+\t\t\ttitle: 'My first blogpost ever!',\n+\t\t\tbody: 'Lorem ipsum dolor sit amet.',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 18),\n+\t\t},\n+\t\t{\n+\t\t\ttitle: 'Look I am blogging!',\n+\t\t\tbody: 'Hurray for me, this is my second post!',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 19),\n+\t\t},\n+\t\t{\n+\t\t\ttitle: 'Another one?!',\n+\t\t\tbody: 'Another one!',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 20),\n+\t\t},\n+\t];\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+#app {\n+\tfont-family: 'Avenir', Helvetica, Arial, sans-serif;\n+\t-webkit-font-smoothing: antialiased;\n+\t-moz-osx-font-smoothing: grayscale;\n+\ttext-align: center;\n+\tcolor: #2c3e50;\n+\tmargin-top: 60px;\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+As you can see we define a property on the App component that contains our blog posts, we add the components property to the Component decorator and add the BlogPost tag in the template.\n+We simply loop over the blog posts with the v-for directive.\n+We pass each blog post to the BlogPost component by binding it to the correct data attribute.\n+This can be done through `v-bind:post=\"blogPost\"` but we use the shorthand method of `:post=\"blogPost\"`.\n+Vue transforms `:post` to `v-bind:post` behind the screens.\n+\n+Note that we also pass `:key` which we bind to the title of our blog post.\n+The reason for this is that it allows Vue to keep track of the state of the list by only looking at the `:key` attribute instead of having to deep compare objects.\n+Try to have an unique key of type number or string that can be used for actions such as identifying, ordering and searching.\n+A blog post title is a good start but when ordering, updating or other modifying operations you might not have the wanted result if we have blog posts with the same title.\n+It's best to use something of type number or string as the key.\n+Vue will tell you this in the console of your browser if you would take for example the `datePosted` as your key:\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/vue-key-typing-error.png\" class=\"image fit\">\n+</div>\n+\n+The reason behind this is that Vue relies on the built-in sort and find functionalities of JavaScript.\n+For objects, Vue can not do this natively.\n+\n+When we serve our app with \n+```text\n+$ npm run serve\n+```\n+We see in our browser: \n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/wordvue-first-impression.png\" class=\"image\">\n+</div>\n+\n+Great, you've written your first working component!\n+Now it is time to extend it with some functionalities.\n+\n+## Adding conditional elements to the component\n+An important part of a component is to have some dynamic behaviour.\n+For example what if we want to show a highlighted blog post? \n+We could create a new component called `HighlightedBlogPost` but we could also extend our existing component.\n+\n+We can add a new paragraph with a `v-if` statement:\n+\n+```html\n+<p v-if=\"post.highlighted\">This post is highlighted!</p>\n+```\n+\n+The contents of the `v-if` is a TypeScript statement that should return `true` or `false`.\n+We extend our `Post` interface to accomodate this:\n+\n+```typescript\n+export interface Post {\n+\ttitle: string;\n+\tbody: string;\n+\tauthor: string;\n+\tdatePosted: Date;\n+\thighlighted?: boolean;\n+}\n+```\n+\n+After that we add `highlighted: true,` to the second blog post in `App.vue`.\n+\n+In our browser it looks like this:\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/wordvue-conditional-elements.png\" class=\"image\">\n+</div>\n+\n+We end up with this as our BlogPost component:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div class=\"blogpost\">\n+\t\t<h2>{{ post.title }}</h2>\n+\t\t<p v-if=\"post.highlighted\">This post is highlighted!</p>\n+\t\t<p>{{ post.body }}</p>\n+\t\t<p class=\"meta\">Written by {{ post.author }} on {{ date }}</p>\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Prop, Vue } from 'vue-property-decorator';\n+\n+export interface Post {\n+\ttitle: string;\n+\tbody: string;\n+\tauthor: string;\n+\tdatePosted: Date;\n+\thighlighted?: boolean;\n+}\n+\n+@Component\n+export default class BlogPost extends Vue {\n+\t@Prop() private post!: Post;\n+\n+\tget date() {\n+\t\treturn `${this.post.datePosted.getDate()}/${this.post.datePosted.getMonth()}/${this.post.datePosted.getFullYear()}`;\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+div.blogpost {\n+\th2 {\n+\t\ttext-decoration: underline;\n+\t}\n+\tp.meta {\n+\t\tfont-style: italic;\n+\t}\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+## Adding conditional CSS to our component\n+We now know how to add a conditional element to our component, but we can also have conditional CSS.\n+We will use this conditional CSS so our highlighted blog post is also visually highlighted.\n+\n+We can add in our div with class blogpost an extra `v-bind` directive:\n+\n+```html\n+<div class=\"blogpost\" v-bind:class=\"{ highlighted: post.highlighted }\">...</div>\n+```\n+\n+With `v-bind` we define to which attribute we want to bind after the colon.\n+So in our case, `v-bind:class` results in a binding with the `class` attribute in our HTML.\n+`v-bind:class` accepts an object as parameter in which each key should be mapped to a boolean.\n+For each key that is mapped to a truthy value, that key is added as a class to the HTML tag on which the `v-bind` is located.\n+You will notice that we use `v-bind` to bind to the `class` attribute but that this attribute already exists on our HTML element.\n+This is no problem as Vue will simply concatenate all the values.\n+In the case that `post.highlighted` is truthy, we will thus end up with:\n+\n+```html\n+<div class=\"blogpost highlighted\">...</div>\n+```\n+\n+And when it is falsy, we end up with:\n+\n+```html\n+<div class=\"blogpost\">...</div>\n+```\n+\n+We extend our `.blogpost` to give the blog posts a width, center them and add a border with a background:\n+\n+```css\n+div.blogpost {\n+\twidth: 400px;\n+\tmargin: 0 auto;\n+\t&.highlighted {\n+\t\tborder: 1px solid #f4d942;\n+\t\tbackground: #fff3b2;\n+\t}\n+\t...\n+}\n+```\n+\n+In our browser it looks like this:\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/wordvue-conditional-css.png\" class=\"image\">\n+</div>\n+\n+Note that we also have a shorter version of `v-bind:attributename` which is `:attributename`.\n+So we can shorten `v-bind:class` to this:\n+\n+```html\n+<div class=\"blogpost\" :class=\"{ highlighted: post.highlighted }\">...</div>\n+```\n+\n+We end up with this as our BlogPost component:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div class=\"blogpost\" :class=\"{ highlighted: post.highlighted }\">\n+\t\t<h2>{{ post.title }}</h2>\n+\t\t<p v-if=\"post.highlighted\">This post is highlighted!</p>\n+\t\t<p>{{ post.body }}</p>\n+\t\t<p class=\"meta\">Written by {{ post.author }} on {{ date }}</p>\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Prop, Vue } from 'vue-property-decorator';\n+\n+export interface Post {\n+\ttitle: string;\n+\tbody: string;\n+\tauthor: string;\n+\tdatePosted: Date;\n+\thighlighted?: boolean;\n+}\n+\n+@Component\n+export default class BlogPost extends Vue {\n+\t@Prop() private post!: Post;\n+\n+\tget date() {\n+\t\treturn `${this.post.datePosted.getDate()}/${this.post.datePosted.getMonth()}/${this.post.datePosted.getFullYear()}`;\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+div.blogpost {\n+\twidth: 400px;\n+\tmargin: 0 auto;\n+\t&.highlighted {\n+\t\tborder: 1px solid #f4d942;\n+\t\tbackground: #fff3b2;\n+\t}\n+\th2 {\n+\t\ttext-decoration: underline;\n+\t}\n+\tp.meta {\n+\t\tfont-style: italic;\n+\t}\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+## Using events in a component\n+As a final extension to our blog, we also want to add some dynamic behaviour by reacting to events.\n+For our example, we will bind a button to the click event in our App component with the `v-on:click` directive.\n+\n+```html\n+<button v-on:click=\"toggleHighlightedPostsVisibility\">Show/hide highlighted posts</button>\n+```\n+\n+The syntax to bind to events is `v-on:eventname`.\n+We can also use the shorthand version which is `@eventname`:\n+\n+```html\n+<button @click=\"toggleHighlightedPostsVisibility\">Show/hide highlighted posts</button>\n+```\n+\n+After that we write the event handler along with some variables in our component and we'll explain after the code what we have done:\n+\n+```typescript\n+export default class App extends Vue {\n+\t// ...\n+\tpublic showHighlighted: boolean = true;\n+\n+\tprivate blogPosts: Post[] = [];\n+\n+\tget visibleBlogPosts() {\n+\t\treturn this.blogPosts.filter((post: Post) => post.highlighted === undefined ||  post.highlighted === this.showHighlighted);\n+\t}\n+\n+\tpublic toggleHighlightedPostsVisibility() {\n+\t\tthis.showHighlighted = !this.showHighlighted;\n+\t}\n+\t// ...\n+}\n+```\n+\n+First what we did was add the `showHighlighted` boolean.\n+This is to keep track whether we should show or hide the highlighted blog posts.\n+\n+We also wrote a getter to only show the blog posts that are allowed to be shown.\n+In our filter, we check if the `highlighted` member is defined and if so, we check if it equals our `showHighlighted` variable.\n+\n+The reason why we write this in a getter, is that we want to avoid putting business logic in our template.\n+Thus we opt for writing a getter which is the equivalent of a computed property in Vue JavaScript.\n+\n+After this we have to adapt the `v-for` in our template so that we use the new getter:\n+\n+```html\n+<BlogPost v-for=\"blogPost in visibleBlogPosts\" :post=\"blogPost\" :key=\"blogPost.title\" />\n+```\n+\n+As a small bonus, we will make the text in our button dynamic.\n+Currently we have `Show/hide highlighted posts` as the text but it would be cleaner if we showed `Show highlighted posts` and `Hide highlighted posts` depending on the state of the component.\n+We update the button to the following code:\n+\n+```html\n+{% raw %}\n+<button @click=\"toggleHighlightedPostsVisibility\">{{ showHighlighted ? 'Hide' : 'Show' }} highlighted posts</button>\n+{% endraw %}\n+```\n+\n+In the end, we end up visually with this:\n+\n+<div style=\"text-align: center;\">\n+  <img src=\"/img/vue-with-typescript/wordvue-events-showhide.png\" class=\"image\">\n+</div>\n+\n+And our App component looks like this:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t<h1>Elke's fantastic blog</h1>\n+\t\t<button @click=\"toggleHighlightedPostsVisibility\">{{ showHighlighted ? 'Hide' : 'Show' }} highlighted posts</button>\n+\t\t<BlogPost v-for=\"blogPost in visibleBlogPosts\" :post=\"blogPost\" :key=\"blogPost.title\" />\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+import BlogPost, { Post } from './components/BlogPost.vue';\n+\n+@Component({\n+\tcomponents: {\n+\t\tBlogPost,\n+\t},\n+})\n+export default class App extends Vue {\n+\n+\tpublic showHighlighted: boolean = true;\n+\n+\tprivate blogPosts: Post[] = [\n+\t\t{\n+\t\t\ttitle: 'My first blogpost ever!',\n+\t\t\tbody: 'Lorem ipsum dolor sit amet.',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 18),\n+\t\t},\n+\t\t{\n+\t\t\ttitle: 'Look I am blogging!',\n+\t\t\tbody: 'Hurray for me, this is my second post!',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 19),\n+\t\t\thighlighted: true,\n+\t\t},\n+\t\t{\n+\t\t\ttitle: 'Another one?!',\n+\t\t\tbody: 'Another one!',\n+\t\t\tauthor: 'Elke',\n+\t\t\tdatePosted: new Date(2019, 1, 20),\n+\t\t},\n+\t];\n+\n+\tget visibleBlogPosts() {\n+\t\treturn this.blogPosts.filter((post: Post) => post.highlighted === undefined ||  post.highlighted === this.showHighlighted);\n+\t}\n+\n+\tpublic toggleHighlightedPostsVisibility() {\n+\t\tthis.showHighlighted = !this.showHighlighted;\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+#app {\n+\tfont-family: 'Avenir', Helvetica, Arial, sans-serif;\n+\t-webkit-font-smoothing: antialiased;\n+\t-moz-osx-font-smoothing: grayscale;\n+\ttext-align: center;\n+\tcolor: #2c3e50;\n+\tmargin-top: 60px;\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+# 5. Using your first plugin\n+Vue comes without any libraries, it is a super clean and lean framework where even functionality for HTTP calls is not present.\n+However, every component is a Vue object and can be extended with a `$http` member that you can use in your code to perform HTTP calls.\n+\n+To provide this `$http` member, we have to add the correct plugin to our code.\n+In the [awesome-vue project on GitHub](https://github.com/vuejs/awesome-vue){:target=\"_blank\" rel=\"noopener noreferrer\"}, we can find an [extensive list of HTTP plugins](https://github.com/vuejs/awesome-vue#http-requests){:target=\"_blank\" rel=\"noopener noreferrer\"}.\n+We will use [axios](https://github.com/axios/axios){:target=\"_blank\" rel=\"noopener noreferrer\"} as our HTTP library but we will use [vue-axios](https://github.com/imcvampire/vue-axios){:target=\"_blank\" rel=\"noopener noreferrer\"} for the bindings with Vue in TypeScript as axios does not provide the necessary typings for axios in Vue.\n+\n+## Installing a plugin\n+We follow the installation instructions for vue-axios which are pretty straightforward:\n+\n+```text\n+$ npm i axios vue-axios\n+```\n+\n+As you noticed we also installed axios.\n+This is because vue-axios only focuses on the TypeScript bindings for Vue and does not include the actual axios library.\n+Vue-axios basically turns the axios library into a plugin compatible for Vue.\n+After that, we have to signal to Vue that we want to use this plugin.\n+We add a `Vue.use(plugin, options)` statement in our main.ts so it looks like this:\n+\n+```typescript\n+import axios from 'axios';\n+import Vue from 'vue';\n+import VueAxios from 'vue-axios';\n+import App from './App.vue';\n+\n+Vue.config.productionTip = false;\n+\n+Vue.use(VueAxios, axios);\n+\n+new Vue({\n+\trender: (h) => h(App),\n+}).$mount('#app');\n+```\n+\n+The important part is that we put the `Vue.use(...)` statement before we actually bootstrap the application with `new Vue(...)`.\n+\n+## The effect of adding a plugin\n+So we have added a plugin, but what does that actually mean?\n+What is the effect on our Vue code?\n+The main effect is that we now have `$http` accessible in every Vue component.\n+This means that we can now have `this.$http` in our classes in which a unique instance of the axios library for the whole application will be plugged.\n+When we check the [typings](https://github.com/axios/axios/blob/master/index.d.ts){:target=\"_blank\" rel=\"noopener noreferrer\"}  from axios, we find that we now have methods like `get(...)`, `post(...)` and many more default REST methods available in our code through the \\$http member in which an instance of axios is present.\n+\n+Methods like `get(...)` and `post(...)` will also exist on other HTTP libraries that we can add to Vue.\n+It is not obliged by Vue to provide these same functionalities in another HTTP library.\n+But it makes sense for library creators to comply to the standard set by the HTTP library of preference as chosen by Vue, in this case axios.\n+Otherwise it would not be easy to change certain libraries for another one.\n+\n+## Using the axios plugin for performing HTTP calls\n+A Vue component has [multiple lifecycle hooks](https://vuejs.org/v2/guide/instance.html#Instance-Lifecycle-Hooks){:target=\"_blank\" rel=\"noopener noreferrer\"} with the most interesting ones for what we want to do: `created()` and `mounted()`.\n+Created is called by Vue when the object is created: reactive data is set up, event callbacks are ready and the object is not yet mounted on the DOM.\n+The Vue object will thus be ready to go but it will not yet be visible to the user.\n+The mounted hook is used for when the element is mounted into the HTML DOM, which means the rendering is performed by the browser.\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t...\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+\n+@Component({})\n+export default class App extends Vue {\n+\tprivate created() {\n+\t\tconsole.log('The app is created!');\n+\t}\n+\n+\tprivate mounted() {\n+\t\tconsole.log('The app is mounted!');\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+#app {\n+  ...\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+There are 2 reasons why we want to start our HTTP calls in the created method.\n+The first reason is that we can limit the amount of time the user has to wait for data to be loaded and shown on the screen.\n+The second one is that the mounted hook is not called when we would use serverside rendering.\n+To ensure that our code is compatible with all use cases, we place the HTTP calls in the created method of our App.vue which results in this component:\n+\n+```vue\n+{% raw %}\n+<template>\n+\t<div id=\"app\">\n+\t\t<h1>Elke's fantastic blog</h1>\n+\t\t<button @click=\"toggleHighlightedPostsVisibility\">{{ showHighlighted ? 'Hide' : 'Show' }} highlighted posts</button>\n+\t\t<BlogPost v-for=\"blogPost in visibleBlogPosts\" :post=\"blogPost\" :key=\"blogPost.title\" />\n+\t</div>\n+</template>\n+\n+<script lang=\"ts\">\n+import { Component, Vue } from 'vue-property-decorator';\n+import BlogPost, { Post } from './components/BlogPost.vue';\n+import { AxiosResponse } from 'axios';\n+\n+@Component({\n+\tcomponents: {\n+\t\tBlogPost,\n+\t},\n+})\n+export default class App extends Vue {\n+\n+\tpublic showHighlighted: boolean = true;\n+\n+\tprivate blogPosts: Post[] = [];\n+\n+\tget visibleBlogPosts() {\n+\t\treturn this.blogPosts.filter((post: Post) => post.highlighted === undefined ||  post.highlighted === this.showHighlighted);\n+\t}\n+\n+\tpublic toggleHighlightedPostsVisibility() {\n+\t\tthis.showHighlighted = !this.showHighlighted;\n+\t}\n+\n+\tprivate created() {\n+\t\tthis.$http.get('http://localhost:3000/blogposts').then((response: AxiosResponse) => {\n+\t\t\tthis.blogPosts = response.data.map((val: any) => ({\n+\t\t\t\ttitle: val.title,\n+\t\t\t\tbody: val.body,\n+\t\t\t\tauthor: val.author,\n+\t\t\t\tdatePosted: new Date(val.datePosted),\n+\t\t\t\thighlighted: val.highlighted,\n+\t\t\t}));\n+\t\t});\n+\t}\n+}\n+</script>\n+\n+<style lang=\"scss\">\n+#app {\n+\tfont-family: 'Avenir', Helvetica, Arial, sans-serif;\n+\t-webkit-font-smoothing: antialiased;\n+\t-moz-osx-font-smoothing: grayscale;\n+\ttext-align: center;\n+\tcolor: #2c3e50;\n+\tmargin-top: 60px;\n+}\n+</style>\n+{% endraw %}\n+```\n+\n+As you can see we have added a private created method since this should not be publicly available to other components.\n+We call an API and map the response into our Post array.\n+Now we need to set up our API.\n+\n+## How we have set up a local API\n+To simulate a real API call, we set up [json-server](https://github.com/typicode/json-server){:target=\"_blank\" rel=\"noopener noreferrer\"}, a small tool that launches a web server with a REST API that serves a json file which we call `db.json` present in our assets folder:\n+\n+```json\n+{\n+\t\"blogposts\": [\n+\t\t{\n+\t\t\t\"title\": \"My first blogpost ever!\",\n+\t\t\t\"body\": \"Lorem ipsum dolor sit amet.\",\n+\t\t\t\"author\": \"Elke\",\n+\t\t\t\"datePosted\": \"2019-01-18\"\n+\t\t},\n+\t\t{\n+\t\t\t\"title\": \"Look I am blogging!\",\n+\t\t\t\"body\": \"Hurray for me, this is my second post!\",\n+\t\t\t\"author\": \"Elke\",\n+\t\t\t\"datePosted\": \"2019-01-19\",\n+\t\t\t\"highlighted\": true\n+\t\t},\n+\t\t{\n+\t\t\t\"title\": \"Another one?!\",\n+\t\t\t\"body\": \"Another one!\",\n+\t\t\t\"author\": \"Elke\",\n+\t\t\t\"datePosted\": \"2019-01-20\"\n+\t\t}\n+\t]\n+}\n+```\n+\n+We install json-server with NPM and then we launch it with:\n+\n+```text\n+$ npm i json-server\n+$ json-server src/assets/db.json\n+```\n+\n+By default, json-server will launch on port 3000.\n+When we launch wordvue and open it in the browser, we will see that the blog posts are now coming from our local API.\n+Now you know how to install a plugin and retrieve data with axios over HTTP.\n+\n+# 6. Your first deployment\n+\n+## Development mode versus production mode\n+Just like other frontend frameworks, Vue has its development mode and production mode. The development mode is available with:\n+\n+```text\n+$ npm run serve\n+```\n+\n+While production mode is available with:\n+\n+```text\n+$ npm run build\n+```\n+\n+Now what is the difference between both modes?\n+\n+| Development mode                                                          | Production mode                                                         |\n+|---------------------------------------------------------------------------|-------------------------------------------------------------------------|\n+| CSS & HTML bundled into JS                                                | CSS separately, HTML bundled into JS                                    |\n+| Warnings in console                                                       | No warnings in console                                                  |\n+| Additional checks to identify warnings                                    | No additional checks, ignores any situation that would trigger warnings |\n+| Everything in one app.js                                                  | Separate app.js and vendor.js                                           |","path":"_posts/2019-02-27-vue-with-typescript.md","position":1273,"original_position":1273,"commit_id":"6f51ad9ded6c02d1341feb260ba1a6ec4fb39c96","original_commit_id":"6f51ad9ded6c02d1341feb260ba1a6ec4fb39c96","user":{"login":"yannickdeturck","id":1644089,"node_id":"MDQ6VXNlcjE2NDQwODk=","avatar_url":"https://avatars2.githubusercontent.com/u/1644089?v=4","gravatar_id":"","url":"https://api.github.com/users/yannickdeturck","html_url":"https://github.com/yannickdeturck","followers_url":"https://api.github.com/users/yannickdeturck/followers","following_url":"https://api.github.com/users/yannickdeturck/following{/other_user}","gists_url":"https://api.github.com/users/yannickdeturck/gists{/gist_id}","starred_url":"https://api.github.com/users/yannickdeturck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yannickdeturck/subscriptions","organizations_url":"https://api.github.com/users/yannickdeturck/orgs","repos_url":"https://api.github.com/users/yannickdeturck/repos","events_url":"https://api.github.com/users/yannickdeturck/events{/privacy}","received_events_url":"https://api.github.com/users/yannickdeturck/received_events","type":"User","site_admin":false},"body":"```suggestion\r\n| Everything in one `app.js`                                                  | Separate `app.js` and `vendor.js`                                           |\r\n```","created_at":"2019-03-03T10:36:36Z","updated_at":"2019-03-03T10:42:55Z","html_url":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489#discussion_r261861029","pull_request_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/comments/261861029"},"html":{"href":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489#discussion_r261861029"},"pull_request":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489"}}},"pull_request":{"url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489","id":256578096,"node_id":"MDExOlB1bGxSZXF1ZXN0MjU2NTc4MDk2","html_url":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489","diff_url":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489.diff","patch_url":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489.patch","issue_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/489","number":489,"state":"open","locked":false,"title":"Feature/vue with typescript","user":{"login":"ElkeBxl","id":31392019,"node_id":"MDQ6VXNlcjMxMzkyMDE5","avatar_url":"https://avatars1.githubusercontent.com/u/31392019?v=4","gravatar_id":"","url":"https://api.github.com/users/ElkeBxl","html_url":"https://github.com/ElkeBxl","followers_url":"https://api.github.com/users/ElkeBxl/followers","following_url":"https://api.github.com/users/ElkeBxl/following{/other_user}","gists_url":"https://api.github.com/users/ElkeBxl/gists{/gist_id}","starred_url":"https://api.github.com/users/ElkeBxl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElkeBxl/subscriptions","organizations_url":"https://api.github.com/users/ElkeBxl/orgs","repos_url":"https://api.github.com/users/ElkeBxl/repos","events_url":"https://api.github.com/users/ElkeBxl/events{/privacy}","received_events_url":"https://api.github.com/users/ElkeBxl/received_events","type":"User","site_admin":false},"body":"","created_at":"2019-02-27T08:11:39Z","updated_at":"2019-03-03T10:42:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"52fa638f303076d8da508844162422733da0b290","assignee":{"login":"MrJean","id":1266135,"node_id":"MDQ6VXNlcjEyNjYxMzU=","avatar_url":"https://avatars1.githubusercontent.com/u/1266135?v=4","gravatar_id":"","url":"https://api.github.com/users/MrJean","html_url":"https://github.com/MrJean","followers_url":"https://api.github.com/users/MrJean/followers","following_url":"https://api.github.com/users/MrJean/following{/other_user}","gists_url":"https://api.github.com/users/MrJean/gists{/gist_id}","starred_url":"https://api.github.com/users/MrJean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MrJean/subscriptions","organizations_url":"https://api.github.com/users/MrJean/orgs","repos_url":"https://api.github.com/users/MrJean/repos","events_url":"https://api.github.com/users/MrJean/events{/privacy}","received_events_url":"https://api.github.com/users/MrJean/received_events","type":"User","site_admin":false},"assignees":[{"login":"MrJean","id":1266135,"node_id":"MDQ6VXNlcjEyNjYxMzU=","avatar_url":"https://avatars1.githubusercontent.com/u/1266135?v=4","gravatar_id":"","url":"https://api.github.com/users/MrJean","html_url":"https://github.com/MrJean","followers_url":"https://api.github.com/users/MrJean/followers","following_url":"https://api.github.com/users/MrJean/following{/other_user}","gists_url":"https://api.github.com/users/MrJean/gists{/gist_id}","starred_url":"https://api.github.com/users/MrJean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MrJean/subscriptions","organizations_url":"https://api.github.com/users/MrJean/orgs","repos_url":"https://api.github.com/users/MrJean/repos","events_url":"https://api.github.com/users/MrJean/events{/privacy}","received_events_url":"https://api.github.com/users/MrJean/received_events","type":"User","site_admin":false},{"login":"fredericghijselinck","id":9720030,"node_id":"MDQ6VXNlcjk3MjAwMzA=","avatar_url":"https://avatars3.githubusercontent.com/u/9720030?v=4","gravatar_id":"","url":"https://api.github.com/users/fredericghijselinck","html_url":"https://github.com/fredericghijselinck","followers_url":"https://api.github.com/users/fredericghijselinck/followers","following_url":"https://api.github.com/users/fredericghijselinck/following{/other_user}","gists_url":"https://api.github.com/users/fredericghijselinck/gists{/gist_id}","starred_url":"https://api.github.com/users/fredericghijselinck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fredericghijselinck/subscriptions","organizations_url":"https://api.github.com/users/fredericghijselinck/orgs","repos_url":"https://api.github.com/users/fredericghijselinck/repos","events_url":"https://api.github.com/users/fredericghijselinck/events{/privacy}","received_events_url":"https://api.github.com/users/fredericghijselinck/received_events","type":"User","site_admin":false},{"login":"ElkeBxl","id":31392019,"node_id":"MDQ6VXNlcjMxMzkyMDE5","avatar_url":"https://avatars1.githubusercontent.com/u/31392019?v=4","gravatar_id":"","url":"https://api.github.com/users/ElkeBxl","html_url":"https://github.com/ElkeBxl","followers_url":"https://api.github.com/users/ElkeBxl/followers","following_url":"https://api.github.com/users/ElkeBxl/following{/other_user}","gists_url":"https://api.github.com/users/ElkeBxl/gists{/gist_id}","starred_url":"https://api.github.com/users/ElkeBxl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ElkeBxl/subscriptions","organizations_url":"https://api.github.com/users/ElkeBxl/orgs","repos_url":"https://api.github.com/users/ElkeBxl/repos","events_url":"https://api.github.com/users/ElkeBxl/events{/privacy}","received_events_url":"https://api.github.com/users/ElkeBxl/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"fredericghijselinck","id":9720030,"node_id":"MDQ6VXNlcjk3MjAwMzA=","avatar_url":"https://avatars3.githubusercontent.com/u/9720030?v=4","gravatar_id":"","url":"https://api.github.com/users/fredericghijselinck","html_url":"https://github.com/fredericghijselinck","followers_url":"https://api.github.com/users/fredericghijselinck/followers","following_url":"https://api.github.com/users/fredericghijselinck/following{/other_user}","gists_url":"https://api.github.com/users/fredericghijselinck/gists{/gist_id}","starred_url":"https://api.github.com/users/fredericghijselinck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fredericghijselinck/subscriptions","organizations_url":"https://api.github.com/users/fredericghijselinck/orgs","repos_url":"https://api.github.com/users/fredericghijselinck/repos","events_url":"https://api.github.com/users/fredericghijselinck/events{/privacy}","received_events_url":"https://api.github.com/users/fredericghijselinck/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":694256650,"node_id":"MDU6TGFiZWw2OTQyNTY2NTA=","url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/labels/in%20review","name":"in review","color":"fbca04","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489/commits","review_comments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489/comments","review_comment_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/489/comments","statuses_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/statuses/6f51ad9ded6c02d1341feb260ba1a6ec4fb39c96","head":{"label":"ordina-jworks:feature/vue-with-typescript","ref":"feature/vue-with-typescript","sha":"6f51ad9ded6c02d1341feb260ba1a6ec4fb39c96","user":{"login":"ordina-jworks","id":15261659,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MjYxNjU5","avatar_url":"https://avatars0.githubusercontent.com/u/15261659?v=4","gravatar_id":"","url":"https://api.github.com/users/ordina-jworks","html_url":"https://github.com/ordina-jworks","followers_url":"https://api.github.com/users/ordina-jworks/followers","following_url":"https://api.github.com/users/ordina-jworks/following{/other_user}","gists_url":"https://api.github.com/users/ordina-jworks/gists{/gist_id}","starred_url":"https://api.github.com/users/ordina-jworks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ordina-jworks/subscriptions","organizations_url":"https://api.github.com/users/ordina-jworks/orgs","repos_url":"https://api.github.com/users/ordina-jworks/repos","events_url":"https://api.github.com/users/ordina-jworks/events{/privacy}","received_events_url":"https://api.github.com/users/ordina-jworks/received_events","type":"Organization","site_admin":false},"repo":{"id":44804684,"node_id":"MDEwOlJlcG9zaXRvcnk0NDgwNDY4NA==","name":"ordina-jworks.github.io","full_name":"ordina-jworks/ordina-jworks.github.io","private":false,"owner":{"login":"ordina-jworks","id":15261659,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MjYxNjU5","avatar_url":"https://avatars0.githubusercontent.com/u/15261659?v=4","gravatar_id":"","url":"https://api.github.com/users/ordina-jworks","html_url":"https://github.com/ordina-jworks","followers_url":"https://api.github.com/users/ordina-jworks/followers","following_url":"https://api.github.com/users/ordina-jworks/following{/other_user}","gists_url":"https://api.github.com/users/ordina-jworks/gists{/gist_id}","starred_url":"https://api.github.com/users/ordina-jworks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ordina-jworks/subscriptions","organizations_url":"https://api.github.com/users/ordina-jworks/orgs","repos_url":"https://api.github.com/users/ordina-jworks/repos","events_url":"https://api.github.com/users/ordina-jworks/events{/privacy}","received_events_url":"https://api.github.com/users/ordina-jworks/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/ordina-jworks/ordina-jworks.github.io","description":"Ordina JWorks Business Unit Tech Blog","fork":false,"url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io","forks_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/forks","keys_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/teams","hooks_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/hooks","issue_events_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/events","assignees_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/tags","blobs_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/languages","stargazers_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/stargazers","contributors_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/contributors","subscribers_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/subscribers","subscription_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/subscription","commits_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/merges","archive_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/downloads","issues_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/labels{/name}","releases_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/releases{/id}","deployments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/deployments","created_at":"2015-10-23T09:56:09Z","updated_at":"2019-02-28T08:33:20Z","pushed_at":"2019-03-02T11:14:14Z","git_url":"git://github.com/ordina-jworks/ordina-jworks.github.io.git","ssh_url":"git@github.com:ordina-jworks/ordina-jworks.github.io.git","clone_url":"https://github.com/ordina-jworks/ordina-jworks.github.io.git","svn_url":"https://github.com/ordina-jworks/ordina-jworks.github.io","homepage":"https://ordina-jworks.github.io/","size":319133,"stargazers_count":16,"watchers_count":16,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":18,"mirror_url":null,"archived":false,"open_issues_count":13,"license":null,"forks":18,"open_issues":13,"watchers":16,"default_branch":"source"}},"base":{"label":"ordina-jworks:source","ref":"source","sha":"b083fcacbe9a615f582a7a2633dfe3626b36f567","user":{"login":"ordina-jworks","id":15261659,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MjYxNjU5","avatar_url":"https://avatars0.githubusercontent.com/u/15261659?v=4","gravatar_id":"","url":"https://api.github.com/users/ordina-jworks","html_url":"https://github.com/ordina-jworks","followers_url":"https://api.github.com/users/ordina-jworks/followers","following_url":"https://api.github.com/users/ordina-jworks/following{/other_user}","gists_url":"https://api.github.com/users/ordina-jworks/gists{/gist_id}","starred_url":"https://api.github.com/users/ordina-jworks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ordina-jworks/subscriptions","organizations_url":"https://api.github.com/users/ordina-jworks/orgs","repos_url":"https://api.github.com/users/ordina-jworks/repos","events_url":"https://api.github.com/users/ordina-jworks/events{/privacy}","received_events_url":"https://api.github.com/users/ordina-jworks/received_events","type":"Organization","site_admin":false},"repo":{"id":44804684,"node_id":"MDEwOlJlcG9zaXRvcnk0NDgwNDY4NA==","name":"ordina-jworks.github.io","full_name":"ordina-jworks/ordina-jworks.github.io","private":false,"owner":{"login":"ordina-jworks","id":15261659,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE1MjYxNjU5","avatar_url":"https://avatars0.githubusercontent.com/u/15261659?v=4","gravatar_id":"","url":"https://api.github.com/users/ordina-jworks","html_url":"https://github.com/ordina-jworks","followers_url":"https://api.github.com/users/ordina-jworks/followers","following_url":"https://api.github.com/users/ordina-jworks/following{/other_user}","gists_url":"https://api.github.com/users/ordina-jworks/gists{/gist_id}","starred_url":"https://api.github.com/users/ordina-jworks/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ordina-jworks/subscriptions","organizations_url":"https://api.github.com/users/ordina-jworks/orgs","repos_url":"https://api.github.com/users/ordina-jworks/repos","events_url":"https://api.github.com/users/ordina-jworks/events{/privacy}","received_events_url":"https://api.github.com/users/ordina-jworks/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/ordina-jworks/ordina-jworks.github.io","description":"Ordina JWorks Business Unit Tech Blog","fork":false,"url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io","forks_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/forks","keys_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/teams","hooks_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/hooks","issue_events_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/events{/number}","events_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/events","assignees_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/assignees{/user}","branches_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/branches{/branch}","tags_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/tags","blobs_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/refs{/sha}","trees_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/statuses/{sha}","languages_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/languages","stargazers_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/stargazers","contributors_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/contributors","subscribers_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/subscribers","subscription_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/subscription","commits_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/commits{/sha}","git_commits_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/git/commits{/sha}","comments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/comments{/number}","issue_comment_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/comments{/number}","contents_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/contents/{+path}","compare_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/merges","archive_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/downloads","issues_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues{/number}","pulls_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls{/number}","milestones_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/milestones{/number}","notifications_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/labels{/name}","releases_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/releases{/id}","deployments_url":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/deployments","created_at":"2015-10-23T09:56:09Z","updated_at":"2019-02-28T08:33:20Z","pushed_at":"2019-03-02T11:14:14Z","git_url":"git://github.com/ordina-jworks/ordina-jworks.github.io.git","ssh_url":"git@github.com:ordina-jworks/ordina-jworks.github.io.git","clone_url":"https://github.com/ordina-jworks/ordina-jworks.github.io.git","svn_url":"https://github.com/ordina-jworks/ordina-jworks.github.io","homepage":"https://ordina-jworks.github.io/","size":319133,"stargazers_count":16,"watchers_count":16,"language":"CSS","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":18,"mirror_url":null,"archived":false,"open_issues_count":13,"license":null,"forks":18,"open_issues":13,"watchers":16,"default_branch":"source"}},"_links":{"self":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489"},"html":{"href":"https://github.com/ordina-jworks/ordina-jworks.github.io/pull/489"},"issue":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/489"},"comments":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/issues/489/comments"},"review_comments":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489/comments"},"review_comment":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/pulls/489/commits"},"statuses":{"href":"https://api.github.com/repos/ordina-jworks/ordina-jworks.github.io/statuses/6f51ad9ded6c02d1341feb260ba1a6ec4fb39c96"}},"author_association":"NONE"}}
{"actor":{"display_login":"yannickdeturck"}}