├── .gitignore ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── README.md ├── app.rb ├── config.ru ├── package.json ├── public ├── 89889688147bd7575d6327160d64e760.svg ├── build-a744d488c8a67ccd63a4.js ├── build-a744d488c8a67ccd63a4.js.map ├── glyphicons-halflings-regular.svg └── index.html ├── src ├── client │ └── client.js ├── components │ ├── App.vue │ ├── ListItem.vue │ ├── MainComponent.vue │ └── ShowItem.vue ├── index_template.html ├── main.js ├── pages │ ├── ErrorPage.vue │ ├── ItemPage.vue │ └── MainPage.vue ├── routes │ └── router.js ├── store │ └── store.js └── styles │ ├── custom.scss │ └── main.css ├── webpack.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/ruby,node 3 | 4 | ### Node ### 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # Bower dependency directory (https://bower.io/) 31 | bower_components 32 | 33 | # node-waf configuration 34 | .lock-wscript 35 | 36 | # Compiled binary addons (http://nodejs.org/api/addons.html) 37 | build/Release 38 | 39 | # Dependency directories 40 | node_modules/ 41 | jspm_packages/ 42 | 43 | # Typescript v1 declaration files 44 | typings/ 45 | 46 | # Optional npm cache directory 47 | .npm 48 | 49 | # Optional eslint cache 50 | .eslintcache 51 | 52 | # Optional REPL history 53 | .node_repl_history 54 | 55 | # Output of 'npm pack' 56 | *.tgz 57 | 58 | # Yarn Integrity file 59 | .yarn-integrity 60 | 61 | # dotenv environment variables file 62 | .env 63 | 64 | 65 | ### Ruby ### 66 | *.gem 67 | *.rbc 68 | /.config 69 | /coverage/ 70 | /InstalledFiles 71 | /pkg/ 72 | /spec/reports/ 73 | /spec/examples.txt 74 | /test/tmp/ 75 | /test/version_tmp/ 76 | /tmp/ 77 | 78 | # Used by dotenv library to load environment variables. 79 | # .env 80 | 81 | ## Specific to RubyMotion: 82 | .dat* 83 | .repl_history 84 | build/ 85 | *.bridgesupport 86 | build-iPhoneOS/ 87 | build-iPhoneSimulator/ 88 | 89 | ## Specific to RubyMotion (use of CocoaPods): 90 | # 91 | # We recommend against adding the Pods directory to your .gitignore. However 92 | # you should judge for yourself, the pros and cons are mentioned at: 93 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 94 | # 95 | # vendor/Pods/ 96 | 97 | ## Documentation cache and generated files: 98 | /.yardoc/ 99 | /_yardoc/ 100 | /doc/ 101 | /rdoc/ 102 | 103 | ## Environment normalization: 104 | /.bundle/ 105 | /vendor/bundle 106 | /lib/bundler/man/ 107 | 108 | # for a library or gem, you might want to ignore these files since the code is 109 | # intended to run in multiple environments; otherwise, check them in: 110 | # Gemfile.lock 111 | # .ruby-version 112 | # .ruby-gemset 113 | 114 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 115 | .rvmrc 116 | 117 | # db 118 | *.db 119 | 120 | # End of https://www.gitignore.io/api/ruby,node 121 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-2.4.1 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | ruby '2.4.1' 3 | 4 | gem 'sinatra', '~> 2.0.0' 5 | gem 'sinatra-contrib' 6 | gem 'sequel' 7 | gem 'foreman' 8 | gem 'sqlite3' 9 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.2.1) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (>= 0.7, < 2) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | backports (3.11.4) 10 | concurrent-ruby (1.0.5) 11 | foreman (0.85.0) 12 | thor (~> 0.19.1) 13 | i18n (1.1.0) 14 | concurrent-ruby (~> 1.0) 15 | minitest (5.11.3) 16 | multi_json (1.13.1) 17 | mustermann (1.0.3) 18 | rack (2.0.6) 19 | rack-protection (2.0.4) 20 | rack 21 | sequel (5.12.0) 22 | sinatra (2.0.4) 23 | mustermann (~> 1.0) 24 | rack (~> 2.0) 25 | rack-protection (= 2.0.4) 26 | tilt (~> 2.0) 27 | sinatra-contrib (2.0.4) 28 | activesupport (>= 4.0.0) 29 | backports (>= 2.8.2) 30 | multi_json 31 | mustermann (~> 1.0) 32 | rack-protection (= 2.0.4) 33 | sinatra (= 2.0.4) 34 | tilt (>= 1.3, < 3) 35 | sqlite3 (1.3.13) 36 | thor (0.19.4) 37 | thread_safe (0.3.6) 38 | tilt (2.0.8) 39 | tzinfo (1.2.5) 40 | thread_safe (~> 0.1) 41 | 42 | PLATFORMS 43 | ruby 44 | 45 | DEPENDENCIES 46 | foreman 47 | sequel 48 | sinatra (~> 2.0.0) 49 | sinatra-contrib 50 | sqlite3 51 | 52 | RUBY VERSION 53 | ruby 2.4.1p111 54 | 55 | BUNDLED WITH 56 | 1.16.1 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | front-end: bundle exec rackup 2 | back-end: yarn run dev 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sinatra Webpack vue.js SPA template project 2 | 3 | ## Build Setup 4 | ``` 5 | bundle install 6 | yarn 7 | ``` 8 | 9 | ## run development 10 | ``` 11 | foreman start 12 | # for back-end 13 | # open http://localhost:9292 14 | # for front-end 15 | # open http://localhost:8080 16 | ``` 17 | 18 | ## run production 19 | ``` 20 | yarn run build 21 | APP_ENV=production bundle exec rackup 22 | # open http://localhost:9292 23 | ``` 24 | -------------------------------------------------------------------------------- /app.rb: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'sinatra' 3 | require 'sinatra/json' 4 | require 'sinatra/namespace' 5 | require 'sinatra/base' 6 | require 'sinatra/reloader' 7 | require 'sequel' 8 | require 'sqlite3' 9 | require 'json' 10 | Bundler.require 11 | set :erb, escape_html: true 12 | 13 | ## 14 | # prepare 15 | DB = Sequel.sqlite 16 | DB.create_table :items do 17 | primary_key :id 18 | String :title 19 | end 20 | items = DB[:items] 21 | [ 22 | { id: '1', title: 'First item' }, 23 | { id: '2', title: 'Second item' }, 24 | { id: '3', title: 'Third item' }, 25 | { id: '4', title: 'Fourth item' }, 26 | { id: '5', title: 'Fifth item' } 27 | ].each { |item| items.insert(:title => item[:title]) } 28 | 29 | ## 30 | # app 31 | class App < Sinatra::Base 32 | register Sinatra::Namespace 33 | configure :development do 34 | register Sinatra::Reloader 35 | end 36 | 37 | get '/' do 38 | File.read(File.join('public', 'index.html')) 39 | end 40 | 41 | namespace '/api/items' do 42 | get '' do 43 | json items: DB[:items].all 44 | end 45 | 46 | post '' do 47 | request.body.rewind 48 | param = JSON.parse(request.body.read) 49 | title = param['title'] || '' 50 | DB[:items].insert(:title => title) 51 | json success: true 52 | end 53 | 54 | get '/:id' do 55 | json item: DB[:items].where(:id => params['id']).first 56 | end 57 | 58 | delete '/:id' do 59 | DB[:items].filter(:id => params['id']).delete 60 | json success: true 61 | end 62 | end 63 | 64 | not_found do 65 | File.read(File.join('public', 'index.html')) 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require './app' 2 | 3 | run App 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sinatra-webpack-vuejs-template", 3 | "description": "Sinatra Webpack vue.js SPA template", 4 | "version": "0.0.4", 5 | "author": "vkopylov ", 6 | "private": false, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", 9 | "build": "cross-env NODE_ENV=production webpack --progress --hide-modules" 10 | }, 11 | "dependencies": { 12 | "axios": "^0.16.2", 13 | "bootstrap": "3.3.7", 14 | "jquery": "^3.0.0", 15 | "vue": "^2.5.3", 16 | "vue-router": "^2.7.0", 17 | "vuex": "^3.0.0", 18 | "vuex-router-sync": "" 19 | }, 20 | "devDependencies": { 21 | "autoprefixer": "^7.1.4", 22 | "babel-core": "^6.26.0", 23 | "babel-loader": "^7.1.2", 24 | "babel-preset-env": "^1.6.0", 25 | "clean-webpack-plugin": "^0.1.17", 26 | "cross-env": "^5.0.5", 27 | "css-loader": "^0.28.7", 28 | "extract-text-webpack-plugin": "3.0.0", 29 | "file-loader": "^0.11.2", 30 | "html-webpack-plugin": "^2.30.1", 31 | "node-sass": "", 32 | "postcss": "^6.0.11", 33 | "postcss-loader": "^2.0.6", 34 | "precss": "", 35 | "sanitize.css": "^5.0.0", 36 | "sass-loader": "", 37 | "style-loader": "", 38 | "url-loader": "", 39 | "vue-loader": "^12.1.0", 40 | "vue-template-compiler": "^2.3.3", 41 | "webpack": "^3.6.0", 42 | "webpack-dev-server": "^2.4.5", 43 | "webpack-merge": "^4.1.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /public/89889688147bd7575d6327160d64e760.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | -------------------------------------------------------------------------------- /public/glyphicons-halflings-regular.svg: -------------------------------------------------------------------------------- 1 | module.exports = __webpack_public_path__ + "89889688147bd7575d6327160d64e760.svg"; -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | TITLE 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /src/client/client.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | export default (function(){ 4 | return{ 5 | 6 | get_all: function(){ 7 | return axios.get('/api/items') 8 | }, 9 | 10 | create_new: function(title){ 11 | return axios.post('/api/items', {title: title}) 12 | }, 13 | 14 | show_one: function(id){ 15 | return axios.get('/api/items/' + id) 16 | }, 17 | 18 | delete: function(id){ 19 | return axios.delete('/api/items/' + id) 20 | } 21 | }; 22 | })(); 23 | -------------------------------------------------------------------------------- /src/components/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /src/components/ListItem.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 34 | -------------------------------------------------------------------------------- /src/components/MainComponent.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 76 | -------------------------------------------------------------------------------- /src/components/ShowItem.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 35 | -------------------------------------------------------------------------------- /src/index_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | TITLE 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // 2 | // Libraries 3 | // 4 | import Vue from 'vue' 5 | import Vuex from 'vuex' 6 | Vue.use(Vuex) 7 | import client from './client/client.js' 8 | import store from './store/store.js' 9 | import 'bootstrap'; 10 | 11 | // 12 | // Styles 13 | // 14 | import 'sanitize.css'; 15 | import 'bootstrap/dist/css/bootstrap.min.css'; 16 | // for your css-styles 17 | import './styles/main.css'; 18 | // or for scss 19 | import './styles/custom.scss'; 20 | 21 | // 22 | // Settings 23 | // 24 | Vue.config.debug = process.env.NODE_ENV == 'development' 25 | Vue.config.devtools = process.env.NODE_ENV == 'development' 26 | Vue.config.productionTip = process.env.NODE_ENV == 'development' 27 | Vue.config.silent = process.env.NODE_ENV != 'development' 28 | 29 | // 30 | // Vue Router 31 | // 32 | import router from './routes/router' 33 | import {sync} from 'vuex-router-sync' 34 | sync(store, router); 35 | 36 | // 37 | // Vue 38 | // 39 | import App from './components/App.vue' 40 | 41 | document.vueApp = new Vue({ 42 | el: '#mainapp', 43 | router, 44 | store, 45 | render: function(h){ return h(App);} 46 | }); 47 | -------------------------------------------------------------------------------- /src/pages/ErrorPage.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /src/pages/ItemPage.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /src/pages/MainPage.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | -------------------------------------------------------------------------------- /src/routes/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import MainPage from '../pages/MainPage.vue' 4 | import ItemPage from '../pages/ItemPage.vue' 5 | import ErrorPage from '../pages/ErrorPage.vue' 6 | 7 | Vue.use(Router); 8 | 9 | export default new Router({ 10 | mode: 'history', 11 | routes: [ 12 | { 13 | path: '/', 14 | name: 'main_page', 15 | component: MainPage 16 | }, 17 | { 18 | path: '/show/:id', 19 | name: 'show_item', 20 | component: ItemPage 21 | }, 22 | { 23 | path: '*', 24 | name: 'error', 25 | component: ErrorPage 26 | }, 27 | ], 28 | scrollBehavior(to, from, savedPosition) { 29 | return {x: 0, y: 0} 30 | } 31 | }); 32 | -------------------------------------------------------------------------------- /src/store/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import client from './../client/client.js' 4 | Vue.use(Vuex); 5 | 6 | const state = { 7 | items: [], 8 | item: { 9 | title: '' 10 | } 11 | }; 12 | 13 | const actions = { 14 | get_all(context){ 15 | let _this = this 16 | client.get_all() 17 | .then(function(response){ 18 | _this.commit('load_items', response.data) 19 | }) 20 | .catch(function(error) { 21 | console.error('error in get_all') 22 | console.error(error) 23 | }) 24 | }, 25 | 26 | create_new(context, title){ 27 | return client.create_new(title) 28 | }, 29 | 30 | show_one(context, id){ 31 | let _this = this 32 | client.show_one(id) 33 | .then(function(response){ 34 | _this.commit('load_item', response.data) 35 | }) 36 | .catch(function(error) { 37 | console.error('error in show_one') 38 | console.error(error) 39 | }) 40 | }, 41 | 42 | delete(context, id){ 43 | return client.delete(id) 44 | }, 45 | 46 | clear_item(context){ 47 | context.commit('clear_item') 48 | } 49 | }; 50 | 51 | const mutations = { 52 | load_items (context, data){ 53 | context.items = data.items 54 | }, 55 | 56 | load_item (context, data){ 57 | context.item = data.item 58 | }, 59 | 60 | clear_items (context){ 61 | context.items = [] 62 | }, 63 | 64 | clear_item(context){ 65 | context.item = { title: '' } 66 | } 67 | }; 68 | 69 | const getters = { 70 | getItem (state){ 71 | return state.item 72 | }, 73 | getItems (state){ 74 | return state.items 75 | }, 76 | }; 77 | 78 | export default new Vuex.Store({ 79 | state: state, 80 | actions: actions, 81 | mutations: mutations, 82 | getters: getters 83 | }); 84 | 85 | -------------------------------------------------------------------------------- /src/styles/custom.scss: -------------------------------------------------------------------------------- 1 | body { 2 | div { 3 | font-size: 30px; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/styles/main.css: -------------------------------------------------------------------------------- 1 | .del_btn{ 2 | float: right; 3 | height: 43px; 4 | line-height: 43px; 5 | } 6 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | let baseConfig = {}; 2 | let config = {}; 3 | let loader = {}; 4 | 5 | const path = require('path'); 6 | const webpack = require('webpack'); 7 | const merge = require('webpack-merge'); 8 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 9 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 10 | const ExtractTextPlugin = require('extract-text-webpack-plugin'); 11 | 12 | loader.css = [ 13 | { 14 | loader: 'style-loader', 15 | options: { 16 | sourceMap: true 17 | } 18 | }, 19 | { 20 | loader: 'css-loader', 21 | options: { 22 | sourceMap: true 23 | } 24 | } 25 | ]; 26 | 27 | baseConfig = { 28 | entry: './src/main.js', 29 | output: { 30 | path: path.resolve(__dirname, './public'), 31 | publicPath: '/' 32 | }, 33 | module: { 34 | rules: [ 35 | { 36 | test: /\.vue$/, 37 | use: { 38 | loader: 'vue-loader', 39 | options: { 40 | loaders: { 41 | coffee: loader.coffee, 42 | stylus: loader.stylus 43 | } 44 | } 45 | } 46 | }, 47 | { 48 | test: /\.(png|jpg|gif|svg)$/, 49 | use: [ 50 | { 51 | loader: 'file-loader', 52 | options: { 53 | name: '[name].[ext]?[hash]' 54 | } 55 | } 56 | ] 57 | }, 58 | { 59 | test: /\.(png|woff|woff2|eot|ttf|svg)$/, 60 | loader: 'url-loader?limit=100000' 61 | }, 62 | { 63 | test: /\.css$/, 64 | use: loader.css 65 | }, 66 | { 67 | test: /\.(scss)$/, 68 | use: [{ 69 | loader: 'style-loader', // inject CSS to page 70 | }, { 71 | loader: 'css-loader', // translates CSS into CommonJS modules 72 | }, { 73 | loader: 'postcss-loader', // Run post css actions 74 | options: { 75 | plugins: function () { // post css plugins, can be exported to postcss.config.js 76 | return [ 77 | require('precss'), 78 | require('autoprefixer') 79 | ]; 80 | } 81 | } 82 | }, { 83 | loader: 'sass-loader' // compiles SASS to CSS 84 | }] 85 | }, 86 | { 87 | test: /\.js$/, 88 | exclude: /node_modules/, 89 | loader: 'babel-loader' 90 | } 91 | ] 92 | }, 93 | resolve: { 94 | alias: { 95 | '@src': path.resolve(__dirname, 'src'), 96 | '@components': path.resolve(__dirname, 'src', 'components'), 97 | '@pages': path.resolve(__dirname, 'src', 'pages'), 98 | '@assets': path.resolve(__dirname, 'src', 'assets'), 99 | '@styles': path.resolve(__dirname, 'src', 'styles'), 100 | 'vue$': 'vue/dist/vue.esm.js' 101 | } 102 | }, 103 | plugins: [ 104 | new HtmlWebpackPlugin({ 105 | template: path.resolve(__dirname, 'src', 'index_template.html') 106 | }), 107 | new webpack.DefinePlugin({ 108 | 'process.env': { 109 | NODE_ENV: `'${process.env.NODE_ENV}'` 110 | } 111 | }), 112 | new webpack.ProvidePlugin({ 113 | '_': 'lodash', 114 | 'axios': 'axios' 115 | }), 116 | // for bootstrap 117 | new webpack.ProvidePlugin({ 118 | $: 'jquery', 119 | jQuery: 'jquery', 120 | 'window.jQuery': 'jquery', 121 | Popper: ['popper.js', 'default'], 122 | // In case you imported plugins individually, you must also require them here: 123 | Util: "exports-loader?Util!bootstrap/js/dist/util", 124 | Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown", 125 | }) 126 | ] 127 | }; 128 | 129 | if (process.env.NODE_ENV === 'production') { 130 | config = merge(baseConfig, { 131 | output: { 132 | filename: 'build-[hash].js' 133 | }, 134 | devtool: '#source-map', 135 | plugins: [ 136 | new CleanWebpackPlugin(['public']), 137 | new webpack.LoaderOptionsPlugin({ 138 | minimize: true 139 | }) 140 | ] 141 | }); 142 | } else { 143 | config = merge(baseConfig, { 144 | output: { 145 | filename: 'build.js' 146 | }, 147 | devtool: '#eval-source-map', 148 | devServer: { 149 | contentBase: 'public', 150 | historyApiFallback: true, 151 | noInfo: true, 152 | proxy: { 153 | "/api": { 154 | target: 'http://localhost:9292', 155 | //changeOrigin: true 156 | } 157 | } 158 | }, 159 | performance: { 160 | hints: false 161 | } 162 | }); 163 | } 164 | 165 | module.exports = config; 166 | --------------------------------------------------------------------------------