├── .babelrc
├── .env
├── .gitignore
├── LICENSE
├── README.md
├── package-lock.json
├── package.json
├── src
├── App.vue
├── app.ts
├── components
│ ├── TodoItem.vue
│ └── TodoList.vue
├── public
│ ├── favicon.ico
│ └── index.html
├── router
│ └── index.ts
├── shims-vue.d.ts
├── store
│ └── index.ts
└── views
│ ├── About.vue
│ └── Home.vue
├── tsconfig.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/env",
4 | "@babel/typescript"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | BASE_URL=/
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /dist
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vlad Starkovsky
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue 3 webpack boilerplate
2 |
3 | This is preview version Vue 3, DO NOT USE IN PRODUCTION!
4 |
5 | ## Includes
6 |
7 | - Vue 3.0.0-beta.18
8 | - Vue Router 4.0.0-beta.1
9 | - Vuex 4.0.0-beta.4
10 | - Typescript 3.9.6
11 | - Babel 7.10.4
12 | - Webpack 4.43.0
13 |
14 |
15 | ## Project setup
16 | ```
17 | npm install
18 | ```
19 |
20 | ### Compiles and hot-reloads for development
21 | ```
22 | npm run serve
23 | ```
24 |
25 | ### Compiles and minifies for production
26 | ```
27 | npm run build
28 | ```
29 |
30 | ### To Do
31 | - webpack 5
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@starkovsky/vue3-webpack-boilerplate",
3 | "version": "1.0.0",
4 | "description": "",
5 | "private": true,
6 | "scripts": {
7 | "serve": "webpack-dev-server",
8 | "build": "webpack --env.production",
9 | "dev": "webpack",
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "author": "Vlad Starkovsky",
13 | "license": "ISC",
14 | "dependencies": {
15 | "vue": "^3.0.0-beta.18",
16 | "vue-router": "^4.0.0-beta.1",
17 | "vuex": "^4.0.0-beta.4"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.10.4",
21 | "@babel/preset-env": "^7.10.4",
22 | "@babel/preset-typescript": "^7.10.4",
23 | "@vue/compiler-sfc": "^3.0.0-beta.18",
24 | "babel-loader": "^8.1.0",
25 | "clean-webpack-plugin": "^3.0.0",
26 | "css-loader": "^3.6.0",
27 | "dotenv": "^8.2.0",
28 | "html-webpack-plugin": "^3.2.0",
29 | "mini-css-extract-plugin": "^0.9.0",
30 | "style-loader": "^1.2.1",
31 | "ts-loader": "^6.2.2",
32 | "typescript": "^3.9.6",
33 | "vue-loader": "^16.0.0-beta.4",
34 | "webpack": "^4.43.0",
35 | "webpack-cli": "^3.3.12",
36 | "webpack-dev-server": "^3.11.0",
37 | "webpackbar": "^4.0.0"
38 | },
39 | "peerDependencies": {
40 | "webpack": "^4.1.0 || ^5.0.0-0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Home
5 | About
6 |
7 |
8 |
9 |
10 |
11 |
18 |
19 |
42 |
--------------------------------------------------------------------------------
/src/app.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import { router } from './router';
3 | import { store } from './store';
4 |
5 | import App from "./App.vue";
6 |
7 | createApp(App)
8 | .use(router)
9 | .use(store)
10 | .mount('#app');
11 |
--------------------------------------------------------------------------------
/src/components/TodoItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
{{ todo.title }}
9 |
10 |
11 |
12 |
13 |
47 |
48 |
57 |
--------------------------------------------------------------------------------
/src/components/TodoList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
11 |
12 |
13 | {{ todoList }}
14 |
15 |
16 |
17 |
18 |
61 |
62 |
65 |
--------------------------------------------------------------------------------
/src/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starkovsky/vue3-webpack-boilerplate/0bd0febb7a41c3643935f78a353498cf4bd034e8/src/public/favicon.ico
--------------------------------------------------------------------------------
/src/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | VueApp
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | import {createRouter, createWebHistory} from 'vue-router';
2 | import Home from "../views/Home.vue";
3 | import About from "../views/About.vue";
4 |
5 | const routes = [
6 | {
7 | path: '/',
8 | component: Home,
9 | name: 'home'
10 | },
11 | {
12 | path: '/about',
13 | component: About,
14 | name: 'about'
15 | },
16 | ];
17 |
18 | export const router = createRouter({
19 | history: createWebHistory(),
20 | routes
21 | });
22 |
--------------------------------------------------------------------------------
/src/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.vue' {
2 | import { ComponentOptions } from 'vue'
3 | const component: ComponentOptions;
4 | export default component
5 | }
6 |
7 | declare module 'vuex'
8 |
--------------------------------------------------------------------------------
/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import {createStore} from 'vuex'
2 |
3 | type Todo = {
4 | id: number,
5 | complete: boolean,
6 | title: string,
7 | }
8 |
9 | type State = {
10 | todoList: Array
11 | }
12 |
13 | const state: State = {
14 | todoList: []
15 | };
16 |
17 | const mutations = {
18 | createTodo(state: State, todo: Todo) {
19 | state.todoList.push({
20 | id: todo.id,
21 | complete: todo.complete,
22 | title: todo.title,
23 | });
24 | },
25 | editTodo(state: State, todo: Todo) {
26 | const index = state.todoList.findIndex(
27 | item => item.id === todo.id
28 | );
29 | state.todoList[index] = todo;
30 | },
31 | removeTodo(state: State, id: number) {
32 | state.todoList = state.todoList.filter(
33 | item => item.id !== id
34 | );
35 | }
36 | };
37 |
38 | export const store = createStore({ state, mutations });
39 |
--------------------------------------------------------------------------------
/src/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | About Page
4 |
5 |
6 |
7 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/src/views/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home Page
4 |
5 |
6 |
7 |
8 |
9 |
20 |
21 |
24 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "strict": true,
6 | "jsx": "preserve",
7 | "importHelpers": true,
8 | "moduleResolution": "node",
9 | "esModuleInterop": true,
10 | "allowSyntheticDefaultImports": true,
11 | "sourceMap": true,
12 | "baseUrl": ".",
13 | "paths": {
14 | "@/*": [
15 | "src/*"
16 | ]
17 | },
18 | "lib": [
19 | "esnext",
20 | "dom",
21 | "dom.iterable",
22 | "scripthost"
23 | ],
24 | "types": [
25 | "@vue/compiler-core/dist/compiler-core",
26 | "@vue/compiler-dom/dist/compiler-dom",
27 | "@vue/compiler-sfc/dist/compiler-sfc",
28 | "@vue/compiler-ssr/dist/compiler-ssr",
29 | "@vue/reactivity/dist/reactivity",
30 | "@vue/runtime-core/dist/runtime-core",
31 | "@vue/runtime-dom/dist/runtime-dom"
32 | ]
33 | },
34 | "include": [
35 | "src/**/*.ts",
36 | "src/**/*.tsx",
37 | "src/**/*.vue"
38 | ],
39 | "exclude": [
40 | "node_modules"
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // webpack config
2 | const path = require('path');
3 | const WebpackBar = require('webpackbar');
4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
7 |
8 | const { VueLoaderPlugin } = require('vue-loader');
9 |
10 | module.exports = (env = {}) => ({
11 | context: path.resolve(__dirname, 'src'),
12 | mode: env.production ? 'production' : 'development',
13 | entry: {
14 | app: './app.ts'
15 | },
16 | output: {
17 | path: path.resolve(__dirname, "dist"),
18 | filename: "[name].[hash:6].bundle.js",
19 | publicPath: process.env.BASE_URL,
20 | },
21 | module: {
22 | rules: [
23 | {
24 | test: /\.vue$/,
25 | use: 'vue-loader'
26 | },
27 | {
28 | test: /\.js$/,
29 | exclude: /node_modules/,
30 | loader: "babel-loader"
31 | },
32 | {
33 | test: /\.ts$/,
34 | exclude: /node_modules/,
35 | use: [
36 | {
37 | loader: "babel-loader",
38 | options: { babelrc: true }
39 | },
40 | {
41 | loader: "ts-loader",
42 | options: { appendTsSuffixTo: [/\.vue$/] }
43 | }
44 | ]
45 | },
46 | {
47 | test: /\.css$/,
48 | use: [
49 | {
50 | loader: MiniCssExtractPlugin.loader,
51 | options: { hmr: !env.production }
52 | },
53 | 'css-loader'
54 | ]
55 | },
56 | ],
57 | },
58 | resolve: {
59 | extensions: ['.ts', '.js', '.vue', '.json'],
60 | alias: {
61 | 'vue': '@vue/runtime-dom'
62 | }
63 | },
64 | plugins: [
65 | new CleanWebpackPlugin(),
66 | new HtmlWebpackPlugin({
67 | template: './public/index.html'
68 | }),
69 | new MiniCssExtractPlugin({
70 | filename: '[name].css'
71 | }),
72 | new WebpackBar(),
73 | new VueLoaderPlugin(),
74 | ],
75 | optimization: {
76 | runtimeChunk: 'single',
77 | splitChunks: {
78 | cacheGroups: {
79 | vendor: {
80 | test: /[\\/]node_modules[\\/]/,
81 | name: 'vendors',
82 | chunks: 'all'
83 | }
84 | }
85 | }
86 | },
87 | devtool: 'source-map',
88 | devServer: {
89 | contentBase: path.join(__dirname, 'src/public'),
90 | publicPath: process.env.BASE_URL,
91 | index: './index.html',
92 | hot: true,
93 | stats: 'minimal',
94 | quiet: true,
95 | overlay: {
96 | warnings: true,
97 | errors: true
98 | },
99 | historyApiFallback: true,
100 | }
101 | });
102 |
--------------------------------------------------------------------------------