Vue使用之配置文件加载

利用Vue.js开发,前后端分离,妈妈再也不用担心我是用Pug还是Jinja2了。

但是前后端分离会遇到一个问题,vue在调用服务端restful接口时,因为不同的环境需要配置不同的url。比如我有个接口,返回商品信息。在测试环境,接口是http://testing.com/products,而线上环境是http://production.com/products,如何在vue中根据环境变量使用不同的接口。

全局变量window加载配置

在遇到这个问题的时候,我第一时间问了公司的前端花美男,前端花美男呵呵一笑,说道,对不起,我不和菜鸡说话。

最后,花美男还是告诉了我解决方案,根据环境变量,加载不同的配置到window对象上。

  • 不同环境创建不同的配置文件

    1
    2
    3
    test-config.js --- 测试环境
    dev-config.js --- 开发环境
    prod-config.js --- 线上环境

    配置文件大概长这样:

    1
    2
    3
    4
    window.config = {
    company_url : "http://localhost:5000/api/v1.0/companys",
    shelf_url: "http://localhost:5000/api/v1.0/shelfs/"
    }
  • webpack中根据不同环境变量加载不同配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    ...
    if (process.env.NODE_ENV === 'test') {
    var config_file = SRC_PATH + '/test-config.js';
    var publicPath = '/';
    } else if (process.env.NODE_ENV === 'prod') {
    var config_file = SRC_PATH + '/prod-config.js';
    var publicPath = 'http://192.168.4.62/';
    } else {
    var config_file = SRC_PATH + '/dev-config.js';
    var publicPath = '/'
    }
    module.exports = {
    entry: {
    bundle: SRC_PATH + '/main.js',
    config: config_file
    },
    output: {
    path: BUILD_PATH,
    publicPath: publicPath,
    filename: '[name].js'
    },
    ...
  • 使用配置项

    1
    2
    3
    4
    5
    6
    7
    8
    this.$http({
    url : window.config.company_url,
    method : "GET"
    }).then(function (response) {
    this.result = JSON.parse(response.data);
    }, function (response) {
    console.error("Load data error", response);
    });

开发时,我用了webpack-dev-server(webpack-dev-server --inline --hot --no-info --port 8083 --host 0.0.0.0 --progress),这种解决方案没什么问题,但是当我用HtmlWebpackPlugin构建项目的时候遇到了问题。

构建项目后,有两个js文件,app.jsconfig.js,因为xxx.config.js并没有在vue中引入,所以不能在HtmlWebpackPlugin的配置项中配置它们script标签的顺序。每次构建完需要手动修改两个script标签的顺序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<link rel=icon href=assets/logo.png type=image/x-icon>
<link href=/static/css/app. 3ef6bc1e3364257262cd802b616c6c7f.css rel=stylesheet>
</head>
<body class="hold-transition skin-blue sidebar-mini hold-transition login-page">
<div id=app></div>
<script type=text/javascript src=/static/js/manifest.db4e67c59c1cf7ebad71.js>
</script>
<script type=text/javascript src=/static/js/vendor.1350da6d631717189fe5.js></script>
<!--app.js文件中用到了config选项,但是config.js后加载,app.js中找不到配置项-->
<script type=text/javascript src=/static/js/app.04f242bf744b021aea45.js></script>
<script type=text/javascript src=/static/js/config.34ec7e8f25ae24db45ca.js></script>
</body>
</html>

Vue原型链加载配置

折腾了好久的webpack,希望可以使用wenpack配置把这件事搞定,最后放弃,最后我的解决方案是根据不同的环境变量,在main.js中把配置项加载到Vue的原型链上。

1
2
3
4
5
6
7
8
9
10
11
12
13
Object.defineProperties(Vue.prototype, {
$url_config: {
get: function () {
if (process.env.NODE_ENV === "production") {
return require("./settings/prod.config.js");
} else if (process.env.NODE_ENV === "development") {
return require("./settings/dev.config.js");
} else {
return require("./settings/test.config.js");
}
}
}
});

这样最后构建完只会有一个app.js文件,在vue中可以这么调用:

1
2
3
4
5
6
7
8
this.$http({
url : this.$url_config.company_url,
method : "GET"
}).then(function (response) {
this.result = JSON.parse(response.data);
}, function (response) {
console.error("Load data error", response);
});

事实告诉我们,果然不能相信花美男。对不起,我不和花美男说话!!!