├── static
└── .gitkeep
├── config
├── prod.env.js
├── dev.env.js
└── index.js
├── vue-shim.d.ts
├── .gitignore
├── .editorconfig
├── .postcssrc.js
├── index.html
├── .babelrc
├── tsconfig.json
├── src
├── store
│ ├── index.ts
│ ├── login.ts
│ ├── plugin.ts
│ └── todos.ts
├── types.ts
├── main.ts
└── App.vue
├── README.md
└── package.json
/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | NODE_ENV: '"production"'
3 | }
4 |
--------------------------------------------------------------------------------
/vue-shim.d.ts:
--------------------------------------------------------------------------------
1 | declare module "*.vue" {
2 | import Vue from 'vue'
3 | export default Vue
4 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | var merge = require('webpack-merge')
2 | var prodEnv = require('./prod.env')
3 |
4 | module.exports = merge(prodEnv, {
5 | NODE_ENV: '"development"'
6 | })
7 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserlist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | vue-typescript-starter
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", { "modules": false }],
4 | "stage-2"
5 | ],
6 | "plugins": ["transform-runtime"],
7 | "comments": false,
8 | "env": {
9 | "test": {
10 | "presets": ["env", "stage-2"],
11 | "plugins": [ "istanbul" ]
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [
4 | "dom",
5 | "es5",
6 | "es2015",
7 | "es2016"
8 | ],
9 | "module": "esnext",
10 | "moduleResolution": "node",
11 | "target": "es5",
12 | "sourceMap": true,
13 | "emitDecoratorMetadata": true,
14 | "experimentalDecorators": true,
15 | "allowSyntheticDefaultImports": true
16 | }
17 | }
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import { todos } from './todos'
4 | import { history } from './plugin'
5 |
6 | Vue.use(Vuex)
7 |
8 | export const store = new Vuex.Store({
9 | state: {
10 | count: 0
11 | },
12 | mutations: {
13 | sum(state) {
14 | state.count += 1
15 | }
16 | },
17 | modules: {
18 | todos
19 | },
20 | plugins: [history({
21 | persist: true
22 | })]
23 | })
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { MutationPayload } from 'vuex'
2 |
3 | // Store
4 | export interface RootState {
5 | count: number
6 | todos: TodoState
7 | login: LoginState
8 | }
9 |
10 | export interface TodoState {
11 | todos: Todo[]
12 | }
13 |
14 | export interface LoginState {
15 | user: string,
16 | isLoggedIn: boolean
17 | }
18 |
19 | export interface HistoryState {
20 | history: MutationPayload[]
21 | }
22 |
23 | export interface PluginOptions {
24 | persist?: boolean
25 | }
26 |
27 | // Models
28 | export interface Todo {
29 | text: string,
30 | checked: boolean
31 | }
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App.vue'
5 | import { store } from './store'
6 |
7 | Vue.config.productionTip = false
8 |
9 | const load = true
10 |
11 | if (load) {
12 | import('./store/login').then(({ login }) => {
13 | store.registerModule('login', login)
14 | })
15 | }
16 |
17 | /* eslint-disable no-new */
18 | new Vue({
19 | el: '#app',
20 | store,
21 | template: '',
22 | components: { App }
23 | })
24 |
--------------------------------------------------------------------------------
/src/store/login.ts:
--------------------------------------------------------------------------------
1 | import { Store, GetterTree, MutationTree, Module } from 'vuex'
2 | import { RootState, LoginState } from '../types'
3 |
4 | const state: LoginState = {
5 | user: '',
6 | isLoggedIn: false
7 | }
8 |
9 | const mutations: MutationTree = {
10 | login(state) {
11 | state.isLoggedIn = true
12 | state.user = 'Alex'
13 | }
14 | }
15 |
16 | export const login: Module = {
17 | state,
18 | mutations,
19 | namespaced: true
20 | }
21 |
22 | export function load(store: Store) {
23 | store.registerModule('login', login)
24 | }
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue TypeScript Starter
2 |
3 | Basic starter based on [Webpack](https://github.com/vuejs-templates/webpack) from [Vue cli](https://github.com/vuejs/vue-cli)
4 |
5 | ## How to TypeScriptify your Vue project
6 |
7 | Here are the steps taken in this starter:
8 |
9 | - Add [tsconfig.json](https://github.com/alexjoverm/Vue-Typescript-Starter/blob/master/tsconfig.json)
10 | - Add [tsloader to build/webpack.base.conf.js](https://github.com/alexjoverm/Vue-Typescript-Starter/blob/master/build/webpack.base.conf.js#L30), plus add/update extensions to ts. Remember to install ts-loader and TypeScript
11 | - Add [vue-shim.d.ts](https://github.com/alexjoverm/Vue-Typescript-Starter/blob/master/vue-shim.d.ts) in order to TypeScript recognize and treat .vue files
12 | - [build/vue-loader.conf.js](https://github.com/alexjoverm/Vue-Typescript-Starter/blob/master/build/vue-loader.conf.js#L12): add `esModule: true`
13 | - Rename `.js` to `.ts` files in `src` folder
14 | - Use `lang="ts"` in .vue files
--------------------------------------------------------------------------------
/src/store/plugin.ts:
--------------------------------------------------------------------------------
1 | import { Store, Module } from 'vuex'
2 | import { HistoryState, PluginOptions, RootState } from '../types'
3 |
4 | const historyModule: Module = {
5 | state: {
6 | history: []
7 | },
8 | mutations: {
9 | add(state, mutation) {
10 | state.history.push(mutation)
11 | },
12 | save(state) {
13 | localStorage.setItem('history', JSON.stringify(state.history))
14 | },
15 | load(state) {
16 | state.history = JSON.parse(localStorage.getItem('history') || '[]')
17 | }
18 | },
19 | namespaced: true
20 | }
21 |
22 | export const history = (options: PluginOptions = {}) =>
23 | (store: Store) => {
24 | const ignoreMutations = ['history/add', 'history/save']
25 |
26 | store.registerModule('history', historyModule)
27 |
28 | if (options.persist) {
29 | store.commit('history/load')
30 | }
31 |
32 | store.subscribe((mutation, state) => {
33 | if (!ignoreMutations.includes(mutation.type)) {
34 | console.log(mutation)
35 | store.commit('history/add', mutation)
36 |
37 | if (options.persist) {
38 | store.commit('history/save')
39 | }
40 | }
41 | })
42 | }
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | // see http://vuejs-templates.github.io/webpack for documentation.
2 | var path = require('path')
3 |
4 | module.exports = {
5 | build: {
6 | env: require('./prod.env'),
7 | index: path.resolve(__dirname, '../dist/index.html'),
8 | assetsRoot: path.resolve(__dirname, '../dist'),
9 | assetsSubDirectory: 'static',
10 | assetsPublicPath: '/',
11 | productionSourceMap: true,
12 | // Gzip off by default as many popular static hosts such as
13 | // Surge or Netlify already gzip all static assets for you.
14 | // Before setting to `true`, make sure to:
15 | // npm install --save-dev compression-webpack-plugin
16 | productionGzip: false,
17 | productionGzipExtensions: ['js', 'css'],
18 | // Run the build command with an extra argument to
19 | // View the bundle analyzer report after build finishes:
20 | // `npm run build --report`
21 | // Set to `true` or `false` to always turn it on or off
22 | bundleAnalyzerReport: process.env.npm_config_report
23 | },
24 | dev: {
25 | env: require('./dev.env'),
26 | port: 8080,
27 | autoOpenBrowser: false,
28 | assetsSubDirectory: 'static',
29 | assetsPublicPath: '/',
30 | proxyTable: {},
31 | // CSS Sourcemaps off by default because relative paths are "buggy"
32 | // with this option, according to the CSS-Loader README
33 | // (https://github.com/webpack/css-loader#sourcemaps)
34 | // In our experience, they generally work as expected,
35 | // just be aware of this issue when enabling this option.
36 | cssSourceMap: false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/store/todos.ts:
--------------------------------------------------------------------------------
1 | import { GetterTree, MutationTree, ActionTree, Module } from 'vuex'
2 | import { RootState, TodoState, Todo } from '../types'
3 |
4 | type TodoGetter = GetterTree
5 |
6 | export const state: TodoState = {
7 | todos: [
8 | { text: 'Buy milk', checked: false },
9 | { text: 'Buy salad', checked: true },
10 | { text: 'Get haircut', checked: true }
11 | ]
12 | }
13 |
14 | export const getters: TodoGetter = {
15 | // With 3 parameters, you access the root state
16 | todos: (state, getters, rootState) => state.todos.filter(todo => !todo.checked),
17 | dones: state => state.todos.filter(todo => todo.checked)
18 | }
19 |
20 | export const mutations: MutationTree = {
21 | addTodo(state, newTodo) {
22 | const todoCopy = Object.assign({}, newTodo)
23 | state.todos.push(todoCopy)
24 | },
25 | toggleTodo(state, todo) {
26 | todo.checked = !todo.checked
27 | }
28 | }
29 |
30 | export const actions: ActionTree = {
31 | addTodoAsync({commit, dispatch, rootState}, id) {
32 | fetch('https://jsonplaceholder.typicode.com/posts/' + id)
33 | .then(data => data.json())
34 | .then(item => {
35 | const todo: Todo = {
36 | checked: false,
37 | text: rootState.login.user + ': ' + item.title
38 | }
39 |
40 | commit('addTodo', todo)
41 | commit('login/login', null, { root: true })
42 | // dispatch('actionName', null, { root: true })
43 | })
44 | }
45 | }
46 |
47 | export const todos: Module = {
48 | state,
49 | getters,
50 | mutations,
51 | actions,
52 | namespaced: true
53 | }
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Hello {{ login.user }}
6 |
7 |
8 |
To do
9 |
14 |
15 |
Done
16 |
21 |
22 |
Add todo:
23 |
Add Async:
24 |
25 |
26 |
27 |
58 |
59 |
60 |
61 |
71 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-typescript-starter",
3 | "version": "1.0.0",
4 | "description": "Typescript starter based on the Vue-cli webpack template",
5 | "author": "Alex J ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "start": "node build/dev-server.js",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "vue": "^2.2.6",
14 | "vue-property-decorator": "^5.1.0",
15 | "vue-router": "^2.3.1",
16 | "vuex": "^2.3.1",
17 | "vuex-class": "^0.2.0"
18 | },
19 | "devDependencies": {
20 | "autoprefixer": "^7.1.2",
21 | "babel-core": "^6.22.1",
22 | "babel-loader": "^7.1.1",
23 | "babel-plugin-transform-runtime": "^6.22.0",
24 | "babel-preset-env": "^1.3.2",
25 | "babel-preset-stage-2": "^6.22.0",
26 | "babel-register": "^6.22.0",
27 | "chalk": "^2.0.1",
28 | "connect-history-api-fallback": "^1.3.0",
29 | "copy-webpack-plugin": "^4.0.1",
30 | "css-loader": "^0.28.0",
31 | "eventsource-polyfill": "^0.9.6",
32 | "express": "^4.14.1",
33 | "extract-text-webpack-plugin": "^3.0.0",
34 | "file-loader": "^0.11.1",
35 | "friendly-errors-webpack-plugin": "^1.1.3",
36 | "html-webpack-plugin": "^2.28.0",
37 | "http-proxy-middleware": "^0.17.3",
38 | "opn": "^5.1.0",
39 | "optimize-css-assets-webpack-plugin": "^2.0.0",
40 | "ora": "^1.2.0",
41 | "rimraf": "^2.6.0",
42 | "semver": "^5.3.0",
43 | "shelljs": "^0.7.6",
44 | "ts-loader": "^2.0.3",
45 | "typescript": "^2.3.2",
46 | "url-loader": "^0.5.8",
47 | "vue-loader": "^12.2.2",
48 | "vue-style-loader": "^3.0.1",
49 | "vue-template-compiler": "^2.2.6",
50 | "webpack": "^3.3.0",
51 | "webpack-bundle-analyzer": "^2.2.1",
52 | "webpack-dev-middleware": "^1.10.0",
53 | "webpack-hot-middleware": "^2.18.0",
54 | "webpack-merge": "^4.1.0"
55 | },
56 | "engines": {
57 | "node": ">= 4.0.0",
58 | "npm": ">= 3.0.0"
59 | },
60 | "browserslist": [
61 | "> 1%",
62 | "last 2 versions",
63 | "not ie <= 8"
64 | ]
65 | }
66 |
--------------------------------------------------------------------------------