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 AutoScroller 函数类
May 29 Javascript
Jquery仿淘宝京东多条件筛选可自行结合ajax加载示例
Aug 28 Javascript
jQuery中[attribute!=value]选择器用法实例
Dec 31 Javascript
常用的JavaScript WEB操作方法分享
Feb 28 Javascript
JavaScript知识点整理
Dec 09 Javascript
微信小程序 css使用技巧总结
Jan 09 Javascript
vue2.0父子组件间通信的实现方法
Apr 19 Javascript
详解node服务器中打开html文件的两种方法
Sep 18 Javascript
JavaScript常见JSON操作实例分析
Aug 08 Javascript
详解超简单的react服务器渲染(ssr)入坑指南
Feb 28 Javascript
详解element-ui设置下拉选择切换必填和非必填
Jun 17 Javascript
如何提升vue.js中大型数据的性能
Jun 21 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输出控制功能在简繁体转换中的应用
2006/10/09 PHP
php生成文件
2007/01/15 PHP
php cookie的操作实现代码(登录)
2010/12/29 PHP
关于php正则匹配汉字的方法介绍
2013/04/25 PHP
php生成excel文件的简单方法
2014/02/08 PHP
Yii实现多数据库主从读写分离的方法
2014/12/29 PHP
Paypal实现循环扣款(订阅)功能
2017/03/23 PHP
php使用mysqli和pdo扩展,测试对比mysql数据库的执行效率完整示例
2019/05/09 PHP
IE中createElement需要注意的一个问题
2010/07/13 Javascript
jquery控制listbox中项的移动并排序的实现代码
2010/09/28 Javascript
基于jQuery的烟花效果(运动相关)点击屏幕出烟花
2012/06/14 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
jquery图片切换实例分析
2015/04/15 Javascript
Jquery代码实现图片轮播效果(一)
2015/08/12 Javascript
jQuery formValidator表单验证
2016/01/07 Javascript
基于javascript实现动态时钟效果
2020/08/18 Javascript
js 客户端打印html 并且去掉页眉、页脚的实例
2017/11/03 Javascript
bootstrap table支持高度百分比的实例代码
2018/02/28 Javascript
JavaScript实现选项卡效果的分析及步骤
2019/04/16 Javascript
vue+element实现表单校验功能
2019/05/20 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
谈一谈vue请求数据放在created好还是mounted里好
2020/07/27 Javascript
如何利用 JS 脚本实现网页全自动秒杀抢购功能
2020/10/12 Javascript
[07:40]DOTA2每周TOP10 精彩击杀集锦vol.4
2014/06/25 DOTA
[33:17]OG vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
Python使用redis pool的一种单例实现方式
2016/04/16 Python
Python使用django搭建web开发环境
2017/06/09 Python
Python WEB应用部署的实现方法
2019/01/02 Python
谈谈对css属性box-sizing的了解
2017/01/04 HTML / CSS
Prototype中如何为一个元素添加一个方法
2014/12/08 面试题
财务主管的岗位职责
2013/12/30 职场文书
假面舞会策划方案
2014/05/29 职场文书
民主评议党员工作总结
2014/10/20 职场文书
2015年学校体育工作总结
2015/04/22 职场文书
2015年学校安全管理工作总结
2015/05/11 职场文书
vue3使用vue-router的完整步骤记录
2021/06/20 Vue.js