環境(ローカル、テスト・STG・本番)毎に値(APIのURL等)が変わるのを、RailsのConfig Gemみたいに持てないかと、今回は日本語のみですが、言語ファイル(i18n)で共通化出来ないかも試したので、メモしておきます。
結論、cross-envは使わずに、publicRuntimeConfigを使用しました。
また、i18nは導入すれば、templateとexport内では問題なく使えます。
ただ、vee-validateのextend内ではundefinedになるので、configureで対応しました。
前回作った下記に導入して行きます。
vee-validateで入力チェックした上で、APIからの入力エラーも各項目に表示する
publicRuntimeConfigで環境毎に値を保持
SPA(Single Page Application)で作っているので、publicを使います。
nuxt.config.js に追加
import colors from 'vuetify/es5/util/colors' + const environment = process.env.NODE_ENV || 'development' + const config = require(`./config/${environment}.js`) export default { + publicRuntimeConfig: config,
.vueファイルで$configやthis.$configで、development.jsやproduction.js内の値が参照出来ようになります。
.envで定義して、process.envで参照しても良いですが、DB接続情報やクレデンシャル(シークレットキー等)ではないので、こちらを採用しました。
また、cross-envはprocess.envで、.env以外のファイルを参照できるのが利点だと思います。
ただ、$configと明確に分けた方が取得元が分かりやすいので、今回は導入しませんでした。
auth: { strategies: { local: { endpoints: { - login: { url: 'http://localhost:3000/users/auth/sign_in.json', method: 'post' }, + login: { url: config.authSignInURL, method: 'post' }, - logout: { url: 'http://localhost:3000/users/auth/sign_out.json', method: 'delete' }, + logout: { url: config.authSignOutURL, method: 'delete' }, - user: { url: 'http://localhost:3000/users/auth/validate_token.json', method: 'get' } + user: { url: config.authUserURL, method: 'get' }
ここでは$configが使えないので、requireしているconfigで参照。
config/development.js を作成
module.exports = { authSignInURL: 'http://localhost:3000/users/auth/sign_in.json', authSignOutURL: 'http://localhost:3000/users/auth/sign_out.json', authUserURL: 'http://localhost:3000/users/auth/validate_token.json', singUpUrl: 'http://localhost:3000/users/auth/sign_up.json', singUpConfirmSuccessUrl: 'http://localhost:5000/users/sign_in' }
jsonでも出来ますが、jsで揃えたいし、コメントも書けるので、こちらを採用しました。
config/production.js,prod を作成
(サーバーは全てproductionモードにしたいので、これをコピーしてからbuildする想定)
module.exports = { authSignInURL: 'https://example.com/users/auth/sign_in.json', authSignOutURL: 'https://example.com/users/auth/sign_out.json', authUserURL: 'https://example.com/users/auth/validate_token.json', singUpUrl: 'https://example.com/users/auth/sign_up.json', singUpConfirmSuccessUrl: 'https://front.example.com/users/sign_in' }
.gitignore に追加
(なので、Git管理外に)
config/production.js
pages/users/sign_up.vue を変更
methods: { async signUp () { - await this.$axios.post('http://localhost:3000/users/auth/sign_up.json', { + await this.$axios.post(this.$config.singUpUrl, { name: this.name, email: this.email, password: this.password, password_confirmation: this.password_confirmation, - confirm_success_url: 'http://localhost:5000/users/sign_in' + confirm_success_url: this.$config.singUpConfirmSuccessUrl
publicRuntimeConfigで定義した値のが、this.$configで取得できます。
i18n対応
$ yarn add @nuxtjs/i18n
nuxt.config.js に追加
modules: [ + '@nuxtjs/i18n', '@nuxtjs/axios', '@nuxtjs/auth', '@nuxtjs/toast', '@nuxtjs/pwa' ], + // I18n module configuration: https://i18n.nuxtjs.org/ + i18n: { + locales: [ + { code: 'ja', iso: 'ja', file: 'ja.js' } + ], + defaultLocale: 'ja', + lazy: true, + langDir: 'locales/' + },
今回は日本語しか使わないので、jaのみ定義しています。
locales/ja.js を作成
module.exports = { network: { failure: '通信に失敗しました。しばらく時間をあけてから、やり直してください。' }, auth: { signed_out: 'ログアウトしました。', already_authenticated: '既にログインしています。', already_signed_out: '既にログアウトされています。' } }
pages/users/sign_up.vue を変更
(sign_in.vue, sign_out.vueも同様に変更)
<validation-provider v-slot="{ errors }" name="password_confirmation" - rules="required|confirmed:password"> + rules="required|confirmed_password:password">
confirmedをconfirmed_passwordにして、ルール変えずに、後続で独自メッセージを設定しています。
- import { ValidationObserver, ValidationProvider, extend, setInteractionMode } from 'vee-validate' + import { ValidationObserver, ValidationProvider, extend, configure, localize } from 'vee-validate' import { required, email, min, confirmed } from 'vee-validate/dist/rules' import Message from '~/components/Message.vue' - setInteractionMode('eager')
setInteractionModeはデフォルトeagerなので、消しちゃいました。
- extend('required', { - ...required, - message: '入力してください。' - }) - extend('email', { - ...email, - message: '形式が正しくありません。' - }) - extend('min', { - ...min, - message: '{length}文字以上で入力してください。' - }) - extend('confirmed', { - ...confirmed, - message: 'パスワードと一致しません。' - }) + extend('required', required) + extend('email', email) + extend('min', min) + extend('confirmed_password', confirmed)
ルールはconfirmedで、メッセージはconfirmed_password(locales/validate.ja.jsで定義)
+ configure({ generateMessage: localize('ja', require('~/locales/validate.ja.js')) })
validate用の言語ファイルを作成して、設定しています。
messageに$tが使えなくてハマりましたが、こっちの方が1行で済むので良い。
message: this.$t(‘messages.required’)
> TypeError: Cannot read properties of undefined (reading ‘$t’)
message: $t(‘messages.required’)
> ReferenceError: $t is not defined
- this.$toasted.info('既にログインしています。') + this.$toasted.info(this.$t('auth.already_authenticated'))
- this.$toasted.error('通信に失敗しました。しばらく時間をあけてから、やり直してください。') + this.$toasted.error(this.$t('network.failure'))
nuxt.config.jsで設定した言語ファイル(locales/ja.js)を参照しています。
locales/validate.ja.js を作成
module.exports = { messages: { // confirmed: '致していません。', // "{_field_}が一致しません", confirmed_password: 'パスワードと一致していません。', email: '形式が正しくありません。', // "{_field_}は有効なメールアドレスではありません", min: '{length}文字以上で入力してください。', // "{_field_}は{length}文字以上でなければなりません", required: '入力してください。' // "{_field_}は必須項目です", } }
extendで指定したキーに対して、メッセージを設定出来ます。
「パスワードと一致していません。」の「パスワード」が渡せるようになってなかったので、この方法にしました。
もっと共通化出来そうですが、可読性は今の方が良さそうに思えるので、一旦、保留にしました。