mirror of https://github.com/fatedier/frp
fatedier
6 years ago
39 changed files with 16189 additions and 30 deletions
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
@ -0,0 +1 @@
|
||||
<!doctype html> <html lang=en> <head> <meta charset=utf-8> <title>frp client admin UI</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?eb6e6e7683a17c61011d"></script><script type="text/javascript" src="vendor.js?1fbc6539feeed727105b"></script></body> </html> |
@ -1 +1 @@
|
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];l<t.length;l++)a=t[l],o[a]&&s.push(o[a][0]),o[a]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=n(n.s=u[l]);return f};var t={},o={1:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var u=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+""+e+".js?"+{0:"51925ec1a77936b64d61"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,u.appendChild(i),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]); |
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];l<t.length;l++)a=t[l],o[a]&&s.push(o[a][0]),o[a]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=n(n.s=u[l]);return f};var t={},o={1:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var u=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+""+e+".js?"+{0:"1fbc6539feeed727105b"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,u.appendChild(i),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
@ -1 +1 @@
|
||||
<!DOCTYPE html> <html lang=en> <head> <meta charset=utf-8> <title>frps dashboard</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?14bea8276eef86cc7c61"></script><script type="text/javascript" src="vendor.js?51925ec1a77936b64d61"></script></body> </html> |
||||
<!DOCTYPE html> <html lang=en> <head> <meta charset=utf-8> <title>frps dashboard</title> <link rel="shortcut icon" href="favicon.ico"></head> <body> <div id=app></div> <script type="text/javascript" src="manifest.js?bc42bc4eff72df8da372"></script><script type="text/javascript" src="vendor.js?ee403fce53c8757fc931"></script></body> </html> |
@ -0,0 +1 @@
|
||||
!function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,l=0,s=[];l<t.length;l++)a=t[l],o[a]&&s.push(o[a][0]),o[a]=0;for(i in c)Object.prototype.hasOwnProperty.call(c,i)&&(e[i]=c[i]);for(r&&r(t,c,u);s.length;)s.shift()();if(u)for(l=0;l<u.length;l++)f=n(n.s=u[l]);return f};var t={},o={1:0};n.e=function(e){function r(){i.onerror=i.onload=null,clearTimeout(a);var n=o[e];0!==n&&(n&&n[1](new Error("Loading chunk "+e+" failed.")),o[e]=void 0)}var t=o[e];if(0===t)return new Promise(function(e){e()});if(t)return t[2];var c=new Promise(function(n,r){t=o[e]=[n,r]});t[2]=c;var u=document.getElementsByTagName("head")[0],i=document.createElement("script");i.type="text/javascript",i.charset="utf-8",i.async=!0,i.timeout=12e4,n.nc&&i.setAttribute("nonce",n.nc),i.src=n.p+""+e+".js?"+{0:"ee403fce53c8757fc931"}[e];var a=setTimeout(r,12e4);return i.onerror=i.onload=r,u.appendChild(i),c},n.m=e,n.c=t,n.i=function(e){return e},n.d=function(e,r,t){n.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:t})},n.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(r,"a",r),r},n.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},n.p="",n.oe=function(e){throw console.error(e),e}}([]); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,14 @@
|
||||
{ |
||||
"presets": [ |
||||
["es2015", { "modules": false }] |
||||
], |
||||
"plugins": [ |
||||
[ |
||||
"component", |
||||
{ |
||||
"libraryName": "element-ui", |
||||
"styleLibraryName": "theme-chalk" |
||||
} |
||||
] |
||||
] |
||||
} |
@ -0,0 +1,6 @@
|
||||
.DS_Store |
||||
node_modules/ |
||||
dist/ |
||||
npm-debug.log |
||||
.idea |
||||
.vscode/settings.json |
@ -0,0 +1,6 @@
|
||||
.PHONY: dist build |
||||
build: |
||||
@npm run build
|
||||
|
||||
dev: |
||||
@npm run dev
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,46 @@
|
||||
{ |
||||
"name": "frpc-web", |
||||
"description": "An admin web ui for frp client.", |
||||
"author": "fatedier", |
||||
"private": true, |
||||
"scripts": { |
||||
"dev": "webpack-dev-server -d --inline --hot --env.dev", |
||||
"build": "rimraf dist && webpack -p --progress --hide-modules" |
||||
}, |
||||
"dependencies": { |
||||
"element-ui": "^2.5.3", |
||||
"vue": "^2.5.22", |
||||
"vue-resource": "^1.5.1", |
||||
"vue-router": "^3.0.2", |
||||
"whatwg-fetch": "^3.0.0" |
||||
}, |
||||
"engines": { |
||||
"node": ">=6" |
||||
}, |
||||
"devDependencies": { |
||||
"autoprefixer": "^9.4.7", |
||||
"babel-core": "^6.26.3", |
||||
"babel-eslint": "^10.0.1", |
||||
"babel-loader": "^7.1.5", |
||||
"babel-plugin-component": "^1.1.1", |
||||
"babel-preset-es2015": "^6.24.1", |
||||
"css-loader": "^2.1.0", |
||||
"eslint": "^5.12.1", |
||||
"eslint-config-enough": "^0.3.4", |
||||
"eslint-loader": "^2.1.1", |
||||
"file-loader": "^3.0.1", |
||||
"html-loader": "^0.5.5", |
||||
"html-webpack-plugin": "^2.24.1", |
||||
"less": "^3.9.0", |
||||
"less-loader": "^4.1.0", |
||||
"postcss-loader": "^3.0.0", |
||||
"rimraf": "^2.6.3", |
||||
"style-loader": "^0.23.1", |
||||
"url-loader": "^1.1.2", |
||||
"vue-loader": "^15.6.2", |
||||
"vue-template-compiler": "^2.5.22", |
||||
"webpack": "^2.7.0", |
||||
"webpack-cli": "^3.2.1", |
||||
"webpack-dev-server": "^3.1.14" |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
module.exports = { |
||||
plugins: [ |
||||
require('autoprefixer')() |
||||
] |
||||
} |
@ -0,0 +1,73 @@
|
||||
<template> |
||||
<div id="app"> |
||||
<header class="grid-content header-color"> |
||||
<el-row> |
||||
<a class="brand" href="#">frp client</a> |
||||
</el-row> |
||||
</header> |
||||
<section> |
||||
<el-row :gutter="20"> |
||||
<el-col id="side-nav" :xs="24" :md="4"> |
||||
<el-menu default-active="1" mode="vertical" theme="light" router="false" @select="handleSelect"> |
||||
<el-menu-item index="/">Overview</el-menu-item> |
||||
<el-menu-item index="/configure">Configure</el-menu-item> |
||||
<el-menu-item index="">Help</el-menu-item> |
||||
</el-menu> |
||||
</el-col> |
||||
|
||||
<el-col :xs="24" :md="20"> |
||||
<div id="content"> |
||||
<router-view></router-view> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</section> |
||||
<footer></footer> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
methods: { |
||||
handleSelect(key, path) { |
||||
if (key == '') { |
||||
window.open("https://github.com/fatedier/frp") |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
body { |
||||
background-color: #fafafa; |
||||
margin: 0px; |
||||
font-family: -apple-system,BlinkMacSystemFont,Helvetica Neue,sans-serif; |
||||
} |
||||
|
||||
header { |
||||
width: 100%; |
||||
height: 60px; |
||||
} |
||||
|
||||
.header-color { |
||||
background: #58B7FF; |
||||
} |
||||
|
||||
#content { |
||||
margin-top: 20px; |
||||
padding-right: 40px; |
||||
} |
||||
|
||||
.brand { |
||||
color: #fff; |
||||
background-color: transparent; |
||||
margin-left: 20px; |
||||
float: left; |
||||
line-height: 25px; |
||||
font-size: 25px; |
||||
padding: 15px 15px; |
||||
height: 30px; |
||||
text-decoration: none; |
||||
} |
||||
</style> |
After Width: | Height: | Size: 9.4 KiB |
@ -0,0 +1,106 @@
|
||||
<template> |
||||
<div> |
||||
<el-row id="head"> |
||||
<el-button type="primary" @click="fetchData">Refresh</el-button> |
||||
<el-button type="primary" @click="uploadConfig">Upload</el-button> |
||||
</el-row> |
||||
<el-input type="textarea" autosize v-model="textarea" placeholder="frpc configrue file, can not be empty..."></el-input> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
textarea: '' |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, |
||||
watch: { |
||||
'$route': 'fetchData' |
||||
}, |
||||
methods: { |
||||
fetchData() { |
||||
fetch('/api/config', {credentials: 'include'}) |
||||
.then(res => { |
||||
return res.text() |
||||
}).then(text => { |
||||
this.textarea= text |
||||
}).catch( err => { |
||||
this.$message({ |
||||
showClose: true, |
||||
message: 'Get configure content from frpc failed!', |
||||
type: 'warning' |
||||
}) |
||||
}) |
||||
}, |
||||
uploadConfig() { |
||||
this.$confirm('This operation will upload your frpc configure file content and hot reload it, do you want to continue?', 'Notice', { |
||||
confirmButtonText: 'Yes', |
||||
cancelButtonText: 'No', |
||||
type: 'warning' |
||||
}).then(() => { |
||||
if (this.textarea == "") { |
||||
this.$message({ |
||||
type: 'warning', |
||||
message: 'Configure content can not be empty!' |
||||
}) |
||||
return |
||||
} |
||||
|
||||
fetch('/api/config', { |
||||
credentials: 'include', |
||||
method: 'PUT', |
||||
body: this.textarea, |
||||
}).then(res => { |
||||
return res.json() |
||||
}).then(json => { |
||||
console.log(json) |
||||
if (json.code != 0) { |
||||
this.$message({ |
||||
showClose: true, |
||||
message: 'Put config to frpc and hot reload failed!', |
||||
type: 'warning' |
||||
}) |
||||
} else { |
||||
fetch('/api/reload', {credentials: 'include'}) |
||||
.then(res => { |
||||
return res.json() |
||||
}).then(json => { |
||||
this.$message({ |
||||
type: 'success', |
||||
message: 'Success' |
||||
}) |
||||
}).catch(err => { |
||||
this.$message({ |
||||
showClose: true, |
||||
message: 'Reload frpc configure file error!', |
||||
type: 'warning' |
||||
}) |
||||
}) |
||||
} |
||||
}).catch(err => { |
||||
this.$message({ |
||||
showClose: true, |
||||
message: 'Put config to frpc and hot reload failed!', |
||||
type: 'warning' |
||||
}) |
||||
}) |
||||
}).catch(() => { |
||||
this.$message({ |
||||
type: 'info', |
||||
message: 'Canceled' |
||||
}) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
#head { |
||||
margin-bottom: 30px; |
||||
} |
||||
</style> |
@ -0,0 +1,72 @@
|
||||
<template> |
||||
<div> |
||||
<el-row> |
||||
<el-col :md="24"> |
||||
<div> |
||||
<el-table :data="status" stripe style="width: 100%" :default-sort="{prop: 'type', order: 'ascending'}"> |
||||
<el-table-column prop="name" label="name"></el-table-column> |
||||
<el-table-column prop="type" label="type" width="150"></el-table-column> |
||||
<el-table-column prop="local_addr" label="local address" width="200"></el-table-column> |
||||
<el-table-column prop="plugin" label="plugin" width="200"></el-table-column> |
||||
<el-table-column prop="remote_addr" label="remote address"></el-table-column> |
||||
<el-table-column prop="status" label="status" width="150"></el-table-column> |
||||
<el-table-column prop="err" label="info"></el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
status: null |
||||
} |
||||
}, |
||||
created() { |
||||
this.fetchData() |
||||
}, |
||||
watch: { |
||||
'$route': 'fetchData' |
||||
}, |
||||
methods: { |
||||
fetchData() { |
||||
fetch('/api/status', {credentials: 'include'}) |
||||
.then(res => { |
||||
return res.json() |
||||
}).then(json => { |
||||
this.status = new Array() |
||||
for (let s of json.tcp) { |
||||
this.status.push(s) |
||||
} |
||||
for (let s of json.udp) { |
||||
this.status.push(s) |
||||
} |
||||
for (let s of json.http) { |
||||
this.status.push(s) |
||||
} |
||||
for (let s of json.https) { |
||||
this.status.push(s) |
||||
} |
||||
for (let s of json.stcp) { |
||||
this.status.push(s) |
||||
} |
||||
for (let s of json.xtcp) { |
||||
this.status.push(s) |
||||
} |
||||
}).catch( err => { |
||||
this.$message({ |
||||
showClose: true, |
||||
message: 'Get status info from frpc failed!', |
||||
type: 'warning' |
||||
}) |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style> |
||||
</style> |
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<title>frp client admin UI</title> |
||||
</head> |
||||
|
||||
<body> |
||||
<div id="app"></div> |
||||
<!--<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>--> |
||||
<!--<script src="//cdn.bootcss.com/echarts/3.4.0/echarts.min.js"></script>--> |
||||
</body> |
||||
|
||||
</html> |
@ -0,0 +1,52 @@
|
||||
import Vue from 'vue' |
||||
// import ElementUI from 'element-ui'
|
||||
import { |
||||
Button, |
||||
Form, |
||||
FormItem, |
||||
Row, |
||||
Col, |
||||
Table, |
||||
TableColumn, |
||||
Menu, |
||||
MenuItem, |
||||
MessageBox, |
||||
Message, |
||||
Input |
||||
} from 'element-ui' |
||||
import lang from 'element-ui/lib/locale/lang/en' |
||||
import locale from 'element-ui/lib/locale' |
||||
import 'element-ui/lib/theme-chalk/index.css' |
||||
import './utils/less/custom.less' |
||||
|
||||
import App from './App.vue' |
||||
import router from './router' |
||||
import 'whatwg-fetch' |
||||
|
||||
locale.use(lang) |
||||
|
||||
Vue.use(Button) |
||||
Vue.use(Form) |
||||
Vue.use(FormItem) |
||||
Vue.use(Row) |
||||
Vue.use(Col) |
||||
Vue.use(Table) |
||||
Vue.use(TableColumn) |
||||
Vue.use(Menu) |
||||
Vue.use(MenuItem) |
||||
Vue.use(Input) |
||||
|
||||
Vue.prototype.$msgbox = MessageBox; |
||||
Vue.prototype.$confirm = MessageBox.confirm |
||||
Vue.prototype.$message = Message |
||||
|
||||
//Vue.use(ElementUI)
|
||||
|
||||
Vue.config.productionTip = false |
||||
|
||||
new Vue({ |
||||
el: '#app', |
||||
router, |
||||
template: '<App/>', |
||||
components: { App } |
||||
}) |
@ -0,0 +1,18 @@
|
||||
import Vue from 'vue' |
||||
import Router from 'vue-router' |
||||
import Overview from '../components/Overview.vue' |
||||
import Configure from '../components/Configure.vue' |
||||
|
||||
Vue.use(Router) |
||||
|
||||
export default new Router({ |
||||
routes: [{ |
||||
path: '/', |
||||
name: 'Overview', |
||||
component: Overview |
||||
},{ |
||||
path: '/configure', |
||||
name: 'Configure', |
||||
component: Configure, |
||||
}] |
||||
}) |
@ -0,0 +1,22 @@
|
||||
@color: red; |
||||
|
||||
.el-form-item { |
||||
span { |
||||
margin-left: 15px; |
||||
} |
||||
} |
||||
|
||||
.demo-table-expand { |
||||
font-size: 0; |
||||
|
||||
label { |
||||
width: 90px; |
||||
color: #99a9bf; |
||||
} |
||||
|
||||
.el-form-item { |
||||
margin-right: 0; |
||||
margin-bottom: 0; |
||||
width: 50%; |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
class ProxyStatus { |
||||
constructor(status) { |
||||
this.name = status.name |
||||
this.type = status.type |
||||
this.status = status.status |
||||
this.err = status.err |
||||
this.local_addr = status.local_addr |
||||
this.plugin = status.plugin |
||||
this.remote_addr = status.remote_addr |
||||
} |
||||
} |
||||
|
||||
export {ProxyStatus} |
@ -0,0 +1,107 @@
|
||||
const path = require('path') |
||||
var webpack = require('webpack') |
||||
var HtmlWebpackPlugin = require('html-webpack-plugin') |
||||
var VueLoaderPlugin = require('vue-loader/lib/plugin') |
||||
var url = require('url') |
||||
var publicPath = '' |
||||
|
||||
module.exports = (options = {}) => ({ |
||||
entry: { |
||||
vendor: './src/main' |
||||
}, |
||||
output: { |
||||
path: path.resolve(__dirname, 'dist'), |
||||
filename: options.dev ? '[name].js' : '[name].js?[chunkhash]', |
||||
chunkFilename: '[id].js?[chunkhash]', |
||||
publicPath: options.dev ? '/assets/' : publicPath |
||||
}, |
||||
resolve: { |
||||
extensions: ['.js', '.vue', '.json'], |
||||
alias: { |
||||
'vue$': 'vue/dist/vue.esm.js', |
||||
'@': path.resolve(__dirname, 'src'), |
||||
} |
||||
}, |
||||
module: { |
||||
rules: [{ |
||||
test: /\.vue$/, |
||||
loader: 'vue-loader' |
||||
}, { |
||||
test: /\.js$/, |
||||
use: ['babel-loader'], |
||||
exclude: /node_modules/ |
||||
}, { |
||||
test: /\.html$/, |
||||
use: [{ |
||||
loader: 'html-loader', |
||||
options: { |
||||
root: path.resolve(__dirname, 'src'), |
||||
attrs: ['img:src', 'link:href'] |
||||
} |
||||
}] |
||||
}, { |
||||
test: /\.less$/, |
||||
loader: 'style-loader!css-loader!postcss-loader!less-loader' |
||||
}, { |
||||
test: /\.css$/, |
||||
use: ['style-loader', 'css-loader', 'postcss-loader'] |
||||
}, { |
||||
test: /favicon\.png$/, |
||||
use: [{ |
||||
loader: 'file-loader', |
||||
options: { |
||||
name: '[name].[ext]?[hash]' |
||||
} |
||||
}] |
||||
}, { |
||||
test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/, |
||||
exclude: /favicon\.png$/, |
||||
use: [{ |
||||
loader: 'url-loader', |
||||
options: { |
||||
limit: 10000 |
||||
} |
||||
}] |
||||
}] |
||||
}, |
||||
plugins: [ |
||||
new webpack.optimize.CommonsChunkPlugin({ |
||||
names: ['vendor', 'manifest'] |
||||
}), |
||||
new HtmlWebpackPlugin({ |
||||
favicon: 'src/assets/favicon.ico', |
||||
template: 'src/index.html' |
||||
}), |
||||
new webpack.NormalModuleReplacementPlugin(/element-ui[\/\\]lib[\/\\]locale[\/\\]lang[\/\\]zh-CN/, 'element-ui/lib/locale/lang/en'), |
||||
new webpack.DefinePlugin({ |
||||
'process.env': { |
||||
NODE_ENV: '"production"' |
||||
} |
||||
}), |
||||
new webpack.optimize.UglifyJsPlugin({ |
||||
sourceMap: false, |
||||
comments: false, |
||||
compress: { |
||||
warnings: false |
||||
} |
||||
}), |
||||
new VueLoaderPlugin() |
||||
], |
||||
devServer: { |
||||
host: '127.0.0.1', |
||||
port: 8010, |
||||
proxy: { |
||||
'/api/': { |
||||
target: 'http://127.0.0.1:8080', |
||||
changeOrigin: true, |
||||
pathRewrite: { |
||||
'^/api': '' |
||||
} |
||||
} |
||||
}, |
||||
historyApiFallback: { |
||||
index: url.parse(options.dev ? '/assets/' : publicPath).pathname |
||||
} |
||||
}//,
|
||||
//devtool: options.dev ? '#eval-source-map' : '#source-map'
|
||||
}) |
Loading…
Reference in new issue