频道栏目
首页 > 微信学院 > 微信小程序 > 正文
手把手教你在小程序项目中配置Gulp
2019-12-07 10:54:00           
收藏   我要投稿

如果是做原生小程序开发,你是否想过在你的小程序项目中也加入一些工程的东西?本文将手把手教你在小程序中配置一些工程化的东西,基于我自身的痛点,目前有支持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 here
  cb();
}

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(/kf/201902/&);
}
.usermotto {
    margin-top: 200px;
    color: @txt-highlight;
}

// 编译后
.bg {
  background-image: url(/kf/201902/&);
}
.usermotto {
  margin-top: 200px;
  color: #FD7622;
}

.wxml






// 编译后


图片自动压缩,上传七牛

由于小程序对代码包有限制,每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: '//*****.com', // 七牛空间域名
        prefix: {
            default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略
            remove: 'test/', // 七牛空间删除前缀
            prefetch: 'test/', // 七牛空间预取前缀
            refresh: 'test/', // 七牛空间刷新前缀
        },
    },
};

const urlPrefix = {
    prefix: '//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()流,这个是把我们项目中引用的图片替换成上传七:蟮牡刂,需要配合七牛对应配置来设定。

如:

// 替换前
// 替换后

打包加入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: '//*****.com', // 七牛空间域名
        prefix: {
            default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略
            remove: 'test/', // 七牛空间删除前缀
            prefetch: 'test/', // 七牛空间预取前缀
            refresh: 'test/', // 七牛空间刷新前缀
        },
    },
};

const urlPrefix = {
    prefix: '//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: '//*****.com', // 七牛空间域名
        prefix: {
            default: 'test/', // 七牛空间默认前缀,如果下面三个相同可省略
            remove: 'test/', // 七牛空间删除前缀
            prefetch: 'test/', // 七牛空间预取前缀
            refresh: 'test/', // 七牛空间刷新前缀
        },
    },
};

const urlPrefix = {
    prefix: '//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));

整个项目我放在githubgulp-wechat-weapp

点击复制链接 与好友分享!回本站首页
相关TAG标签
上一篇:小程序的诞生
下一篇:认识小程序云开发
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 全峰安全联盟--致力于做实用的IT技术学习网站