如果是做原生小程序开发,你是否想过在你的小程序项目中也加入一些工程的东西?本文将手把手教你在小程序中配置一些工程化的东西,基于我自身的痛点,目前有 支持Less、支持路径别名、图片自动压缩,上传七牛、打包加入Eslint检查这么几个功能,后期有遇到其他需要再更新。
在小程序项目中我目前用的是Gulp。为啥不用热门的webpack?因为我觉得对于小程序项目来说gulp足够了,关键是配置非常简单,流式管理简单明了,不了解Gulp的大家可以去官网看看。
需要提醒的是,以下举例的gulpfie基于gulp 4.0,配置上与之前的版本略有不同,不过变化不大。详细的大家可以点这里去看看。

项目结构
gulpfile.js 我们放在根目录下,初始长这样
const { src, dest, parallel, watch, series } = require('gulp');function defaultTask(cb) {// place code for your default task herecb();}exports.default = defaultTask
接下来我们将一个任务一个任务往里面添加。
支持Less
由于平时项目中习惯了用CSS 预处理语言,wxss的原始css 写法让我写起项目来很难受。我个人比较习惯使用Less,习惯使用sass的大家自己找一下相关插件替换一下就行。gulp中处理less的插件是gulp-less,gulp-less把文件处理完成后我们还需要把文件名改成.wxss所以我们还需要一个重命名插件,这里用的是gulp-rename。
gulpfile.js如下:
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const path = {lessPath: ['src/**/*.less'],};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Less()).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}exports.default = series(wxss);
需要注意的是上面的 src() 在第二个参数传入了 {base: 'src/'},至于原因嘛,跟我们配的匹配less文件路径 src/**/*.less有关。感兴趣的同学可以结合 Explaining Globs看看,这里我不细说。
当然如果你想对wxss进行压缩可以使用gulp-csso 。
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const Csso = require('gulp-csso');const GulpIf = require('gulp-if');const path = {lessPath: ['src/**/*.less'],};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Less()).pipe(GulpIf(process.env.NODE_ENV === 'production', Csso())).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}exports.default = series(wxss);
支持路径别名
在项目中,如果应用文件路径过深过长,不仅开发者写起来费劲,还容易出错且代码观赏性很差。小程序中路径别名我们用gulp-wechat-weapp-src-alisa,支持在 .wxml、.wxss/less、.js 中使用。
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const Csso = require('gulp-csso');const GulpIf = require('gulp-if');const Alias = require('gulp-wechat-weapp-src-alisa');// 匹配文件路径const path = {lessPath: ['src/**/*.less'],jsPath: ['src/**/*.js'],copy: ['src/**/*.wxml', 'src/**/*.json', 'src/**/*.wxs'],};// 路径拼接function _join(dirname) {return Path.join(process.cwd(), 'src', dirname);}// 引用路径别名配置const aliasConfig = {'@Libs': _join('libs'),'@Utils': _join('utils'),'@Components': _join('components'),'@Style': _join('style'),'@Images': _join('images'),};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Alias(aliasConfig)).pipe(Less()).pipe(GulpIf(process.env.NODE_ENV === 'production', Csso())).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}function js() {return src(path.jsPath).pipe(Alias(aliasConfig)).pipe(dest('dist'));}// 针对wxs,wxml,json文件直接复制function copy() {return src(path.copy).pipe(Alias(aliasConfig)).pipe(dest('dist'));}exports.default = series(wxss, js);
使用效果
.js
import * as Utils from '@Utils/base';// require('@Libs/WXPage/index');// 编译后import * as Utils from '../../utils/base';// require('libs/WXPage/index');
.less
// index.less@import '@Style/variables.less';.bg {background-image: url('@Images/32821027.jpgg');}.usermotto {margin-top: 200px;color: @txt-highlight;}// 编译后.bg {background-image: url('../../images/32821027.jpg');}.usermotto {margin-top: 200px;color: #FD7622;}
.wxml
<!--logs.wxml--><import src="@Utils/index.wxs" /><image src="@Images/32821027.jpg" mode="cover"></image>// 编译后<import src="../../utils/index.wxs" /><image src="../../images/32821027.jpg" mode="cover"></image>
图片自动压缩,上传七牛
由于小程序对代码包有限制,每1KB空间对小程序项目都十分珍贵,而且从用户体验来说,过大的代码包对首次进入小程序的用户来说下载时间会过长。基于这些原因我们几乎不会选择把图片放在小程序代码包中,那就只能上传图片服务器了。
上传图片之前需要对图片进行压缩,可能有些通许是通过手动来做这部分工作的,其实可以用工具来的嘛。压缩图片用的插件是gulp-imagemin, 我的图片是上传到七牛,对应的插件是gulp-qiniu-utils。
接下来我们在gulpfile中添加图片相关任务
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const Csso = require('gulp-csso');const GulpIf = require('gulp-if');const Alias = require('gulp-wechat-weapp-src-alisa');const ImageMin = require('gulp-imagemin');const UrlPrefixer = require('gulp-url-prefixer');const Qiniu = require('gulp-qiniu-utils');// 匹配文件路径const path = {lessPath: ['src/**/*.less'],jsPath: ['src/**/*.js'],copy: ['src/**/*.wxml', 'src/**/*.json', 'src/**/*.wxs'],};// 七牛相关配置const qiniuOptions = {ak: 'ac key',sk: 'sk key',zone: 'Zone_z0', // 空间对应存储区域(华东:z0,华北:z1,华南:z2,北美:na0)bucket: 'hynal-com', // 七牛对应空间upload: {dir: './dist/images', // 上传本地目录// prefix: 'test/', // 上传时添加的前缀,可省略except: /\.(html|js)$/, // 上传时不上传文件的正则匹配},remote: {url: 'https://*****.com', // 七牛空间域名prefix: {default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略remove: 'test/', // 七牛空间删除前缀prefetch: 'test/', // 七牛空间预取前缀refresh: 'test/', // 七牛空间刷新前缀},},};const urlPrefix = {prefix: 'https://cdn.liayal.com/dist',tags: ['image'],};// 路径拼接function _join(dirname) {return Path.join(process.cwd(), 'src', dirname);}// 引用路径别名配置const aliasConfig = {'@Libs': _join('libs'),'@Utils': _join('utils'),'@Components': _join('components'),'@Style': _join('style'),'@Images': _join('images'),};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Alias(aliasConfig)).pipe(Less()).pipe(UrlPrefixer.css(urlPrefix)).pipe(GulpIf(process.env.NODE_ENV === 'production', Csso())).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}function js() {return src(path.jsPath).pipe(Alias(aliasConfig)).pipe(dest('dist'));}function imagemin() {return src(path.images).pipe(ImageMin()).pipe(dest('dist/images'));}const images = series(imagemin, (cb) => {const qiniu = new Qiniu(qiniuOptions);qiniu.upload();cb();});// 针对wxs,wxml,json文件直接复制function copy() {return src(path.copy).pipe(Alias(aliasConfig)).pipe(UrlPrefixer.html(urlPrefix)).pipe(dest('dist'));}exports.default = series(wxss, js, images);
上面我们还添加了一个 UrlPrefixer() 流,这个是把我们项目中引用的图片替换成上传七牛后的地址,需要配合七牛对应配置来设定。
如:
// 替换前<image src="@Images/32821027.jpg" mode="cover"></image>// 替换后<image src="https://cdn.liayal.com/dist/images/32821027.jpg" mode="cover"></image>
打包加入Eslint检查
打包时加入Eslint检查可以让我们提早发现一些由代码引发问题,也方便推行代码规范。
下面我们在js任务中加入gulp-eslint
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const Csso = require('gulp-csso');const GulpIf = require('gulp-if');const Alias = require('gulp-wechat-weapp-src-alisa');const ImageMin = require('gulp-imagemin');const UrlPrefixer = require('gulp-url-prefixer');const Qiniu = require('gulp-qiniu-utils');const ESLint = require('gulp-eslint');// 匹配文件路径const path = {lessPath: ['src/**/*.less'],jsPath: ['src/**/*.js'],copy: ['src/**/*.wxml', 'src/**/*.json', 'src/**/*.wxs'],};// 七牛相关配置const qiniuOptions = {ak: 'ac key',sk: 'sk key',zone: 'Zone_z0', // 空间对应存储区域(华东:z0,华北:z1,华南:z2,北美:na0)bucket: 'hynal-com', // 七牛对应空间upload: {dir: './dist/images', // 上传本地目录// prefix: 'test/', // 上传时添加的前缀,可省略except: /\.(html|js)$/, // 上传时不上传文件的正则匹配},remote: {url: 'https://*****.com', // 七牛空间域名prefix: {default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略remove: 'test/', // 七牛空间删除前缀prefetch: 'test/', // 七牛空间预取前缀refresh: 'test/', // 七牛空间刷新前缀},},};const urlPrefix = {prefix: 'https://cdn.liayal.com/dist',tags: ['image'],};// 路径拼接function _join(dirname) {return Path.join(process.cwd(), 'src', dirname);}// 引用路径别名配置const aliasConfig = {'@Libs': _join('libs'),'@Utils': _join('utils'),'@Components': _join('components'),'@Style': _join('style'),'@Images': _join('images'),};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Alias(aliasConfig)).pipe(Less()).pipe(UrlPrefixer.css(urlPrefix)).pipe(GulpIf(process.env.NODE_ENV === 'production', Csso())).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}function js() {return src(path.jsPath).pipe(Alias(aliasConfig)).pipe(ESLint()).pipe(ESLint.format()).pipe(dest('dist'));}function imagemin() {return src(path.images).pipe(ImageMin()).pipe(dest('dist/images'));}const images = series(imagemin, (cb) => {const qiniu = new Qiniu(qiniuOptions);qiniu.upload();cb();});// 针对wxs,wxml,json文件直接复制function copy() {return src(path.copy).pipe(Alias(aliasConfig)).pipe(UrlPrefixer.html(urlPrefix)).pipe(dest('dist'));}exports.default = series(wxss, js, images);
效果大概是这样的

也可以通过eslint.failOnError()或者eslint.failAfterError()在编译报错时中断编译。
END
最后完善一下gulpfile, 添加监测任务,添加一个clean任务
const { src, dest, parallel, watch, series } = require('gulp');const Path = require('path');const Less = require('gulp-less');const Rename = require('gulp-rename');const Csso = require('gulp-csso');const GulpIf = require('gulp-if');const Alias = require('gulp-wechat-weapp-src-alisa');const ImageMin = require('gulp-imagemin');const UrlPrefixer = require('gulp-url-prefixer');const Qiniu = require('gulp-qiniu-utils');const ESLint = require('gulp-eslint');const Clean = require('gulp-clean');// 匹配文件路径const path = {lessPath: ['src/**/*.less'],jsPath: ['src/**/*.js'],copy: ['src/**/*.wxml', 'src/**/*.json', 'src/**/*.wxs'],};// 七牛相关配置const qiniuOptions = {ak: 'ac key',sk: 'sk key',zone: 'Zone_z0', // 空间对应存储区域(华东:z0,华北:z1,华南:z2,北美:na0)bucket: 'hynal-com', // 七牛对应空间upload: {dir: './dist/images', // 上传本地目录// prefix: 'test/', // 上传时添加的前缀,可省略except: /\.(html|js)$/, // 上传时不上传文件的正则匹配},remote: {url: 'https://*****.com', // 七牛空间域名prefix: {default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略remove: 'test/', // 七牛空间删除前缀prefetch: 'test/', // 七牛空间预取前缀refresh: 'test/', // 七牛空间刷新前缀},},};const urlPrefix = {prefix: 'https://cdn.liayal.com/dist',tags: ['image'],};// 路径拼接function _join(dirname) {return Path.join(process.cwd(), 'src', dirname);}// 引用路径别名配置const aliasConfig = {'@Libs': _join('libs'),'@Utils': _join('utils'),'@Components': _join('components'),'@Style': _join('style'),'@Images': _join('images'),};function wxss() {return src(path.lessPath, { base: 'src/' }).pipe(Alias(aliasConfig)).pipe(Less()).pipe(UrlPrefixer.css(urlPrefix)).pipe(GulpIf(process.env.NODE_ENV === 'production', Csso())).pipe(Rename({extname: '.wxss',})).pipe(dest('dist'));}function js() {return src(path.jsPath).pipe(Alias(aliasConfig)).pipe(ESLint()).pipe(ESLint.format()).pipe(dest('dist'));}function imagemin() {return src(path.images).pipe(ImageMin()).pipe(dest('dist/images'));}const images = series(imagemin, (cb) => {const qiniu = new Qiniu(qiniuOptions);qiniu.upload();cb();});// 针对wxs,wxml,json文件直接复制function copy() {return src(path.copy).pipe(Alias(aliasConfig)).pipe(UrlPrefixer.html(urlPrefix)).pipe(dest('dist'));}function clean() {return src('dist/*', { read: false }).pipe(Clean());}watch(path.lessPath, wxss);watch(path.jsPath, js);watch(path.copy, copy);watch(path.images, images);exports.default = series(clean, parallel(copy, wxss, js, images));
整个项目我放在github
gulp-wechat-weapp
写于 2019年02月19日小程序 Gulp 6164
如非特别注明,文章皆为原创。
转载请注明出处: https://www.liayal.com/article/5c6b76a6c0ab13505eeefaaf
记小栈小程序上线啦~搜索【记小栈】或【点击扫码】体验


~ 评论还没有,沙发可以有 O(∩_∩)O~