【vuecli】src配下にapplication configファイルを追加する

ハマった。

環境

$ npm list -g vue-cli

E:\node_modules
+-- @vue/cli-init@3.0.0-rc.10
| `-- vue-cli@2.9.6
`-- vue-cli@2.9.6

$ npm -version
6.4.1

やりたいこと

  • vue cli を使ってテンプレート生成したプロジェクトに、vue用の application コンフィグファイルを作ってRestAPIの接続先サーバーを記述し、アプリケーションで利用したい。
  • npm run から起動するビルドスクリプトなどで、NODE_ENVがdevelopmentならdevlopment.jsを読み込み、productionならproduction.jsを読み込みたい。

構成は以下のとおり

vueproject
 |`- .babelrc
 |`- .editorconfig
 |`- .eslintignore
 |`- .eslintrc.js
 |`- .gitignore
 |`- .postcssrc.js
 |`- build
 |`- config
 |`- dist
 |`- index.html
 |`- node_modules
 |`- package-lock.json
 |`- package.json
 |`- README.md
 |`- src
 |    |`- config
 |    |    |`- development.js   ←
 |    |     `- production.js    ←
 |     `- componentsとか色々なやつ。この中のコードからconfigを参照
 |`- static
  `- test

設定追加に至るまで

結果的にWebpackにalias を設定する方法を採用。

qiita.com qiita.com

webpack.base.conf.js

build/webpack.base.confに下記を追記

module.exports = {
  // ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src')
    }
  },
  // ...
}

↓

module.exports = {
  // ...
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'config': resolve(`src/config/${process.env.NODE_ENV}.js`) // 追記
    }
  },
  // ...
}

npm run devnpm run build 時に展開されてwebpackに渡される寸法。

npm run devだけだとでNODE_ENV未設定で解決

どうも vuecli で生成したスクリプトでは、npm run dev はNODE_ENVにdevelopmentが自動設定される前にwebpackをrunしてしまうらしい。

事前に環境変数 NODE_ENV にdevelopment を設定しておくだけでも解決するが、 自前用のコードであったしものぐさなので、webpack.dev.conf.jsの下記にハードコードで上書きするようにした。

const devWebpackConfig = merge(baseWebpackConfig, {
  // 下記追記
  resolve: {
    alias: {
      config: resolve(`src/config/development.js`)
    }
  },
  // ...
})

これで、下記コードでコンフィグが参照できるようになる。

development.js

export default {
  apiurl: '{protocol}//{host}/api'
}

main.js

import Vue from 'vue'
import App from './App'
import router from './router'
import config from 'config' // これ
import services from './services/entry'

Vue.config.productionTip = false

const configMixin = Vue.mixin({
  created: function () {
    this.$config = config

    for (const key in services) {
      var tagservice = '$' + key
      if (this[tagservice]) {
        console.error(`module name conflicted with $vue.${tagservice}! we take overwrite to ./services/modules.`)
      }
      this['$' + key] = services[key]
    }
  }
})

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  configMixin,
  components: { App },
  template: '<App/>'
})