Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js build with different environment variables

Tags:

I've used official Webpack template for Vue.js. It uses separate configuration for different environments. They offer test, development and production. However, I need another one as we have two production servers (one production and one staging).

What is the best practice to have different configurations for different production environments? I would think of something like npm run build --URL:http://some-url.com --PORT:80 ....

Any advice is welcome!

like image 575
kuceram Avatar asked Jun 01 '17 14:06

kuceram


People also ask

How do I use environment variables in Vue?

Using Env Variables in Client-side CodeNODE_ENV - this will be one of "development" , "production" or "test" depending on the mode the app is running in. BASE_URL - this corresponds to the publicPath option in vue.config.js and is the base path your app is deployed at.

Should you use .env in production?

Using environment variables is a somewhat common practice during Development but it is actually not a healthy practice to use with Production. While there are several reasons for this, one of the main reasons is that using environment variables can cause unexpected persistence of variable values.


2 Answers

This is more like a webpack question rather then Vue.js, I wanna share our previous setup for handling different build files and environments. first of all, we keep our config in separated folder.

config/index.js

// see http://vuejs-templates.github.io/webpack for documentation. var path = require('path')  const CDN = 'https://cdnURL.com/'  module.exports = {   build: {     env: require('./prod.env'),     assetsRoot: path.resolve(__dirname, '../dist'),     assetsSubDirectory: 'static',     assetsPublicPath: CDN,     productionSourceMap: true,     // Gzip off by default as many popular static hosts such as     // Surge or Netlify already gzip all static assets for you.     // Before setting to `true`, make sure to:     // npm install --save-dev compression-webpack-plugin     productionGzip: false,     productionGzipExtensions: ['js', 'css'],     productionBundleAnalyze: process.env.ANALYZE ? true : false   },   dev: {     env: require('./dev.env'),     port: 8080,     assetsSubDirectory: 'static',     assetsPublicPath: '/',     proxyTable: {       '/api': {         target: process.env.npm_package_config_proxy,         logLevel: 'debug',         changeOrigin: true,         onProxyRes(proxyRes, req, res) {           // http-proxy-middleware           proxyRes.headers['Content-Type'] = proxyRes.headers['content-type']           delete proxyRes.headers['content-type']         }       }     },     // CSS Sourcemaps off by default because relative paths are "buggy"     // with this option, according to the CSS-Loader README     // (https://github.com/webpack/css-loader#sourcemaps)     // In our experience, they generally work as expected,     // just be aware of this issue when enabling this option.     cssSourceMap: false   },   projects: {     main: {       entry: './packages/home/index.js',       devPath: 'main.html',       target: 'web',       buildPath: path.resolve(__dirname, '../dist/index.html'),       testPath: '../packages/home/__test__/index.js'     },     desktop: {       entry: './packages/desktop/index.js',       devPath: 'desktop.html',       target: 'electron-renderer',       buildPath: path.resolve(__dirname, '../../static/desktop.html'),       assetsRoot: path.resolve(__dirname, '../../'),       assetsSubDirectory: 'static',       assetsPublicPath: '../',       testPath: '../packages/desktop/__test__/index.js'     },     login: {       entry: './packages/login/index.js',       devPath: 'login.html',       target: 'web',       buildPath: path.resolve(__dirname, '../dist/login.html'),       testPath: '../packages/login/__test__/index.js'     },     setting: {       entry: './packages/setting/index.js',       devPath: 'setting.html',       target: 'web',       buildPath: path.resolve(__dirname, '../dist/setting.html'),       testPath: '../packages/setting/__test__/index.js'     },     playground: {       entry: './packages/playground/index.js',       target: 'web'     }   } } 

config/dev.env.js

var merge = require('webpack-merge') var prodEnv = require('./prod.env')  module.exports = merge(prodEnv, {   NODE_ENV: '"development"',   API_ROOT: '"/api"' }) 

config/prod.env

module.exports = {   NODE_ENV: '"production"',   API_ROOT: '"http://test.example.co/api"'  //staging server   // API_ROOT: '"http://127.0.0.1:8787/api"'  //mock-up server } 

incase of where we wanna work we change API root in here.

and our webpack.base.conf.js look like this. build/webpack.base.conf.js

var path = require('path') var config = require('../config') var utils = require('./utils') var projectRoot = path.resolve(__dirname, '../')  const isProduction = process.env.NODE_ENV === 'production'  module.exports = {   entry: utils.entrys(),   output: {     path: config.build.assetsRoot,     publicPath: isProduction ? config.build.assetsPublicPath : config.dev.assetsPublicPath,     filename: '[name].js'   },   resolve: {     extensions: ['.js', '.vue', '.json'],     alias: {       'src': path.resolve(__dirname, '../src'),       'assets': path.resolve(__dirname, '../src/assets'),       'components': path.resolve(__dirname, '../src/components')     },     unsafeCache: true   },   target: config.projects[process.env.npm_package_config_dev].target,   module: {     rules: [       {         test: /\.vue$/,         loader: 'vue-loader',         options: {           postcss: [             require('postcss-cssnext')(),             require('lost')()           ],           cssModules: {             localIdentName: isProduction ? '[path][name]---[local]---[hash:base64:5]' : '[path][name]--[local]',             camelCase: true           },           loaders: Object.assign({}, utils.cssLoaders()),           preLoaders: {             html: 'inline-svg-loader'           }         }       },       {         test: /\.js$/,         loader: 'babel-loader',         include: projectRoot,         exclude: /node_modules/,         query: {           cacheDirectory: true         }       },       {         test: /\.json$/,         loader: 'json-loader'       },       {         test: /\.html$/,         loader: 'vue-html-loader'       },       {         test: /\.(png|jpe?g|gif)(\?.*)?$/,         loader: 'url-loader',         query: {           limit: 10000,           name: utils.assetsPath('img/[name].[hash:7].[ext]')         }       },       {         test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,         loader: 'url-loader',         query: {           limit: 10000,           name: utils.assetsPath('fonts/[name].[hash:7].[ext]')         }       }     ]   } } 

and finally our package.json is look like this

... ... ...     "scripts": {       "dev": "webpack-dashboard -- node build/dev-server.js",       "dev:login": "npm config set mesh:dev login && npm run dev",       "dev:setting": "npm config set mesh:dev setting && npm run dev",       "dev:main": "npm config set mesh:dev main && npm run dev",       "dev:desktop": "npm config set mesh:dev desktop && node build/dev-server.js",       "dev:playground": " npm config set mesh:dev playground && cross-env PORT=9000 npm run dev"      } ... ... ... 

we used this setup for bundle our app for electron, web, and webkit while using shared components.

but still later on we had issue of scalling. and we started to use lerna if you need something more moduler. I recommend you to check that one out.

Best regards.

like image 144
Necmttn Avatar answered Sep 22 '22 12:09

Necmttn


There is a simple way. In config/prod.env.js append your variables like this:

module.exports = {   NODE_ENV: '"production"',   MY_URL: JSON.stringify(process.env.MY_URL || 'http://example.com') } 

Then run your build like this: MY_URL=http://example.org npm run build

Your variable will be available in main.js as process.env.MY_URL

like image 33
niutech Avatar answered Sep 23 '22 12:09

niutech