从源码分析vue-cli@3.0环境变量配置

栏目: JavaScript · 发布时间: 4年前

内容简介:在开始之前,我们先来看下官方文档说明;查看vue-cli文档中有这么一句话:由此我们可以知道,查看根路径的

在开始之前,我们先来看下官方文档说明;查看vue-cli文档中有这么一句话:

只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中。
复制代码

由此我们可以知道, vue-cli 是有针对 VUE_APP_ 这个变量进行配置。接下来让我们查看源码,看下 vue-cli 是怎么实现的。

源码分析

查看根路径的 package.json 文件我们可以知道,当执行 npm run serve 时会执行 vue-cli-service ;所以我们找到该文件的执行地址 node_modules/@vue/cli-service

分析其 package.json 我们知道,当我们执行 vue-cli-service 时候会调用文件 lib/Service.jsinit 函数:

init (mode = process.env.VUE_CLI_MODE) {
    ...
    this.mode = mode

    // load mode .env
    if (mode) {
      this.loadEnv(mode)
    }
    // load base .env
    this.loadEnv()
    ...
  }
复制代码

紧接着我们再来看 loadEnv 方法

loadEnv (mode) {
    const logger = debug('vue:env')
    const basePath = path.resolve(this.context, `.env${mode ? `.${mode}` : ``}`)
    // 注意这里,不管你有没有定义它都会在后面加上一个.local的后缀,感觉这里不是很好
    const localPath = `${basePath}.local`

    const load = path => {
        try {
            const env = dotenv.config({ path, debug: process.env.DEBUG })
            dotenvExpand(env)
            logger(path, env)
        } catch (err) {
            // only ignore error if file is not found
            if (err.toString().indexOf('ENOENT') < 0) {
                error(err)
            }
        }
    }

    load(localPath)
    load(basePath)

    ...
}
复制代码

这里会先调用 dotenv (位于 node_modules/dotenv )的 config 函数,最终会返回这样的格式 { parsed: { YOUR_ENV_KEY: '你设定的环境变量值' } } 。 并且我们可以看到,这里已经将值存放到 process.env 中了。

function config (options /*: ?DotenvConfigOptions */) /*: DotenvConfigOutput */ {
  ...

  try {
    // specifying an encoding returns a string instead of a buffer
    const parsed = parse(fs.readFileSync(dotenvPath, { encoding }), { debug })

    Object.keys(parsed).forEach(function (key) {
      if (!process.env.hasOwnProperty(key)) {
        process.env[key] = parsed[key]
      } else if (debug) {
        log(`"${key}" is already defined in \`process.env\` and will not be overwritten`)
      }
    })

    return { parsed }
  } catch (e) {
    return { error: e }
  }
}
复制代码

这里再说下 parse 方法,会读取你设置的所有 .env 文件,然后将里面的数据转换成对象,简单来说就是 以换行符号来循环,用正则匹配出内容 ,最终形成以 {key: value} 的格式输出。

const NEWLINE = '\n'
const RE_INI_KEY_VAL = /^\s*([\w.-]+)\s*=\s*(.*)?\s*$/
const RE_NEWLINES = /\\n/g

function parse (src /*: string | Buffer */, options /*: ?DotenvParseOptions */) /*: DotenvParseOutput */ {
  const debug = Boolean(options && options.debug)
  const obj = {}

  // convert Buffers before splitting into lines and processing
  src.toString().split(NEWLINE).forEach(function (line, idx) {
    // matching "KEY' and 'VAL' in 'KEY=VAL'
    const keyValueArr = line.match(RE_INI_KEY_VAL)
    // matched?
    if (keyValueArr != null) {
      const key = keyValueArr[1]
      // default undefined or missing values to empty string
      let val = (keyValueArr[2] || '')
      const end = val.length - 1
      const isDoubleQuoted = val[0] === '"' && val[end] === '"'
      const isSingleQuoted = val[0] === "'" && val[end] === "'"

      // if single or double quoted, remove quotes
      if (isSingleQuoted || isDoubleQuoted) {
        val = val.substring(1, end)

        // if double quoted, expand newlines
        if (isDoubleQuoted) {
          val = val.replace(RE_NEWLINES, NEWLINE)
        }
      } else {
        // remove surrounding whitespace
        val = val.trim()
      }

      obj[key] = val
    } else if (debug) {
      log(`did not match key and value when parsing line ${idx + 1}: ${line}`)
    }
  })

  return obj
}
复制代码

然后我们再来看下 dotenvExpand 方法,找到它位于 node_modules/dotenv-expand 下,这里就没啥好说的,就是将几个环境变量的值放到一起

接下来让我们回到开头说的 只有以 VUE_APP_ 开头的变量会被 webpack.DefinePlugin 静态嵌入到客户端侧的包中 ,这个是在那里配置的呢?

我们知道 vue-cli 会对 webpack 进行配置扩展,所以我们发现在 cli-service/lib/config/app.js

const resolveClientEnv = require('../util/resolveClientEnv')
    webpackConfig
      .plugin('define')
        .use(require('webpack/lib/DefinePlugin'), [
          resolveClientEnv(options)
        ])
复制代码

我们接着找到 resolveClientEnv 方法,可以看到是在这里定义的,并且会将非 VUE_APP_ 开头的过滤掉

const prefixRE = /^VUE_APP_/

module.exports = function resolveClientEnv (options, raw) {
  const env = {}
  Object.keys(process.env).forEach(key => {
    if (prefixRE.test(key) || key === 'NODE_ENV') {
      env[key] = process.env[key]
    }
  })
  // 需要注意的是 `baseUrl` 从 `Vue CLI 3.3` 起已弃用,请使用 `publicPath` 。以下源码涉及此改动
  env.BASE_URL = options.publicPath

  if (raw) {
    return env
  }

  for (const key in env) {
    env[key] = JSON.stringify(env[key])
  }
  return {
    'process.env': env
  }
}
复制代码

以上所述就是小编给大家介绍的《从源码分析vue-cli@3.0环境变量配置》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法问题实战策略

算法问题实战策略

[韩] 具宗万 / 崔盛一 / 人民邮电出版社 / 2015-2 / 119.00元

第一部分 开始解决问题 第二部分 算法分析 第三部分 算法设计范式 第四部分 一些著名的算法 第五部分 基本数据结构 第六部分 树 第七部分 图一起来看看 《算法问题实战策略》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具