开发小程序时,最麻烦的事情莫过于在上线前需要反复切换测试和正式环境接口地址。
本文介绍一种小程序工程化改造的思路,基于这个我们能够实现小程序自动根据多环境打包。
参考项目
https://github.com/mecoepcoo/miniprogram-boilerplate
准备工作
阅读本文,你需要有对以下内容的基本认知:
工程化改造
原生的小程序只有一个简单的启动脚手架,不支持less、sass等样式预处理器,对npm的支持也不是太好,我们自己做一个简单的构建工具,来增强小程序的功能。本节起一个抛砖引玉的作用,基于这个思路,可以改造出更多更强大的功能。
目录结构
- dist 输出/发布目录,在微信开发者工具中打开这个目录
- project.config.json 配置文件,这个文件与src中的配置无关
- src
- miniprogram
- assets 静态资源目录,放图片之类的东西
- components 组件目录
- pages 小程序页面目录
- app.js 小程序入口
- app.json 小程序全局配置
- app.less
- sitemap.json
- project.config.json 配置文件样板,这个文件不会被编译到dist中
安装gulp
本文写作时,gulp的版本是v4
,api与之前的版本有一些变化。
创建一个空目录后,先安装依赖:
1 2
| $ npm init $ npm i -D gulp gulp-plumber gulp-rename del
|
在根目录新建gulpfile.js
文件,引入依赖:
1 2 3 4
| const gulp = require('gulp'); const plumber = require('gulp-plumber'); const rename = require('gulp-rename'); const del = require('del');
|
支持less
用less等预处理器书写样式,可能会更方便,安装依赖:
1
| $ npm i -D gulp-less gulp-cssnano
|
假设我们的源码放在/src/miniprogram
目录下,输出到/dist
目录下。
现在让gulp支持less编译:
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
| const less = require('gulp-less'); const cssnano = require('gulp-cssnano');
gulp.task('build:style', () => { return gulp.src([ 'src/miniprogram/pages/**/*.less', 'src/miniprogram/components/**/*.less', 'src/miniprogram/spreadpack/**/*.less', 'src/miniprogram/app.less' ], {base: 'src/miniprogram'}) .pipe(plumber()) .pipe(less()) .pipe( cssnano({ zindex: false, autoprefixer: false, discardComments: { removeAll: true } }) ) .pipe( rename(path => { path.extname = '.wxss'; }) ) .pipe(gulp.dest('dist')); });
|
处理脚本、模板和配置文件
本文只做简单的思路介绍,所以我们还是按照原来的方法编写小程序的js和模板。
这里只是把js,wxml和json复制到输出目录:
1 2 3 4 5 6 7 8 9 10
| gulp.task('build:main', gulp.series('build:style', () => { return gulp.src([ 'src/miniprogram/**/*', '!src/miniprogram/**/*.less', '!src/project.config.json', ], {base: 'src/miniprogram', allowEmpty: true}) .pipe(plumber()) .pipe(gulp.dest('dist')); }));
|
清理输出目录
在发布前,我们需要删除掉多余的文件,这里新增一个工作流用来清理输出目录:
1 2 3 4 5 6
| gulp.task('clean', cb => { return del([ 'dist/**/*', '!dist/project.config.json' ], cb); });
|
配置开发环境启动命令和构建命令
最后我们补全功能,首先增加一个开发环境启动配置:
1 2 3 4 5 6 7 8 9 10 11
| gulp.task('build', gulp.series('build:main'));
function watch() { let watcher = gulp.watch('src/**', cb => cb()); watcher.on('all', (event, path, stats) => { console.log('File ' + path + ' was ' + event + ', running tasks...'); }); return watcher; }
gulp.task('default', gulp.series(watch));
|
在package.json
中增加脚本:
1 2 3 4 5 6 7
| "scripts": { "start": "npm run clean && npm run build", "dev": "gulp", "build": "gulp build", "watch": "gulp watch", "clean": "gulp clean", }
|
现在执行npm start
或者npm run dev
,用小程序开发工具打开dist目录,就能看到效果了。
注入环境变量
有了gulp,一切关于构建的问题都简单了。使用gulp-preprocess
来支持环境变量。
gulp-preprocess的用法见官方文档。
安装依赖:
1
| $ npm i -D cross-env gulp-preprocess
|
修改构建配置
由于操作系统之间设置环境变量命令的差异,引入cross-env
来解决,先修改package.json
:
1 2 3 4 5 6 7
| "scripts": { "start": "cross-env NODE_ENV=prod npm run clean && npm run build", "dev": "cross-env NODE_ENV=dev gulp", "build": "cross-env NODE_ENV=prod gulp build", "watch": "cross-env NODE_ENV=dev gulp watch", "clean": "gulp clean", }
|
这里增加了一个名为NODE_ENV
的环境变量,并设置了dev
和prod
两个值,这样开发时会取dev变量,打包发布时会取prod变量。
然后增加gulp配置:
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
| const preprocess = require('gulp-preprocess');
gulp.task('build:main', gulp.series('build:style', () => { return gulp.src([ 'src/miniprogram/**/*', '!src/miniprogram/assets/**/*', '!src/miniprogram/**/*.less', '!src/project.config.json', ], {base: 'src/miniprogram', allowEmpty: true}) .pipe(plumber()) .pipe(preprocess()) .pipe(gulp.dest('dist')); }));
gulp.task('build:assets', () => { return gulp.src([ "src/miniprogram/assets/**/*" ], { base: 'src/miniprogram', allowEmpty: true }) .pipe(plumber()) .pipe(gulp.dest('dist')); });
gulp.task('build', gulp.parallel('build:main', 'build:assets')); function watch() { let watcher = gulp.watch('src/**', gulp.parallel('build:main', 'build:assets'), cb => cb()); watcher.on('all', (event, path, stats) => { console.log('File ' + path + ' was ' + event + ', running tasks...'); }); return watcher; }
|
代码示例
用这种方法注入环境变量:
1 2 3 4 5 6 7 8 9 10
| let env = '/* @echo NODE_ENV */'; let apiRoot = ''; switch (env) { case 'dev': apiRoot = 'http://dev-api.tianzhen.tech'; break; case 'prod': apiRoot = 'http://api.tianzhen.tech'; break; }
|
写一个demo,运行npm start
试试吧!