需要在一套小程序代码中输出多个小程序。之前是通过在npm srcipts配置环境变量,然后编译代码中通过process.env获取:

1
2
3
4
5
6
7
8
scripts: {
"dev:dev": "cross-env NODE-ENV=dev gulp-dev",
"dev:test": "cross-env NODE-ENV=test gulp-dev",
"dev:prod": "cross-env NODE-ENV=prod gulp-dev",
"build:dev": "cross-env NODE-ENV=dev gulp-build",
"build:test": "cross-env NODE-ENV=test gulp-build",
"build:prod": "cross-env NODE-ENV=prod gulp-build",
}

但是现在有三个小程序,未来可能更多,如果要写一堆scripts就很烦了。考虑在控制台做交互,选择小程序,再选择环境,然后编译。这样scripts就可以简化了。

在node中,可以通过安装inquirer这个包来实现。可以实现类似vue-cli那种交互。

inquirer

可以在终端中实现输入、确认、单选、多选操作,返回一个promise。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import inquirer from 'inquirer';

inquirer
.prompt([
/* Pass your questions in here */
])
.then((answers) => {
// Use user feedback for... whatever!!
})
.catch((error) => {
if (error.isTtyError) {
// Prompt couldn't be rendered in the current environment
} else {
// Something else went wrong
}
});

改造小程序

配置文件和首页

我们现在有多个小程序,不同环境的配置有多份。按照小程序名称,在config目录新建多个目录,存放各自的环境配置。另外,这几个小程序基本一样,只有首页我们做成独立的,有多个首页,按照小程序名称都放在pages目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
.
├── .git
├── config
│ ├── a
│ │ ├── base.js
│ │ ├── config.dev.js
│ │ ├── config.local.js
│ │ ├── config.prod.js
│ │ └── config.test.js
│ ├── b
│ │ ├── base.js
│ │ ├── config.dev.js
│ │ ├── config.local.js
│ │ ├── config.prod.js
│ │ └── config.test.js
│ ├── c
│ │ ├── base.js
│ │ ├── config.dev.js
│ │ ├── config.local.js
│ │ ├── config.prod.js
│ │ └── config.test.js
│ └── option.js
├── dist
├── src
│ ├── pages
│ │ ├── index-a
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ └── index.sjs
│ │ ├── index-b
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ └── index.sjs
│ │ ├── index-c
│ │ │ ├── index.html
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ ├── index.less
│ │ │ └── index.sjs
...

npm scripts

1
2
3
4
scripts: {
"dev": "gulp-dev",
"build": "gulp-build",
}

gulpfile

在gulpfile中加入inquirer代码。为了方便以后快速修改配置,把问题选项配置也放在config目录了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
envs: [
{ name: '本地', value: 'local' },
{ name: '开发', value: 'dev' },
{ name: '测试', value: 'test' },
{ name: '生产', value: 'prod' },
],
apps: [
{ name: '小程序a', value: 'a' },
{ name: '小程序b', value: 'b' },
{ name: '小程序c', value: 'c' },
],
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const inquirer = require('inquirer');
const options = require('./config/option.js');
const merge = require('deepmerge');

let env;
let app;

...
function getOption () {
const promptList = [
{
type: 'list',
message: '请选择应用:',
name: 'app',
choices: options.apps
},
{
type: 'list',
message: '请选择环境:',
name: 'env',
choices: options.envs
}
];
return inquirer.prompt(promptList)
.then(answer => {
console.log(answer);
app = answer.app;
env = answer.env;
return answer;
});
}
gulp.task('init', done => {
return getOption();
});
gulp.task('env', done => {
const baseConfig = require(`./config/${app}/base.js`);
const envConfig = require(`./config/${app}/config.${ENV}.js`);
const config = merge(baseConfig, envConfig);

return string_src('config.json', JSON.stringify(config, null, 2))
.pipe(rename(function (path) {
path.extname = '.json';
}))
.pipe(gulp.dest(OUTPUT_PATH));
});
gulp.task('index', done => {
return gulp.src(`${OUTPUT_PATH}/pages/index-${app}/**/*`)
.pipe(gulp.dest(`${OUTPUT_PATH}/pages/index`));
});

...

// 开发编译
gulp.task('dev', gulp.series('clean', 'init', 'env', 'checkDist', 'main', 'index', 'watch', done => {
done();
const endTime = Date.now();
console.log(chalk.blue('当前环境是:' + ENV));
console.log(chalk.green('编译用时' + ((endTime - startTime) / 1000) + 's'));
console.log(chalk.yellow('监听中'));
}));

// 生产编译
gulp.task('build', gulp.series('clean', 'init', 'env', 'checkDist', 'main', 'index', done => {
done();
const endTime = Date.now();
console.log(chalk.blue('当前环境是:' + ENV));
console.log(chalk.green('编译完成,用时' + ((endTime - startTime) / 1000) + 's'));
}));

我们在dev和build顺序任务中,先加入一个init方法,里面调用inquirer询问,返回答案,修改选项。然后后续env任务,根据修改的app和env变量,读取指定配置文件,输出到dist/config.json。最后,在一些列编译任务执行完之后,再加一个index任务,将dist/index-{app}页面复制到dist/index页面。

后续再扩充小程序,我们只需要添加配置和首页即可。

  1. 优化

修改OUTPUT目录,clean时清除目录仅限dist/{app},编译后输出到dist/{app}。

再调整任务执行顺序,先执行init,根据当前app修改OUTPUT值,再执行clean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// gulpfile改动
let OUTPUT_PATH = './dist';

function getOption () {
...
OUTPUT_PATH = `./dist/${app}`;
}

// 开发编译
gulp.task('dev', gulp.series('init', 'clean', 'env', 'checkDist', 'main', 'index', 'watch', done => {
done();
const endTime = Date.now();
console.log(chalk.blue('当前环境是:' + ENV));
console.log(chalk.green('编译用时' + ((endTime - startTime) / 1000) + 's'));
console.log(chalk.yellow('监听中'));
}));

// 生产编译
gulp.task('build', gulp.series('init', 'clean', 'env', 'checkDist', 'main', 'index', done => {
done();
const endTime = Date.now();
console.log(chalk.blue('当前环境是:' + ENV));
console.log(chalk.green('编译完成,用时' + ((endTime - startTime) / 1000) + 's'));
}));