gulp构建小程序的方法步骤


Posted in Javascript onMay 31, 2019

目前来说,对于构建小程序的,类似taro这些框架,生态已经挺完善的了,没有什么必要再搞一套来折腾自己。但是,我司的小程序,是很早之前就开发的,我们负责人当时信不过这些开源的框架,于是自己用webpack搞了一套框架,但有一个比较严重的问题,有一些文件依赖重复打包了,导致小程序包体积比较大。

持续了一个多月,主包体积在2M左右徘徊,开发都很难做下去。我们负责人终于受不了了,给了我个任务,让我写一个构建小程序的工具,减少小程序包体积。

我们现在的框架对比一下原生小程序,其实差别不大,无非就是

ts => js
sass=>wxss
wxml=>wxml
json=>json

由于我司小程序基础库是1.9.8的,不支持构建npm,所以node_modules的依赖包以及依赖路径需要自己处理,于是写了一个babel插件 babel-plugin-copy-npm。
这么一想,其实不难,而且单文件编译,那不是gulp的强项吗!!!

最终效果:

gulp构建小程序的方法步骤

gulp构建小程序的方法步骤

gulp构建小程序的方法步骤

而且由于增量更新,只修改改变的文件,所以编译的速度非常快。

项目地址:https://github.com/m-Ryan/ry-wx

最终流程大概如下:清除dist目录下的文件 => 编译文件到dist目录下=> 开发模式监听文件更改,生产环境压缩文件。

一、清除dist目录下的文件 (clean.js)

const del = require('del');
const fs = require('fs');
const path = require('path');
const cwd = process.cwd();
module.exports = function clean() {
  if (!fs.existsSync(path.join(cwd, 'dist'))) {
    fs.mkdirSync('dist');
    return Promise.resolve(null);
  }
  return del([ '*', '!npm' ], {
    force: true,
    cwd: path.join(cwd, 'dist')
  });
};

二、编译文件

1.编译typescript(compileJs.js)

const gulp = require('gulp');
const { babel } = require('gulp-load-plugins')();
const path = require('path');
const cwd = process.cwd();
module.exports = function compileJs(filePath) {
  let file = 'src/**/*.ts';
  let dist = 'dist';
  if (typeof filePath === 'string') {
    file = path.join(cwd, filePath);
    dist = path.dirname(file.replace(/src/, 'dist'));
  }
  return gulp.src(file).pipe(babel()).pipe(gulp.dest(dist));
};

2.编译sass(compileSass.js)

const gulp = require('gulp');
const { sass, postcss, rename } = require('gulp-load-plugins')();
const path = require('path');
const cwd = process.cwd();
const plugins = [
  require('autoprefixer')({
    browsers: [ 'ios >= 8', 'ChromeAndroid >= 53' ],
    remove: false,
    add: true
  }),
  require('postcss-pxtorpx')({
    multiplier: 2,
    propList: [ '*' ]
  })
];

module.exports = function compileSass(filePath) {
  let file = 'src/**/*.scss';
  let dist = 'dist';
  if (typeof filePath === 'string') {
    file = path.join(cwd, filePath);
    dist = path.dirname(file.replace(/src/, 'dist'));
  }
  return gulp
    .src(file)
    .pipe(sass({ outputStyle: 'compressed' }).on('error', sass.logError))
    .pipe(postcss(plugins))
    .pipe(
      rename({
        extname: '.wxss'
      })
    )
    .pipe(gulp.dest(dist));
};

编译json,wxml,由于需要压缩,所以需要分开处理

(copyJson.js)

const gulp = require('gulp');

module.exports = function copyJson() {
  let file = 'src/**/*.json';
  let dist = 'dist';
  if (typeof filePath === 'string') {
    file = path.join(cwd, filePath);
    dist = path.dirname(file.replace(/src/, 'dist'));
  }
  return gulp.src([ file ]).pipe(gulp.dest(dist));
};

(copyWxml.js)

const gulp = require('gulp');

const minifyHtml = require('gulp-html-minify');
module.exports = function copyWxmlFiles() {
  let file = 'src/**/*.wxml';
  let dist = 'dist';
  if (typeof filePath === 'string') {
    file = path.join(cwd, filePath);
    dist = path.dirname(file.replace(/src/, 'dist'));
  }
  return gulp.src(file).pipe(minifyHtml()).pipe(gulp.dest(dist));
};

4.拷贝其他静态资源,例如字体、图片

(copyAssets.js)

const gulp = require("gulp");

module.exports = function copyAssets() {
 let file = "src/**/**";
 let dist = "dist";
 if (typeof filePath === "string") {
  file = path.join(cwd, filePath);
  dist = path.dirname(file.replace(/src/, "dist"));
 }
 return gulp
  .src([
   file,
   "!**/*.json",
   "!**/*.ts",
   "!**/*.js",
   "!**/*.scss",
   "!**/*.wxml"
  ])
  .pipe(gulp.dest(dist));
};

5.引入文件(gulpfile.js)

const gulp = require("gulp");
const clean = require("./build/clean");
const compileJs = require("./build/compileJs");
const compileSass = require("./build/compileSass");
const copyJson = require("./build/copyJson");
const copyWxml = require("./build/copyWxml");
const copyAssets = require("./build/copyAssets");
const fs = require("fs-extra");
const path = require("path");
const chalk = require("chalk");
const cwd = process.cwd();
const dayjs = require("dayjs");

const tasks = [
 clean,
 gulp.parallel([compileJs, compileSass, copyJson, copyWxml]),
 copyAssets
];
if (process.env.NODE_ENV === "development") {
 tasks.push(watch);
}

gulp.task("default", gulp.series(tasks));

gulp.task("watch", watch);
function watch() {
 console.log(chalk.blue(`正在监听文件... ${getNow()}`));
 const watcher = gulp.watch("src/**/**");

 watcher.on("change", function(filePath, stats) {
  compile(filePath);
 });

 watcher.on("add", function(filePath, stats) {
  compile(filePath);
 });

 watcher.on("unlink", function(filePath, stats) {
  let distFile = filePath.replace(/^src\b/, "dist");
  let absolutePath = "";
  if (distFile.endsWith(".ts")) {
   distFile = distFile.replace(/.ts$/, ".js");
  } else if (distFile.endsWith(".scss")) {
   distFile = distFile.replace(/.scss$/, ".wxss");
  }
  absolutePath = path.join(cwd, distFile);
  if (fs.existsSync(absolutePath)) {
   fs.unlinkSync(absolutePath);
   console.log(
    chalk.yellow(`删除文件:${path.basename(distFile)} ${getNow()}`)
   );
  }
 });
}

function compile(filePath) {
 console.info(
  chalk.green(`编译完成:${path.basename(filePath)} ${getNow()}`)
 );
 if (filePath.endsWith(".ts")) {
  compileJs(filePath);
 } else if (filePath.endsWith(".scss")) {
  compileSass(filePath);
 } else if (filePath.endsWith(".wxml")) {
  copyWxml(filePath);
 } else if (filePath.endsWith(".json")) {
  copyJson(filePath);
 } else {
  copyAssets(filePath);
 }
}

function getNow() {
 return dayjs().format("HH:mm:ss");
}

babel的配置如下.babelrc.js

const babelOptions = {
  presets: [ '@babel/preset-typescript', [ '@babel/env' ] ],
  plugins: [
    'lodash',
    [
      '@babel/plugin-proposal-decorators',
      {
        legacy: true
      }
    ],
    'babel-plugin-add-module-exports',
    [
      '@babel/plugin-transform-runtime',
      {
        corejs: false,
        helpers: true,
        regenerator: true,
        useESModules: false
      }
    ],

    [
      'module-resolver',
      {
        root: [ '.' ],
        alias: {
          '@': './src'
        }
      }
    ],
    [
      'babel-plugin-copy-npm',
      {
        rootDir: 'src',
        outputDir: 'dist',
        npmDir: 'npm',
        format: 'cjs',
        strict: false,
        minify: true,
        loose: true,
        cache: true
      }
    ]
  ]
};

if (process.env.NODE_ENV === 'production') {
  babelOptions.presets.unshift([
    'minify',
    {
      mangle: {
        exclude: [ 'wx', 'module', 'exports', '__wxConfigx', 'process', 'global' ]
      },
      keepFnName: true
    }
  ]);
}

module.exports = babelOptions;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript基础语法让人疑惑的地方小结
May 23 Javascript
Jquery chosen动态设置值实例介绍
Aug 08 Javascript
js实现幻灯片播放图片示例代码
Nov 07 Javascript
css3元素简单的闪烁效果实现(html5 jquery)
Dec 28 Javascript
javascript页面加载完执行事件代码
Feb 11 Javascript
JavaScript使用指针操作实现约瑟夫问题实例
Apr 07 Javascript
基于 webpack2 实现的多入口项目脚手架详解
Jun 26 Javascript
vue单页开发父子组件传值思路详解
May 18 Javascript
JavaScript创建对象的常用方式总结
Aug 10 Javascript
Vue 使用计时器实现跑马灯效果的实例代码
Jul 11 Javascript
koa2的中间件功能及应用示例
Mar 05 Javascript
微信小程序拖拽排序列表的示例代码
Jul 08 Javascript
jQuery实现动态加载(按需加载)javascript文件的方法分析
May 31 #jQuery
自定义javascript验证框架示例【附源码下载】
May 31 #Javascript
vue spa应用中的路由缓存问题与解决方案
May 31 #Javascript
JS实现处理时间,年月日,星期的公共方法示例
May 31 #Javascript
一文了解vue-router之hash模式和history模式
May 31 #Javascript
vue App.vue中的公共组件改变值触发其他组件或.vue页面监听
May 31 #Javascript
微信小程序环境下将文件上传到OSS的方法步骤
May 31 #Javascript
You might like
php生成随机密码的几种方法
2011/01/17 PHP
PHP管理内存函数 memory_get_usage()使用介绍
2012/09/23 PHP
深入分析php中接口与抽象类的区别
2013/06/08 PHP
一个php短网址的生成代码(仿微博短网址)
2014/05/07 PHP
php中curl和file_get_content的区别
2014/05/10 PHP
javascript 去字符串空格终极版(支持utf8)
2009/11/14 Javascript
自定义的一个简单时尚js下拉选择框
2013/11/20 Javascript
用js将内容复制到剪贴板兼容浏览器
2014/03/18 Javascript
jQuery中click事件用法实例
2014/12/26 Javascript
基于nodejs+express(4.x+)实现文件上传功能
2015/11/23 NodeJs
动态设置form表单的action属性的值的简单方法
2016/05/25 Javascript
详解Angular-cli生成组件修改css成less或sass的实例
2017/07/27 Javascript
微信小程序实时聊天WebSocket
2018/07/05 Javascript
Vue源码分析之Vue实例初始化详解
2019/08/25 Javascript
JS中==、===你分清楚了吗
2020/03/04 Javascript
基于javascript原生判断DOM是否加载完毕
2020/10/14 Javascript
[01:21:36]CHAOS vs Alliacne 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
Python批量修改文件后缀的方法
2014/01/26 Python
python使用fileinput模块实现逐行读取文件的方法
2015/04/29 Python
Python实现FTP文件传输的实例
2019/07/07 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
2019/08/20 Python
python中web框架的自定义创建
2019/09/08 Python
Python+Tensorflow+CNN实现车牌识别的示例代码
2019/10/11 Python
移动端解决悬浮层(悬浮header、footer)会遮挡住内容的3种方法
2015/03/27 HTML / CSS
jurlique茱莉蔻英国官网:澳洲天然护肤品
2018/08/03 全球购物
node中使用shell脚本的方法步骤
2021/03/23 Javascript
毕业生求职简历的自我评价
2013/10/23 职场文书
七年级英语教学反思
2014/01/15 职场文书
新学期决心书
2014/03/11 职场文书
党员演讲稿
2014/09/04 职场文书
合作意向书怎么写
2019/06/24 职场文书
800字作文之大雪
2019/12/04 职场文书
python urllib库的使用详解
2021/04/13 Python
新手入门Mysql--sql执行过程
2021/06/20 MySQL
Python自动化测试PO模型封装过程详解
2021/06/22 Python
详解Java实现设计模式之责任链模式
2021/06/23 Java/Android