在一次国际化需求中,我们需要打出不同的包满足不同语言的需求,如果按照根据不同命令打包,那么package.json则会越来越多,例如:
这样的话背离了我们代码的初衷,如果这样写下去,世界这么多语言,我们需要多少命令可以满足?那么到时候的package.json中的scripts需要多长?
所以,当我看到inquirer的时候,我萌生出了一个大胆的想法:使用交互式命令进行打包的配置;
具体如图:
inquirer.js 一款极为友好及便捷的用户与命令行交互工具。vue-cil脚手架工具也使用了他,详细参考文档vue-cli文档
inquirer.js主要功能有:
提供错误反馈
错误反馈
问问题
解析输入
验证答案
管理分层提示
当然,本文不是教写cli脚手架工具的文章,这里大致说一下inquirer的基本参数:
由于交互的方式不一致,有些是提示输入,有些是叫你选择,因此参数也不一致
- type:表示提问的类型,包括:input, confirm, list, rawlist, expand, checkbox, password, editor;
- name: 存储当前问题回答的变量,即字段名
- message:问题的描述;
- default:默认值;
- choices:列表选项,在某些type下可用,并且包含一个分隔符(separator);
- validate:对用户的回答进行校验;
- filter:对用户的回答进行过滤处理,返回处理后的值;
- transformer:对用户回答的显示效果进行处理(如:修改回答的字体或背景颜色),但不会影响最终的答案的内容;
- when:根据前面问题的回答,判断当前问题是否需要被回答;
- pageSize:修改某些type类型下的渲染行数;
- prefix:修改message默认前缀;
- suffix:修改message默认后缀。
例子我就不举了,因为关于inquirer的有很多例子可以搜到;
身为一个初级前端,node-cmd是通过自己不断试错找到的最好的解决方式
node-cmd npm
关于他的具体描述,我觉得我并没有官方总结的好,因此,具体使用查看官方文档,我这里大致说一下他的使用:
node-cmd拥有两种使用方式:
// 引入
var cmd=require('node-cmd');
// 通过get的方式,有回调,可以进行下一步操作
cmd.get(
'pwd',
function(err, data, stderr){
console.log('the current working dir is : ',data)
}
);
// run 仅提供需要使用的命令
cmd.run('touch example.created.file');
目前,稳重具体使用的两个包已经介绍完毕,当然,此处默认安装了cross-env(因为公司项目中必须使用的原因,我也没办法)
npm install inquirer -save
npm install node-cmd -save
为了使配置更加灵活,我将命令行中的问题抽出到src/config/config.js进行了可配置的操作,便于项目的通用性
// 命令行问题抽出进行配置,之后build.js不用动
let lang = require('./src/config/config.js');
const inquirer = require('inquirer');
var cmd = require('node-cmd');
var Promise = require('bluebird');
const getAsync = Promise.promisify(cmd.get, { multiArgs: true, context: cmd })
let promps = lang;
var step = 0;
var condition = []
// 因为配置的不确定性,所以此处做了递归,将根据传入的lang进行比较
function selected(step) {
if (step < promps.length) {
console.log(step);
inquirer.prompt(promps[step]).then(async (answers) => {
step++;
condition.push(answers);
return selected(step)
})
} else {
let consoleText = [];
let crossText = [];
// vue-cil 基础打包命令
let npm_run_build = './node_modules/.bin/vue-cli-service build';
for (let i = 0; i < condition.length; i++) {
consoleText.push(condition[i]['lang']['title'])
crossText.push(`${condition[i]['lang']['name']}=${condition[i]['lang']['type']}`);
}
let build = `./node_modules/.bin/cross-env ENV_file=model-h5 ${crossText.join(' ')} ${npm_run_build}`
console.log(`正在打包${consoleText.join('-')}包,请稍等片刻。。。。。。。。`)
getAsync(build).then(data => {
console.log('打包成功')
}).catch(err => {
console.log('打包失败', err)
})
}
}
selected(step)
// 至此,与用户的所有交互均已完成,answers是收集到的用户所填的所有数据
新建src/config/config.js
module.exports = [
[
{
type: 'list',
name: 'lang',
message: '请选择打包环境',
choices: [
{
name: '测试环境',
value: {
type: 'dev',
// 项目中根据cross env 添加了BUILD_ENV区分生产测试,不用可以删除
name: 'BUILD_ENV',
title: '测试环境'
}
},
{
name: '生产环境',
value: {
type: 'pro',
name: 'BUILD_ENV',
title: '生产环境'
}
},
],
default: 0 // 默认值为列表项编号,起始为 0
},
],
[
{
type: 'list',
name: 'lang',
message: '请选择打包语种',
choices: [
{
name: '英文',
value: {
type: 'en',
// 项目中根据cross env 添加了VUE_APP_PROJECT区分语种en、zh等等等等,不用可以删除
name: 'VUE_APP_PROJECT',
title: '英文'
}
},
{
name: '中文',
value: {
type: 'zh',
name: 'VUE_APP_PROJECT',
title: '中文'
}
},
],
default: 0 // 默认值为列表项编号,起始为 0
}
]
]
npm run build:node
此时,一个完美的互动命令行式分环境打包配置完成!!!!是不是很简单,很想给个赞???
虽然根据命令行打包很简单,而这个方式相对于那种方式而言更加复杂,但是,人生就是在不断的挑战和失败中一次一次爬起,不断的去寻求不同的方式,不同的想法,是每一个程序猿的必经之路,这么做的目的只是为了省几行package.json的代码,却新增了其他的代码,但是好处又在于之后的人在接手项目的时候不用担心每次打包的命令,只要按照交互式的方式走下去,肯定是没有问题的,因为前人已经踩过坑了。
路漫漫其修远兮,吾将上下而求索