最近碰到一个问题:公司新申请了一个公众号,这个新公众号的功能与之前一个公众号功能基本一致,只是两个公众号的用户协议有些区别,所以就会公用一份代码。现在需要解决发布的问题,需要确保发布到两个不同公众号的页面是正确的,不同公众号的用户看到正确的用户协议。
经过上网查找方案,发现 Vue
脚手架中提供的 vue-cli-service
内置了类似的功能,可以用来实现类似功能,这里简单说一下其涉及到的改动要点,更多细节可以参考vue-cli
的文档模式和环境变量。
1. 官方方案解读
1.1 模式
模式(mode
)是 Vue
脚手架项目的一个重要概念。默认情况下,一个脚手架项目会有三个模式:
development
模式用于vue-cli-service serve
test
模式用于vue-cli-service test:unit
production
模式用于vue-cli-service build
和vue-cli-service test:e2e
我们通常用的开发命令 yarn serve
,yarn build
都是由 package.json
封装的 Vue
脚手架命令的简化版:
1{
2 "name": "mp-web",
3 "version": "0.1.0",
4 "private": true,
5 "scripts": {
6 "serve": "vue-cli-service serve",
7 "build": "vue-cli-service build",
8 "lint": "vue-cli-service lint"
9 },
10}
可以看到,yarn serve
对应的就是 development
模式;yarn build
对应的是 production
模式。
1.2 环境变量
NodeJS
应用中有一个非常重要的环境变量 NODE_ENV
。Vue
脚手架中也使用了这个环境变量。NODE_ENV
决定应用运行的模式,是开发,生产还是测试,因此也决定了创建哪种 webpack
配置。文档中说明如下:
例如通过将 NODE_ENV 设置为 “test”,Vue CLI 会创建一个优化过后的,并且旨在用于单元测试的 webpack 配置,它并不会处理图片以及一些对单元测试非必需的其他资源。
同理,NODE_ENV=development 创建一个 webpack 配置,该配置启用热更新,不会对资源进行 hash 也不会打出 vendor bundles,目的是为了在开发的时候能够快速重新构建。
当你运行 vue-cli-service build 命令时,无论你要部署到哪个环境,应该始终把 NODE_ENV 设置为 “production” 来获取可用于部署的应用程序。
除了 NODE_ENV
外,还可以指定其他环境变量。在文档中提到可以在 .env
或 .env.[mode]
文件中指定环境变量,起始还可以直接在命令行中通过 export
方式设置环境变量。需要特别注意的是,不是所有的本地环境变量都可以在代码中能够见到。按照文档的说明,只有如下几个可以:
NODE_ENV
;BASE_URL
;VUE_APP_
开头的环境变量; 其他的环境变量,会被脚手架过滤掉,以防止关键信息泄露。
2. 改造项目
根据官方提供的功能,对项目进行了调整,这里记录一下调整的主要内容,以此记录一下。
2.1 用户协议
两份用户协议分别定义成了两个组件,然后在使用的页面根据情况选择显示。代码实例如下:
1<template>
2 <div>
3 <div class="content">
4 <!-- <div class="title">协议内容</div> -->
5 <div class="agreementCont" v-if="site === 'palytech'">
6 <v-nycont></v-nycont>
7 </div>
8 <div class="agreementCont" v-else>
9 <v-cont></v-cont>
10 </div>
11 </div>
12</template>
13<script lang="ts">
14import agreementCont from '@/components/agreementCont/content.vue';
15import nyContent from '@/components/agreementCont/nyContent.vue';
16@Component({
17 components: {
18 'v-cont': agreementCont,
19 'v-nycont': nyContent
20 }
21})
22export default class infoPerfection extends Vue {
23 site: string | null = '';
24 async mounted() {
25 this.site = localStorage.getItem('site');
26 }
27...
页面中使用site
这个变量来决定显示哪一个用户协议。而这个site
参数是从localStorage
中获取到的。下面会说到这个site
参数是如何写到localStorage
中的。
2.2 main.ts
在 Vue
代码入口的main.ts
中,写入如下代码,这段代码会将site
参数写入localStorage
。注意这里用到了VUE_APP_SITE
这个环境变量。
1import Vue from 'vue';
2import App from './App.vue';
3
4if (process.env.VUE_APP_SITE === 'zhongbl') {
5 console.log('生产环境 zhongbl');
6 localStorage.setItem('site', 'zhongbl');
7} else if (process.env.VUE_APP_SITE === 'palytech') {
8 console.log('生产环境 palytech');
9 localStorage.setItem('site', 'palytech');
10} else {
11 console.log('开发环境 eveus');
12 localStorage.setItem('site', 'eveus');
13}
2.3 环境变量设置
考虑到我们的发布脚本中硬编码了yarn build
,所以环境变量VUE_APP_SITE
我是采用export
方式设置的。例如编译的时候用:
1export VUE_APP_SITE=zhongbl
2# 调用原先的发布脚本
3bash /opt/release/build-deploy-vue.sh -p $Project -s $Service
需要注意的是:必须使用export
将环境变量设置出去,要不然在另一个shell脚本中会看不到这个变量。
另外,还可以在.env
文件中设置一个默认值,当不在命令行中export
的时候,就会用到.env
文件中设置的值。
3. 其他的一些备忘
3.1 编译结果
2.2
中的那段代码经过编译后,会根据环境变量的情况进行优化,去掉不需要的内容。例如,当VUE_APP_SITE
设置成palytech
的时候,最后生成的代码等效于:
1 console.log('生产环境 palytech');
2 localStorage.setItem('site', 'palytech');
其他两个条件中的内容根本不会在编译结果中存在!这点挺有意思的。