├── .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 | 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 | 12 | 13 | 47 | 48 | 57 | -------------------------------------------------------------------------------- /src/components/TodoList.vue: -------------------------------------------------------------------------------- 1 | 2 | 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 | 6 | 7 | 12 | 13 | 16 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 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 | --------------------------------------------------------------------------------