From c8a52f3838521c1b98d425bef7ee75a12ea2f68d Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 29 Dec 2017 16:34:04 -0500 Subject: [PATCH] implement .env loading --- .../cli-service/generator/files/.gitignore | 20 +++++++++--- packages/@vue/cli-service/lib/PluginAPI.js | 8 +++-- packages/@vue/cli-service/lib/Service.js | 31 +++++++++++++++++++ .../cli-service/lib/command-plugins/build.js | 14 +++++++-- .../cli-service/lib/command-plugins/serve.js | 25 +++++++++------ .../cli-service/lib/config-plugins/dev.js | 2 +- .../cli-service/lib/config-plugins/prod.js | 4 ++- .../cli-service/lib/util/resolveClientEnv.js | 9 ++---- packages/@vue/cli-service/package.json | 1 + packages/@vue/cli-shared-utils/index.js | 8 +++-- packages/@vue/cli-shared-utils/package.json | 1 + packages/@vue/cli/lib/Creator.js | 6 ++-- packages/@vue/cli/lib/Generator.js | 4 +-- yarn.lock | 8 +++++ 14 files changed, 105 insertions(+), 36 deletions(-) diff --git a/packages/@vue/cli-service/generator/files/.gitignore b/packages/@vue/cli-service/generator/files/.gitignore index e7e7dbb70..2e0e9dd72 100644 --- a/packages/@vue/cli-service/generator/files/.gitignore +++ b/packages/@vue/cli-service/generator/files/.gitignore @@ -1,17 +1,27 @@ .DS_Store -node_modules/ -/dist/ -npm-debug.log* -yarn-debug.log* -yarn-error.log* +node_modules +/dist <%_ if (options.coverage) { _%> + +# test coverage files /test/unit/coverage/ <%_ } _%> <%_ if (options.e2e === 'nightwatch') { _%> + +# e2e reports & log /test/e2e/reports/ selenium-debug.log <%_ } _%> +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + # Editor directories and files .idea .vscode diff --git a/packages/@vue/cli-service/lib/PluginAPI.js b/packages/@vue/cli-service/lib/PluginAPI.js index 9b3e0da21..40a780f7f 100644 --- a/packages/@vue/cli-service/lib/PluginAPI.js +++ b/packages/@vue/cli-service/lib/PluginAPI.js @@ -10,9 +10,11 @@ module.exports = class PluginAPI { return path.resolve(this.service.context, _path) } - setEnv (env) { - process.env.NODE_ENV = env - process.env.BABEL_ENV = env === 'production' ? env : 'development' + setMode (mode = 'development') { + // by default, NODE_ENV === mode, but this can be overwritten in .env files + process.env.NODE_ENV = mode + // load .env files based on mode + this.service.loadEnv(mode) } registerCommand (name, opts, fn) { diff --git a/packages/@vue/cli-service/lib/Service.js b/packages/@vue/cli-service/lib/Service.js index 9bcbc4d61..f9f9b4630 100644 --- a/packages/@vue/cli-service/lib/Service.js +++ b/packages/@vue/cli-service/lib/Service.js @@ -1,6 +1,8 @@ const fs = require('fs') const path = require('path') +const debug = require('debug') const chalk = require('chalk') +const dotenv = require('dotenv') const getPkg = require('read-pkg-up') const merge = require('webpack-merge') const Config = require('webpack-chain') @@ -19,6 +21,10 @@ module.exports = class Service { this.pkg = pkg.pkg || {} this.context = path.dirname(pkg.path) this.projectOptions = this.loadProjectConfig() + debug('vue:project-config')(this.projectOptions) + + // load base .env + this.loadEnv() // install plugins this.resolvePlugins().forEach(({ id, apply }) => { @@ -34,6 +40,31 @@ module.exports = class Service { } } + loadEnv (mode) { + const basePath = path.resolve(this.context, `.env${mode ? `.${mode}` : ``}`) + const localPath = `${basePath}.local` + const baseRes = dotenv.load({ path: basePath }) + const localRes = dotenv.load({ path: localPath }) + + const checkError = res => { + // only ignore if file is not found + if (res.error && res.error.toString().indexOf('ENOENT') < 0) { + error(res.error) + } + } + + checkError(baseRes) + checkError(localRes) + + const logger = debug('vue:env') + if (baseRes.parsed) { + logger(basePath, baseRes.parsed) + } + if (localRes.parsed) { + logger(localPath, localRes.parsed) + } + } + resolvePlugins () { const builtInPlugins = [ './command-plugins/serve', diff --git a/packages/@vue/cli-service/lib/command-plugins/build.js b/packages/@vue/cli-service/lib/command-plugins/build.js index e4b5019a7..c763e9708 100644 --- a/packages/@vue/cli-service/lib/command-plugins/build.js +++ b/packages/@vue/cli-service/lib/command-plugins/build.js @@ -1,11 +1,21 @@ +const defaults = { + mode: 'production', + extractCSS: true, + sourceMap: true, + cssSourceMap: false +} + module.exports = (api, options) => { api.registerCommand('build', { description: 'build for production', usage: 'vue-cli-service build', options: { - '--extractCSS': 'extract component CSS into one file.' + '--mode': `specify env mode (default: ${defaults.mode})`, + '--extractCSS': `extract component CSS into one file. (default: ${defaults.extractCSS})`, + '--sourceMap': `generate source map (default: ${defaults.sourceMap})`, + '--cssSourceMap': `generate source map for CSS (default: ${defaults.cssSourceMap})` } }, args => { - // TODO + api.setMode(args.mode || defaults.mode) }) } diff --git a/packages/@vue/cli-service/lib/command-plugins/serve.js b/packages/@vue/cli-service/lib/command-plugins/serve.js index b05ce6035..572104c59 100644 --- a/packages/@vue/cli-service/lib/command-plugins/serve.js +++ b/packages/@vue/cli-service/lib/command-plugins/serve.js @@ -1,21 +1,28 @@ const { info, error, hasYarn, clearConsole } = require('@vue/cli-shared-utils') +const defaults = { + mode: 'development', + host: '0.0.0.0', + port: 8080, + https: false +} + module.exports = (api, options) => { api.registerCommand('serve', { description: 'start development server', usage: 'vue-cli-service serve', options: { - '--open': 'open browser on server start', - '--env': 'specify NODE_ENV (default: development)', - '--host': 'specify host (default: 0.0.0.0)', - '--port': 'specify port (default: 8080)', - '--https': 'use https' + '--open': `open browser on server start`, + '--mode': `specify env mode (default: ${defaults.mode})`, + '--host': `specify host (default: ${defaults.host})`, + '--port': `specify port (default: ${defaults.port})`, + '--https': `use https (default: ${defaults.https})` } }, args => { clearConsole() info('Starting development server...') - api.setEnv(args.env || 'development') + api.setMode(args.mode || defaults.mode) const chalk = require('chalk') const webpack = require('webpack') @@ -27,9 +34,9 @@ module.exports = (api, options) => { const overlayMiddleware = require('@vue/cli-overlay/middleware') const projectDevServerOptions = options.devServer || {} - const useHttps = args.https || projectDevServerOptions.https - const host = args.host || process.env.HOST || projectDevServerOptions.host || '0.0.0.0' - portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || 8080 + const useHttps = args.https || projectDevServerOptions.https || defaults.https + const host = args.host || process.env.HOST || projectDevServerOptions.host || defaults.host + portfinder.basePort = args.port || process.env.PORT || projectDevServerOptions.port || defaults.port portfinder.getPort((err, port) => { if (err) { diff --git a/packages/@vue/cli-service/lib/config-plugins/dev.js b/packages/@vue/cli-service/lib/config-plugins/dev.js index 224504785..a1a4a51b4 100644 --- a/packages/@vue/cli-service/lib/config-plugins/dev.js +++ b/packages/@vue/cli-service/lib/config-plugins/dev.js @@ -5,7 +5,7 @@ const WatchMissingNodeModulesPlugin = require('../webpack/watchmissingnodemodule module.exports = api => { api.chainWebpack(webpackConfig => { - if (process.env.NODE_ENV !== 'production') { + if (process.env.NODE_ENV === 'development') { webpackConfig .devtool('cheap-module-source-map') diff --git a/packages/@vue/cli-service/lib/config-plugins/prod.js b/packages/@vue/cli-service/lib/config-plugins/prod.js index 4bccad451..dbbda76b1 100644 --- a/packages/@vue/cli-service/lib/config-plugins/prod.js +++ b/packages/@vue/cli-service/lib/config-plugins/prod.js @@ -1,5 +1,7 @@ module.exports = api => { api.chainWebpack(webpackConfig => { - // TODO + if (process.env.NODE_ENV === 'production') { + + } }) } diff --git a/packages/@vue/cli-service/lib/util/resolveClientEnv.js b/packages/@vue/cli-service/lib/util/resolveClientEnv.js index 8b65909fd..19cb63440 100644 --- a/packages/@vue/cli-service/lib/util/resolveClientEnv.js +++ b/packages/@vue/cli-service/lib/util/resolveClientEnv.js @@ -1,14 +1,9 @@ const prefixRE = /^VUE_APP_/ module.exports = function resolveClientEnv () { - // this should have been set by api.setEnv() - const NODE_ENV = process.env.NODE_ENV || 'development' - - // TODO load .env files - - const env = { NODE_ENV: JSON.stringify(NODE_ENV) } + const env = {} Object.keys(process.env).forEach(key => { - if (prefixRE.test(key)) { + if (prefixRE.test(key) || key === 'NODE_ENV') { env[key] = JSON.stringify(process.env[key]) } }) diff --git a/packages/@vue/cli-service/package.json b/packages/@vue/cli-service/package.json index e8a036eaa..cf3cae068 100644 --- a/packages/@vue/cli-service/package.json +++ b/packages/@vue/cli-service/package.json @@ -28,6 +28,7 @@ "chalk": "^2.3.0", "cross-spawn": "^5.1.0", "css-loader": "^0.28.7", + "dotenv": "^4.0.0", "express-open-in-editor": "^3.1.1", "extract-text-webpack-plugin": "^3.0.2", "file-loader": "^1.1.6", diff --git a/packages/@vue/cli-shared-utils/index.js b/packages/@vue/cli-shared-utils/index.js index 0d50b9faf..17a47939b 100644 --- a/packages/@vue/cli-shared-utils/index.js +++ b/packages/@vue/cli-shared-utils/index.js @@ -1,4 +1,5 @@ const chalk = require('chalk') +const readline = require('readline') const padStart = require('string.prototype.padstart') const { logWithSpinner, stopSpinner } = require('./spinner') @@ -34,9 +35,10 @@ exports.error = (msg) => { exports.clearConsole = title => { if (process.stdout.isTTY) { - process.stdout.write( - process.platform === 'win32' ? '\x1Bc' : '\x1B[2J\x1B[3J\x1B[H' - ) + const blank = '\n'.repeat(process.stdout.rows) + console.log(blank) + readline.cursorTo(process.stdout, 0, 0) + readline.clearScreenDown(process.stdout) if (title) { console.log(title) } diff --git a/packages/@vue/cli-shared-utils/package.json b/packages/@vue/cli-shared-utils/package.json index 5135ce510..06a47f198 100644 --- a/packages/@vue/cli-shared-utils/package.json +++ b/packages/@vue/cli-shared-utils/package.json @@ -21,6 +21,7 @@ "dependencies": { "chalk": "^2.3.0", "ora": "^1.3.0", + "readline": "^1.3.0", "string.prototype.padstart": "^3.0.0" }, "publishConfig": { diff --git a/packages/@vue/cli/lib/Creator.js b/packages/@vue/cli/lib/Creator.js index 2a2ae6ded..5d96b0663 100644 --- a/packages/@vue/cli/lib/Creator.js +++ b/packages/@vue/cli/lib/Creator.js @@ -44,7 +44,7 @@ module.exports = class Creator { // prompt clearConsole() const answers = await inquirer.prompt(this.resolveFinalPrompts()) - debug('answers')(answers) + debug('vue:cli-answers')(answers) let options if (answers.mode === 'saved') { @@ -71,7 +71,7 @@ module.exports = class Creator { projectName: name } - debug('options')(options) + debug('vue:cli-ptions')(options) // write base package.json to disk clearConsole() @@ -204,7 +204,7 @@ module.exports = class Creator { this.injectedPrompts, this.outroPrompts ) - debug('prompts')(prompts) + debug('vue:cli-prompts')(prompts) return prompts } diff --git a/packages/@vue/cli/lib/Generator.js b/packages/@vue/cli/lib/Generator.js index 68b9f5f37..95feb5940 100644 --- a/packages/@vue/cli/lib/Generator.js +++ b/packages/@vue/cli/lib/Generator.js @@ -42,13 +42,13 @@ module.exports = class Generator { }, {}) this.pkg.dependencies = sortDeps(this.pkg.dependencies) this.pkg.devDependencies = sortDeps(this.pkg.devDependencies) - debug('pkg')(this.pkg) + debug('vue:cli-pkg')(this.pkg) } async resolveFiles () { for (const middleware of this.fileMiddlewares) { await middleware(this.files, ejs.render) } - debug('files')(this.files) + debug('vue:cli-files')(this.files) } } diff --git a/yarn.lock b/yarn.lock index fec73588c..2e44df1f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2140,6 +2140,10 @@ dot-prop@^3.0.0: dependencies: is-obj "^1.0.0" +dotenv@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-4.0.0.tgz#864ef1379aced55ce6f95debecdce179f7a0cd1d" + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -5818,6 +5822,10 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" +readline@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/readline/-/readline-1.3.0.tgz#c580d77ef2cfc8752b132498060dc9793a7ac01c" + realpath-native@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.0.0.tgz#7885721a83b43bd5327609f0ddecb2482305fdf0"