不修改环境变量,也能判断打包环境

484 阅读1分钟

前言

如今的前端项目,不管是开发还是上线,都避免不了在打包时判断一下打包环境,来针对开发或者生产做不同的打包配置,那么不修改 process.env.NODE_ENV 或设置 webpack --env,还能做判断吗?

实践

在阅读 only-allow 源码 时,我发现作者是通过whichPMRuns获取包管理器的

其内部逻辑为:

function whichPMRuns() {
  if (!process.env.npm_config_user_agent) {
    return undefined
  }
  return pmFromUserAgent(process.env.npm_config_user_agent)
}

function pmFromUserAgent (userAgent) {
  const pmSpec = userAgent.split(' ')[0]
  const separatorPos = pmSpec.lastIndexOf('/')
  const name = pmSpec.substring(0, separatorPos)
  return {
    name: name === 'npminstall' ? 'cnpm' : name,
    version: pmSpec.substring(separatorPos + 1)
  }
}

在我的项目里面打印一下 process.env,发现一些 npm 相关变量:

{
  "npm_config_email": "xxx",
  "npm_package_scripts_dev": "webpack serve --env development",
  "npm_config___xnpm_ximalaya_com__always_auth": "",
  "npm_package_sideEffects": "false",
  "npm_config_registry": "https://registry.npmmirror.com/",
  "npm_config_home": "https://npmmirror.com",
  "npm_package_description": "",
  "npm_package_license": "ISC",
  "npm_config_set": "registry",
  "npm_execpath": "/Users/xmly/.local/share/fnm/node-versions/v20.16.0/installation/lib/node_modules/pnpm/bin/pnpm.cjs",
  "npm_config_frozen_lockfile": "",
  "npm_config_http___xnpm_ximalaya_com": "",
  "npm_package_name": "web",
  "npm_package_scripts_build": "webpack --env production",
  "npm_config_config": "set",
  "npm_lifecycle_script": "webpack --env production",
  "npm_lifecycle_event": "build",
  "npm_config_user_agent": "pnpm/9.12.2 npm/? node/v20.16.0 darwin arm64",
}

其中:

  • npm_config_user_agent: 包含了包管理器信息
  • npm_lifecycle_event: 指调用的 scripts
  • npm_lifecycle_script: 调用的 scripts 对应的脚本

于是,我完全可以通过 npm_lifecycle_eventnpm_package_scripts_build 判断是开发环境还是生产环境

例如,在 webpack.config.js 中:

/**
 * @returns {import("webpack").Configuration}
 */
export default () => {
  const isDev = /dev|start/i.test(process.env.npm_lifecycle_event);
  process.env.NODE_ENV = isDev ? 'development' : 'production';
  const mode = isDev ? 'development' : 'production';
  const stats = isDev ? 'errors-warnings' : 'normal';
  const devtool = isDev ? 'inline-source-map' : false;

  return {
    mode,
    devtool,
    stats,
    ...
  };
};

只要判断是否调用了 start 或 dev 命令,就可以判断是否为开发环境

同理,也可以通过 npm_lifecycle_script 来判断,如果脚本中包含 devServer,就是开发环境

不过有些依赖包是通过 process.env.NODE_ENV 来判断环境的,还是需要显性地更改一下