background
The company has several small program projects, using the native way of development. The native approach has its advantages, such as not having to step on the frame pit, but it also has obvious drawbacks, such as not being able to use the efficiency gains that the frame provides. Based on this, we simply use Gulp to configure a set of workflows that will save us some repetitive operations during development.
Why use Gulp and not WebPack? After experimenting with both tools, it was easier to use Gulp for our problem…
This article will not do much about gulP, but focus on the implementation.
Feature list
- The CSS can be written using less
- The CSS is automatically completed
- Js syntax Support
- CSS and JS code compression
- The image is automatically uploaded to the CDN. When the image changes are monitored, the CDN is automatically uploaded
- Support for static resource directories, such as DI tripartite JS, images that need to be placed locally
- Applets native NPM function, through the command automatically build applets applicable NPM package
- The unit is converted by default, that is, PX is automatically converted to RPX, and supports adaptation of different screens
- Support for Source Map to locate where the code went wrong after it was built
- Create page and Component by command, automatically generating four files
- Support environment variables to automatically generate code for different environments through commands
- Introduce miniprogram-CI by uploading code to wechat background
The directory structure
First look at the configuration of the directory structure, which SRC directory content is the micro channel small program code, external are some configuration files.
Command definition
Here are the commands defined in package.json, and we’ll implement each of these features one by one.
"scripts": {
"start": "rm -rf ./dist && cross-env NODE_ENV=development gulp"."preview": "gulp preview"."build-pro": "rm -rf ./dist && cross-env NODE_ENV=production gulp build"."build-dev": "rm -rf ./dist && cross-env NODE_ENV=development gulp build"."build-npm": "gulp npm"."deploy-dev": "npm run build-dev && gulp upload"."deploy-pro": "npm run build-pro && gulp upload"."cp": "create-wxapp-page --type=page --dir=src --indent=2 --style=less"."cc": "create-wxapp-page --type=component --dir=src --indent=2 --style=less"
},
Copy the code
gulpfile
The gulpfile file contains all the configuration code. Each task is explained in detail later.
const path = require('path');
const fileExists = require('file-exists');
const gulp = require('gulp');
const less = require('gulp-less');
const uglify = require('gulp-uglify');
const cleanCSS = require('gulp-clean-css');
const rename = require('gulp-rename');
const del = require('del');
const qcloud = require('qcloud-upload');
const gulpif = require('gulp-if');
const gutil = require('gulp-util');
const replace = require('gulp-replace');
const px2rpx = require('gulp-px2rpx');
const ci = require('miniprogram-ci');
const sourcemaps = require('gulp-sourcemaps');
const alias = require('gulp-path-alias');
const pkg = require('./package.json')
const projectConfig = require('./project.config.json')
const buildPath = path.join(__dirname, 'dist/')
const uploadFolder = path.join(__dirname, './src/images')
const isPro = process.env.NODE_ENV === 'production'
const config = {
// Tencent CDN paint bucket configuration
assetsCDN: 'https://xxx.cos.ap-guangzhou.myqcloud.com/'.cos: {
Bucket: 'xxx'.Region: 'xxx'.SecretId: 'xxx'.SecretKey: 'xxx'.prefix: `${pkg.name}/images`.// Which folder to upload to the paint bucket
src: uploadFolder, // Which folder to upload to the paint bucket
overWrite: 1,},enablePx2Rpx: true.enableCleanCSS: false.enableAuto: true.// Autocomplete the CSS
enableUglify: false.enableSourcemap: true};const paths = {
styles: {
src: ['src/**/*.less'].dest: buildPath
},
images: {
src: 'src/images/**/*.{png,jpg,jpeg,svg,gif}'.dest: buildPath
},
scripts: {
src: 'src/**/*.js'.dest: buildPath
},
copy: {
src: ['src/**'.'! src/**/*.less'.'! src/images/**'.'! src/**/*.js'.'package.json'].dest: buildPath
},
}
// Delete the build
function clean() {
return del([buildPath])
}
function log() {
const data = Array.prototype.slice.call(arguments)
gutil.log.apply(false, data)
}
function upload() {
return new Promise(function (resolve, reject) {
// QCloud does not end with the resolve() function
qcloud(config.cos)
resolve()
})
}
// The task handler function
function styles() {
return gulp
.src(paths.styles.src, { base: 'src' })
.pipe(alias({
paths: {
The '@': path.resolve(__dirname, './src/'),
}
}))
.pipe(less())
.pipe(replace('%CDN_IMG%/', config.assetsCDN + config.cos.prefix + '/'))
.pipe(gulpif(config.enableCleanCSS, cleanCSS()))
.pipe(gulpif(config.enablePx2Rpx, px2rpx({
screenWidth: 375.// Design screen, default 750
wxappScreenWidth: 750.// Wechat mini program screen, default 750
remPrecision: 6
})))
.pipe(replace('PX'.'px'))
.pipe(rename(path= > (path.extname = '.wxss')))
.pipe(gulp.dest(paths.styles.dest))
}
function scripts() {
return gulp
.src(paths.scripts.src, { base: 'src' })
.pipe(alias({
paths: {
The '@': path.resolve(__dirname, './src/'), / / SRC directory
}
}))
.pipe(gulpif(config.enableSourcemap, sourcemaps.init()))
.pipe(gulpif(isPro, replace('%ENV%'.'production'), replace('%ENV%'.'development'))) // Static substitution of environment variables
.pipe(replace('%CDN_IMG%/', config.assetsCDN + config.cos.prefix + '/'))
.pipe(replace('%VERSION%', pkg.version))
.pipe(gulpif(config.enableUglify, uglify()))
.pipe(gulpif(config.enableSourcemap, sourcemaps.write('. ')))
.pipe(gulp.dest(paths.scripts.dest))
}
// Copy files that do not need to be processed
function copy() {
return gulp
.src(paths.copy.src)
.pipe(replace('%CDN_IMG%/', config.assetsCDN + config.cos.prefix + '/'))
.pipe(gulp.dest(paths.copy.dest))
}
function watchFiles() {
const w1 = gulp.watch(paths.styles.src, styles).on('unlink'.function (file) {
log(gutil.colors.yellow(file) + ' is deleted')
const filePath = file.replace(/src\\/.'dist\\')
del([filePath])
});
const w2 = gulp.watch(paths.scripts.src, scripts).on('unlink'.function (file) {
log(gutil.colors.yellow(file) + ' is deleted')
const filePath = file.replace(/src\\/.'dist\\')
del([filePath])
});
const w3 = gulp.watch(paths.copy.src, copy).on('unlink'.function (file) {
log(gutil.colors.yellow(file) + ' is deleted')
const filePath = file.replace(/src\\/.'dist\\')
del([filePath])
});
const w4 = gulp.watch(paths.images.src, upload).on('unlink'.function (file) {
log(gutil.colors.yellow(file) + ' is deleted')
const filePath = file.replace(/src\\/.'tmp\\')
del([filePath])
});
return Promise.all([w1, w2, w3, w4])
}
/** * small program ci related function */
let project = {}
const keyFile = fileExists.sync(`./private.${projectConfig.appid}.key`)
if (keyFile) {
project = new ci.Project({
appid: projectConfig.appid,
type: 'miniProgram'.projectPath: './dist'.privateKeyPath: `./private.${projectConfig.appid}.key`.ignores: [],})}async function npmBuild() {
await ci.packNpmManually({
packageJsonPath: './package.json'.miniprogramNpmDistDir: './src/'})},async function mpUpload() {
const uploadResult = await ci.upload({
project,
version: pkg.version,
desc: pkg.description,
setting: {
es6: true.minify: true.autoPrefixWXSS: true,},onProgressUpdate: console.log,
})
console.log('[uploadResult:]', uploadResult)
}
async function preview() {
const previewResult = await ci.preview({
project,
desc: pkg.description, // This remark will be displayed in the "Applet Assistant" development version list
qrcodeFormat: 'image'.qrcodeOutputDest: './preview.jpg'.onProgressUpdate: console.log,
})
console.log('[previewResult:]', previewResult)
}
exports.watch = watchFiles
exports.preview = preview
// Ci builds NPM automatically
exports.npm = npmBuild
exports.upload = mpUpload
exports.default = gulp.series(styles, scripts, copy, upload, watchFiles)
exports.build = gulp.series(clean, styles, scripts, copy, upload)
Copy the code
Automatically create components and pages
Creating components and pages automatically uses an NPM package called CREation-wxapp-page, which allows you to create a set of files directly from the command line.
NPM run CC # then enter the component name NPM run CP # then enter the page nameCopy the code
Automatically build NPM
Small programs support NPM, but you need to manually click compile after the developer tool is started to generate the corresponding NPM package. Fortunately, wechat provides the miniProgram-CI package, which can eliminate the manual process.
const ci = require('miniprogram-ci');
async function npmBuild() {
await ci.packNpmManually({
packageJsonPath: './package.json'.miniprogramNpmDistDir: './src/'})},exports.npm = npmBuild
Copy the code
By running NPM run build-npm, our installed package will be built into SRC’s miniprogram_npm directory.
Environment variable support
Environment variables can help us distinguish the code to be executed in different environments, such as API addresses. The implementation is static substitution.
pipe(gulpif(isPro, replace('%ENV%'.'production'), replace('%ENV%'.'development'))
Copy the code
const isPro = '%ENV%'= = ='production'
if (isPro) {
// Production environment
} else {
// Test, experience the environment
}
Copy the code
Upload the image to the CDN
When an image change is detected in the images folder, the upload operation is performed.
function upload() {
return new Promise(function (resolve, reject) {
// QCloud does not end with the resolve() function. Qcloud does not provide a callback for a successful upload
qcloud(config.cos)
resolve()
})
}
Copy the code
Use CND pictures
<image src="%CDN_IMG%/index/empty" mode="aspectFit" class="empty__img" />
Copy the code
sourcemap
Sourcemap is also simple. It is also a package, gulp-sourcemap
.pipe(gulpif(config.enableSourcemap, sourcemaps.init())
Copy the code
Static directory
Special static resources, such as icon images of tabbar, can be placed in SRC /static, and the files from this directory will be copied to dist.
Js syntax Support
It is recommended to use the “ES6 to ES5” and “enhanced compilation” provided by the small program tool for the new JS syntax. In practice, it is found that using Glup-babel will lead to the slow compilation of JS. The tools are more than enough.
Use CI to upload the code
Miniprogram-ci provides a backend for uploading code to small program management. The first step is to download the key, then name the file private.{appId}.key, and finally place it in the project root directory. For security reasons, it would be better to put CI capabilities on the server side, and here on the front end.
NPM run deploy-dev is executed to upload the code to the experience version, which is selected as the CI robot.
Project. Config. Json changes
{
"description": "Project Profile"."miniprogramRoot": "dist/"."packOptions": {
"ignore": [{"type": "folder"."value": "images"}}}]Copy the code
The dist directory is the small program code that was built, so specify miniprogramRoot as “dist/”.
Since the images are uploaded to the CDN, there is no need to pack the SRC /images folder into the applet, which also reduces the size.
conclusion
In fact, the code of glupfile file is relatively simple, so it feels a little redundant to explain too much. The above configuration runs smoothly on our company’s online small program, and the transformation cost is also very low. If you want to use your own small program, any problems are welcome to leave a message.
Above, thanks for reading!