mockjs区分环境, 过程很有趣
起因.
- 网上找了很多mockjs(是mockjs不是其他的mock插件)环境的配置, 基本全是错的.
- 生产环境不需要mock, 开发环境有时需要mock有时不需要mock.
- 可能这个功能点太小了, 导致大家都不在乎.
- 但是越小的点越有趣味.
一. 要达到的效果
- 不可以手动注释掉import './mock'这段话, 因为只要是人为操作就会存在失误的可能性.
- 用es6的模块规则书写, 而不用common
- 区分 yarn mock 与 yarn xxx
- 写着爽, 可扩展, 核心代码不用动
二. 想到的各种方法与坑
方法一. 我们公司之前使用的是"express
"自己起了一个服务, 然后读取文件夹名为path, 内容当然就是内容了, 这样做也没问题, 但是毕竟不是专业的处理方式, 比如同一个path既是get地址又是post地址, 那这个区分起来就需要改动代码了, 还有就是在模拟数据的随机性上几乎没有, 比如mockjs可以模拟 1-12位的数字返回, 而当前这种方式只能"写死", 是在不是写个随机函数然后每次都调用函数, 这样越做越大没实际意义, 还不如采用成熟的方案.
方法二:
mockjs
下载: yarn add mockjs -D 只是开发使用, 谁会把这个放到生产??
调用: import Mock from 'mockjs'
具体怎么配置就不说了, 简单的过分, 一会可以说下工程化
方法三:
封装好的axios请求外面, 再封装一层mock层, 这个就想想吧,太邪门歪道了.
三. 知识点与坑点(好玩的来了)
网上都说利用cross-env
来区分环境变量, 但是这里有个大坑你知道么???
我选择的是"cross-env": "^6.0.3"
在package.json里面配置 "mock": "cross-env MOCK=true vue-cli-service serve",
本以为大功告成了, 在main.js里面下面代码完全不执行if(process.env.MOCK === 'true'){...}
坑点1:
cross-env属于node环境, 这个值在web代码里面是取不到的, 这个值可以在vue.config.js里面import我们的mockjs, 但是会报错, 不可以使用es6的引入方式, 需要commonjs的方式里面拿到, 那我们转移战场, 在 vue.config.js里面import我们的mockjs, 但是会报错, 不可以使用es6的引入方式, 需要commonjs的方式require
进来
(想要在客户端侧代码中使用环境变量: process.env.VUE_APP_xxx
, 但是有这个变量 import语法也不支持按需决定引入与否)
坑点2:
用require
的方式引入mockjs, 那么意味着mock文件的工程化不能用es6的写法去做了, 真的忍不了啊
坑点3: require
的方式引入会报Mock.setup
找不到的错误, 这个估计是mockjs本身就没想让用户这样引用.
坑点4:
用require
的方式引入了,也执行了, 但是无效, 因为mockjs的实现方式不是在外界起一个服务然后监听一个工程的请求.
想其他办法吧
首先mock既然需要import的方式在main.js里面引入, 那我还就这样使用了, 那我们其实可以在文件级别来解决这个问题, 问题被提炼出来了在main.js文件里面yarn mock
的时候加上'"import './mock'"
', yarn xxx
去掉"import './mock'"
, 这很清晰明了了,真的很暴力.
涉及到修改文件node出场
先来规范一个站位符吧, 毕竟需要区分是否插入, 以及插在哪里, 这样后来的同学也能顺藤摸瓜找到整体的逻辑
大家一定要注意, 代码一定要是连续的, 不可以出现凭空出现某些逻辑这种写法, 比如vue的mixins方法, 这个会导致项目很难交接, 无法定位问题等等坏处
1.// mock : 短小精悍,缺点明显, 不定谁就该删除了.
2./** mock(不要删除) **/
: 比第一个更有戏剧性了.
3.不写占位符, 直接操作, 这样就是不符合代码逻辑连贯性原则, 新同学可能都不知道你的操作怎么实现的, 不建议完全无感的操作, 虽然留一个占位符看着挺low, 但是方便追溯.
node判断文件内容(简单的替换)
添加逻辑
const path = require('path');
const fs=require("fs");
let main = fs.readFileSync( path.resolve(__dirname, '../src/main.js'),'utf-8');
main = main.replace('/** mock(不要删除) **/', "import '../mock'");
fs.writeFile(path.resolve(__dirname, '../src/main.js'), main, 'utf8', (err) => {
if (err) throw err;
console.log('成功引入mock数据');
});
删除逻辑
const path = require('path');
const fs=require("fs");
let main = fs.readFileSync(path.resolve(__dirname, '../src/main.js'),'utf-8');
main = main.replace( "import '../mock'", '/** mock(不要删除) **/');
fs.writeFile(path.resolve(__dirname, '../src/main.js'), main, 'utf8', (err) => {
if (err) throw err;
console.log('去掉mock数据');
});
两个脚本写完开始引入把(下面代码的错误你看出来了么)
"scripts": {
"mock":"node ./mock/add.js vue-cli-service serve",
"serve": "node ./mock/delete.js vue-cli-service serve",
"build": "node ./mock/delete.js vue-cli-service build"
},
运行起来你就会发现vue-cli-service serve不执行, 这是因为这条语句需要区分一下
很多同学这里进坑了, 下面的写法有时也是有bug的
"scripts": {
"mock":"node ./mock/add.js && vue-cli-service serve",
},
正确的写法如下 &&需要紧贴 node语句, 否则可能会有莫名其妙的bug出现, 也算是小知识.
"scripts": {
"mock":"node ./mock/add.js&& vue-cli-service serve",
},
我也想过, 每行都写node ./src/mock/add.js
这种代码 , 不如把每个命令都放在node里面就好了, 直接npx之类的去执行就可以了, 但是我不这样做还是因为上面的原因, 这样写会打乱其他同学的编写习惯, 让别人蒙b但是效益不大, 那么就不要去做了.
四. 工程化结构
本着工程化的原则,肯定是要单独建立一个mock文件夹, 这个不要放在src里面了, 要与src平级, 里面的index文件负责导出所有的接口, 因为考虑到大的需求可能会新增几十个接口, 所以我还是建议再建立一个本次版本的mock接口的文件夹, 这样也方便集体删除不留后遗症, 如果某些接口需要mock很复杂的数据形式, 那还是要单独建立一个文件来存放他的逻辑内容, 虽然mock的时候不写method默认就是get, 我还是建议吧get 写上, 这样更直观
五. 总结
整体缺少美感, 但是也算是一种思路, 过程挺好玩的我就分享出来了, 虽然没有难点但挺有意思的.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。