如何实现Nuxt.js 3多环境部署运行同一编译产物

前端 潘老师 1个月前 (03-24) 18 ℃ (0) 扫码查看

在公司的项目里,我们使用Nuxt.js 3架构搭建了前端项目,并且部署到多个不同的环境中,像开发环境(dev)、测试环境(test)、预发布环境(staging)、集成测试环境(sit)、用户验收测试环境(uat)以及生产环境(prod)。

以往在这些环境部署时,我们会借助dotenv工具,为每个环境配置对应的.env.*文件。每次部署都要针对不同环境执行一次编译打包流水线,虽说部署流程已经实现了自动化,但编译打包的过程耗时很长。

于是,我们就有了一个新需求:只进行一次编译打包,让所有环境都使用这同一批编译产物。这样一来,不仅能大幅节省部署时间,还能减少因不同编译环境带来的差异问题。

要实现这个目标,难点在于.env.*文件里的配置在编译阶段就会被固定到产物代码中,运行时无法更改。所以,关键就是把配置从编译阶段传入改为运行阶段传入。同时,我们也不能再采用编译成静态文件运行的方式,而是需要借助node或者pm2这类管理软件来运行Nuxt.js项目。

下面我分享的方法,不一定是每个项目的最佳解决方案,仅供大家参考。在这个方案里,我们会利用Nuxt.js的runtime-config功能来达成上述需求。项目代码托管在nuxtjs – demo 。

一、理解环境变量在项目中的作用

在Node.js中,获取环境变量使用process.env.*这种方式,但前提是操作系统里已经配置好了相应的环境变量。比如在类Unix操作系统里,执行export API_PREFIX=/api这条命令,就能设置API_PREFIX这个环境变量的值为/api ,之后在Node.js代码里,就可以通过process.env.API_PREFIX获取到这个值。Nuxt.js正是利用了Node.js的这个特性来实现环境变量的注入。在代码里,获取环境变量就像这样:

const apiPrefix = process.env.API_PREFIX

不过,这里有个问题。在编译阶段,代码里所有的process.env.*都会被编译成对应的字符串。这里我们不讨论webpack中的NODE_ENV,只聚焦Nuxt.js里的环境变量。

二、Nuxt.js配置文件的设置

Nuxt.js架构提供了nuxt.config.ts这个配置文件供开发者进行配置。其中runtimeConfig的配置要遵循Nuxt的规范:runtimeConfg.public里的键采用小驼峰命名法,值先留空。这样,Nuxt会自动注入带有NUXT_PUBLIC_前缀的环境变量,而且这些变量需要配置在.env.*文件里。

要是不按照Nuxt的规范来配置,那就只能通过process.env.*的方式获取配置,可这样一来,配置在编译阶段就会被编译到产物代码中,又回到了最初的问题。下面看看规范配置和不规范配置环境变量的示例。

# .env文件配置示例
NUXT_PUBLIC_API_PREFIX=/api
NUXT_PUBLIC_BASE_SERVICE_URL=http://192.168.1.20:8080/
NUXT_PUBLIC_USER_SERVICE_URL=http://192.168.1.21:8080/
# 不按规范,没有NUXT_PUBLIC前缀
OFFICIAL_WEBSITE_URL=https://www.example.com

私密配置规范示例:

# 按照规范配置NUXT前缀
NUXT_PUBKEY=公钥

nuxt.config.js文件里的配置如下:

{
  // 添加runtimeConfig配置
  runtimeConfig: {
    public: {
      // @see https://nuxt.com/docs/guide/going-further/runtime-config#example
      apiPrefix: '', // 可以被NUXT_PUBLIC_API_PREFIX环境变量覆盖
      baseServiceUrl: '', // 可以被NUXT_PUBLIC_BASE_SERVICE_URL环境变量覆盖
      userServiceUrl: '', // 可以被NUXT_PUBLIC_USER_SERVICE_URL环境变量覆盖
      official_website_url: process.env.OFFICIAL_WEBSITE_URL, // 仅能够通过process.env来获取,并在编译阶段编译进代码
    },
  },
}

三、ecosystem.config.cjs配置文件

ecosystem.config.cjs是docker运行pm2时读取的配置文件。apps.env会把docker中的环境变量注入进来,这里env里的键要和nuxt.config.ts里的runtimeConfig对应使用。如果是runtimeConfig.public里的变量,注入时必须带上NUXT_PUBLIC_前缀。配置示例如下:

module.exports = {
  apps: [
    {
      name: 'website-nuxt',
      exec_mode: 'cluster',
      instances: '1',
      script: '.output/server/index.mjs',
      args: 'start',
      env: {
        NUXT_PUBLIC_API_PREFIX: process.env.API_PREFIX,
        NUXT_PUBLIC_COLLEGE_URL: process.env.COLLEGE_URL,
        NUXT_PUBLIC_LOGIN_REGISTER_URL: process.env.LOGIN_REGISTER_URL,
      },
    },
  ],
};

四、客户端与组件中的配置使用

客户端会把配置渲染到html里,示例如下:

<script>
  window.__NUXT__.config = {
    public: {
      apiPrefix: '/api',
      collegeUrl: 'http://192.168.0.212:85/',
      loginRegisterUrl: 'http://192.168.0.212:82/',
    }
  }
</script>

在组件里编写代码时,正常使用这些配置就行。示例代码如下:

<template>
  <div>
     {{ message }}
  </div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue'

const message = ref('')

const runtimeConfig = useRuntimeConfig()

onMounted(() => {
  console.log(runtimeConfig.public)
  message.value = runtimeConfig.public
  // test()
})
</script>

五、本地开发环境配置

在本地开发时,还是可以正常使用dotenv。建议从.env.example复制一份.env.local文件,在.env.local里配置参数。它会和.env合并,而且.env.local的优先级更高。不过要注意,.env.local不要提交到代码仓库,提交到仓库的.env.*文件里不应该包含敏感信息。示例配置如下:

NUXT_PUBLIC_API_PREFIX=/api
NUXT_PUBLIC_COLLEGE_URL=http://192.168.0.212:85/
NUXT_PUBLIC_LOGIN_REGISTER_URL=http://192.168.0.212:82/

六、多环境部署

(一)docker部署多环境

运行时的环境变量参考ecosystem.config.cjs里的env配置,而ecosystem.config.cjs里的env又参考nuxt.confg.tsruntimeConfig中的public变量。

(二)编译docker镜像

编译docker镜像的命令如下:

docker build --pull --rm -f "Dockerfile" -t nuxtjs-demo:latest "."

(三)运行docker容器

运行示例:

# 环境1
docker run -e "API_PREFIX=/api" \
    -e "COLLEGE_URL=http://192.168.0.212:85/" \
    -e "LOGIN_REGISTER_URL=http://192.168.0.212:82/" \
    -it -p 127.0.0.1:3002:3000 -d --rm --name nuxtjs-demo nuxtjs-demo:latest
    
# 环境2
docker run -e "API_PREFIX=/api" \
    -e "COLLEGE_URL=地址1" \
    -e "LOGIN_REGISTER_URL=地址 2" \
    -it -p 127.0.0.1:3002:3000 -d --rm --name nuxtjs-demo1 nuxtjs-demo:latest

这里需要注意,如果使用的是arm系统,比如苹果芯片的mac,可能会遇到平台兼容的问题。运行时可能会出现警告:

WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

可以通过以下方式指定平台:

  1. 设置Docker默认平台:为了在运行或构建镜像时默认使用AMD64平台,可以设置环境变量DOCKER_DEFAULT_PLATFORM。在终端执行命令:
export DOCKER_DEFAULT_PLATFORM=linux/amd64

也可以把这条命令添加到~/.bashrc~/.zshrc文件里,这样每次启动终端时就会自动设置。
2. 运行或构建指定平台的Docker镜像:设置好默认平台后,就可以运行或构建指定平台的Docker镜像了。比如运行一个AMD64的Ubuntu镜像:

docker run --rm -it --platform=linux/amd64 ubuntu:latest

构建镜像时指定平台为AMD64的命令如下:

docker build --platform=linux/amd64 -t myimage:latest.

通过上述一系列操作,就能实现用同一编译产物在多个环境中运行Nuxt.js 3项目,希望对大家有所帮助。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/front/16221.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】