大家好,我是若川。持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步。同时极力推荐订阅我写的《学习源码整体架构系列》 包含20余篇源码文章。历史面试系列
本文来自读者@漫思维 投稿授权
原文链接:https://juejin.cn/post/7072677637117706270
1前言
以下我会列举出我业务中遇到的问题难点及相对应的解决方法,解释简繁体插件怎么诞生的整个过程
2背景
目前开发工作有大量的营销活动需要编写,特点是小而多,同时现阶段项目需要做大陆与港台两个版本
3现阶段实现的方案
先做完大陆版本,最后再复刻一份代码, 改成港台版本
将项目中的汉字、价格、登录方式进行替换。
4存在的问题
首先复制来复制去就不是一个很好的方案,容易复制出问题,其次两个版本都是需要同一个时间点上线,复刻代码的代码的时机存在问题,如果复刻的过早,如果提测阶段大陆版本有bug, 那么就需要修改两份bug, 如果复刻的过晚那么会存在港台版本测试时间不足,也易导致问题发生。
简繁体转换,都是将简体手动复制到谷歌翻译网页端中翻译好,再手动替换,繁琐且工程量大, 登录方式需要单独的复制一份。
5两个版本之间存在以下不同点
登录方式的不同, 大陆主要是用账号密码登录,而港台使用谷歌、脸书、苹果登录
价格、单位不同,¥ 与 NT$
汉字的形式不同,中文简体与中文繁体
核心问题在于复刻出一份项目存在的工作量与潜在风险较大,所以需要将两个项目合成一个项目,怎么解决?
6解决方案
1. 将两个项目合并成一个项目
如果需要将两个项目合成一个项目,并解决以上分析出来的不同点,那么显而易见,需要有个一标识去区分,那么使用环境变量
解决这个问题是非常合适的,以vue项目举例, 可以编写对应的环境变量配置。
大陆版本生产环境:.env
VUE_APP_ENV=prod
VUE_APP_PUBLIC_PATH=/mainland
大陆版本开发环境:.env
VUE_APP_ENV=dev
VUE_APP_PUBLIC_PATH=/mainland
港台版本开发环境:.env.ht
VUE_APP_ENV=ht
VUE_APP_PUBLIC_PATH=/ht
NODE_ENV=production
package.json
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"build:ht": "vue-cli-service build --mode ht",
可以看到这里使用了一个自定义变量 VUE_APP_ENV
, 在项目代码中就可以使用 process.env.VUE_APP_ENV
去做区分当前是大陆还是港台了,同时为什么不使用NODE_ENV
作为变量,因为该变量往往会有其他用途,如当NODE_ENV
设置为production
时,打包时会做一些如压缩等优化操作。
注: 港台版本不做测试环境的区分,因为往往大陆版的逻辑没有问题,港台版的就没有问题,所以只需要基于大陆版开发,港台版只需要最后打包一次即可 **(测试环境可选,只需要多添加一个配置即可)**。
其他注意点: process.env.VUE_APP_ENV
通常只能在node
环境下才能访问的,但是vue-cli
创建项目会自动将.env
里的变量注入到运行时环境中,也就是使用一个全局变量存起来,通常是使用webpack
的define-plugin插件实现的。
解决了环境变量的问题,接下来的工作就比较好进行了。
2. 解决登录方式的不同
将两套登录封装成两个不同的组件,因为登录往往涉及到一些全局状态,项目一般都会使用vuex
等全局状态管理工具,所以默认使用vuex
储存状态,把整个包含登录逻辑的代码制作成一个项目的基础模板,使用自定义脚手架
拉取即可,同时注意使用vuex
时,为登录相关的状态,放置到一个module
下,这样基于该模板创建项目后, 每个项目的其它状态单独再写module
即可,避免修改登录的module
。
自定义脚手架
:交互式创建项目,输入一些选项,如项目名称,项目描述之类的,再从gitlab
等远程仓库拉取已经写好的模板,将模板中的一些特定变量,使用模板引擎将模板中的项目名称等替换,最终产生一个新的项目。(脚手架还有其他用途,这里只描述使用它创建一个简单的项目)
没有脚手架那就只能使用
git clone
下来后再修改项目名称之类的东西,会增加一点额外的工作,但不影响不大。
封装的部分逻辑:
比如大陆的登录组件叫做 mainlandLogin
, 港台的登录组件叫 htLogin
,再写一个 login
组件将他们整合,通过环境变量
进行区分引入不同的组件,使用component
动态加载对应的登录组件如下:
login.vue:
<component :is="currentLogin" @sure="sure" cancel="cancel"></component>
data:{
return {
currentLogin: process.env.VUE_APP_ENV === 'ht' ? 'mainlandLogin' : 'htLogin'
}
},
components: {
mainlandLogin: () => import("./components/mainlandLogin.vue"),
htLogin: () => import("./components/htLogin.vue"),
},
method:{
sure(){
this.$emit('sure')
},
cancel(){
this.$emit('cancel')
}
}
注意: 引入组件的方式使用动态加载,打包时会将两个组件打包成两个单独的chunk</