之前做过一个项目,是一种无线设备,由于设备本身的内存容量比较小,为了节约内存使用,选择了gulp这种工具,可以将前端的代码进行打包发布,并能在项目中正常运行,较之之前的代码量有了量的突破,还是不错的。后来接触的项目几乎无一例外的都是用到打包这种工具。我们知道在html中引入js才能让我们的事件起到效果,那么使用gulp这种工具的好处就在于,编译或者压缩之后的js文件完全可以替代之前传统意义上的js文件,不管你目录怎样?他都能编译后被浏览器识别,被程序识别。

当然这么做的唯一坏处就是不太容易debug,在开发环境中是很容易debug的,因为在开发环境中随时可以替换自己的代码去debug问题,当然各有利弊。在测试环境中我们还是可以保留源码,通过双引入(引入压缩js文件和非压缩文件),来测试复现定位BUG。

工欲善其事必先利其器,想要使用gulp组件打包,需要安装gulp。安装gulp,就不得不讲到另外一个----Node.js.它可以提供世界上最全的开源库生态。

1.Node.js安装

https://nodejs.org/zh-cn/

怎么用yarn打包构建前端项目 打包前端代码_css

命令执行没有问题,就算安装好了。接着我们需要通过node通过的npm命令来执行一系列的依赖js包安装。

切到工作目录下执行npm install -g

怎么用yarn打包构建前端项目 打包前端代码_nodejs_02

将会执行一段时间,他其实是在为你下载依赖库文件,生成一个叫node_modules的文件夹,这个文件夹下的便

时所有的依赖包了。

怎么用yarn打包构建前端项目 打包前端代码_gulp_03

往下拉,我们能够看到打包工具所对应的gulp一系列的包文件

怎么用yarn打包构建前端项目 打包前端代码_怎么用yarn打包构建前端项目_04

到目前为止,我们就是使用nodejs安装好我们所需要的打包工具gulp,下面我们就来看看怎么使用gulp来实现

打包功能。

2.gulp 打包

我们先来看看我的工作目录,是怎么划分的

怎么用yarn打包构建前端项目 打包前端代码_css_05

所有的项目使用的js和html源码,我都是放到src下,这个路径在后面我们使用gulp.src时能够用到。

接下来最关键的就是如何使用其API来实现我们的打包功能。

2.1 引入依赖包

首先我们需要在项目的根目录下,也就是我这里对应的HAM-Front下创建一个gulpfile.js文件,我们会在这个文件种引入依赖的js文件和定义一些执行任务。

// Include gulp
var gulp = require('gulp');

require:引入gulp资源文件,类似于java中import作用

var connect = require('gulp-connect');
var gulpDocs = require('gulp-ngdocs');

这两条命令的意识是引入docs文件,使用gulp可以生成自定义的dos类型的API文档,这个比较高级了。我们的自定义组件都有自己对应的API文档,方便我们自己使用。如果你也有自己API文档不放参考gulp的官方文档,这里不做说明(都是机密

)

怎么用yarn打包构建前端项目 打包前端代码_css_06

如上执行自定义的connect-docs执行,他就会为你启动一个端口为8080的服务,那么你只要在浏览器中输入localhost:8080,就可以访问你们的docs文档。

   

怎么用yarn打包构建前端项目 打包前端代码_怎么用yarn打包构建前端项目_07

// Include Our Plugins
var plugins = require('gulp-load-plugins')({pattern: ['*']});


var wmaApp = 'src/main/webapp/app';
var wmaTemplatePath = '';
var wmaModule = 'am';

自定义项目路径和module模块。

2.2 gulp-task

gulp.task:执行自定义的一系列任务,gulp会最大量的执行定义的所有任务,这些任务不分先后。

gulp.task("one", function () {

});
gulp.task("two", function () {

});

那么这两个任务回一起执行,当然gulp也会支持先后执行,这个需要你做特殊的声明。我们来看看官网是怎么给出支持的。

1.异步支持

gulp支持异步方式,依次执行你所需要的任务,使用一个 callback,或者返回一个 promise 或 stream。

接收一个callback函数:

// 在 shell 中执行一个命令
var exec = require('child_process').exec;
gulp.task('jekyll', function(cb) {
  // 编译 Jekyll
  exec('jekyll build', function(err) {
    if (err) return cb(err); // 返回 error
    cb(); // 完成 task
  });
});

返回一个stream或者promise:

gulp.task('somename', function() {
  var stream = gulp.src('client/**/*.js')
    .pipe(minify())
    .pipe(gulp.dest('build'));
  return stream;
});
var Q = require('q');

gulp.task('somename', function() {
  var deferred = Q.defer();

  // 执行异步的操作
  setTimeout(function() {
    deferred.resolve();
  }, 1);

  return deferred.promise;
});

当需要批量执行一个序列化的任务时,我们需要让下一个任务知道他需要在谁之后执行:(以下内容来自官网)

给出一个提示,来告知 task 什么时候执行完毕,

并且再给出一个提示,来告知一个 task 依赖另一个 task 的完成。

对于这个例子,让我们先假定你有两个 task,"one" 和 "two",并且你希望它们按照这个顺序执行:

  1. 在 "one" 中,你加入一个提示,来告知什么时候它会完成:可以再完成时候返回一个 callback,或者返回一个 promise 或 stream,这样系统会去等待它完成。
  2. 在 "two" 中,你需要添加一个提示来告诉系统它需要依赖第一个 task 完成。

因此,这个例子的实际代码将会是这样:

var gulp = require('gulp');

// 返回一个 callback,因此系统可以知道它什么时候完成
gulp.task('one', function(cb) {
    // 做一些事 -- 异步的或者其他的
    cb(err); // 如果 err 不是 null 或 undefined,则会停止执行,且注意,这样代表执行失败了
});

// 定义一个所依赖的 task 必须在这个 task 执行之前完成
gulp.task('two', ['one'], function() {
    // 'one' 完成后
});

gulp.task('default', ['one', 'two']);

知道任务时怎么执行的之后,我们来创建我们的任务,然后定义需要执行的步骤。

2.3 js,css打包

gulp打包会将js和html代码打包到一个js中,把css打包到另外一个css中,这需要我们定义不同的任务来实现

  • 定制js打包任务

// Concatenate & Minify JS
gulp.task('script-build', function () {

  var javascriptStream = gulp.src(wmaApp + '/**/*.js');
  var htmlStream = gulp.src(wmaApp + '/**/*.html')
    .pipe(plugins.htmlmin({collapseWhitespace: true}))
    .pipe(plugins.angularTemplatecache('templateCache.js', {module: wmaModule, root: wmaTemplatePath}));

  return plugins.eventStream.merge(javascriptStream, htmlStream)
    .pipe(plugins.angularFilesort())
    .pipe(plugins.concat('ham.min.js'))
    .pipe(plugins.uglify())
    .pipe(gulp.dest('build/scripts'));


});

  • 定制css打包任务

// Concatenate & Minify CSS
gulp.task('css-build', function () {
  return gulp.src(wmaApp + '/**/*.css')
    .pipe(plugins.concat('ham.min.css'))
    .pipe(plugins.minifyCss())
    .pipe(gulp.dest('build/styles/css'));
});

通过上面定义的两个任务就可以将css和js文件打包。

其中:

gulp.src(""):输出与指定匹配字符串或数组的文件,将返回一个 Vinyl files 的 stream 它可以被 piped 到别的

插件中。简单的说就是vinyl file的一种流文件,这种流文件可以具备可读写性,更重的是可以被pie到插件中。pie是

nodejs提供的一种方法,该方法可以增加可写性流的可读性,使其可能自动的切换到流动模式,并且使流的所有

数据成为可写。为了防止可写流不被更快的可读流覆盖淹没,这些数据流将会被自动管理。

gulp.dest():之前被pie进去的所有文件数据将会重新输出到文件中,这个文件可以是指定的存在的文件,也

可以是不存在的,如果不存在的话,它将会为你创建该文件。

2.4 gulp-clean

gulp-clean:创建clean任务,该任务主要作用是为了清除之前pie输出的流文件,为了避免在生成文件的时候

数据被覆盖,通常我们希望每次build的文件都是我们需要的最新的,我们需要将之前的文件流清除掉,来生成最新

的。

简单的来说就是直接删除已经build生成的文件:

// Clean existed build
gulp.task('clean', function () {
  return gulp.src(
    [
      'build/*'
    ])
    .pipe(plugins.clean({force: true}));
});

为了方便操作,我们定制了一系列的任务,让他执行,这个定制任务分为两个部分。一部分:清除已build编译

的文件;二部分:重新build文件生成新的我们需要的文件。

2.5 gulp-build

创建这个任务主要是为了方便我们操作:其实就是把clean,和重新编译任务组成一个有序的任务队列,让gulp

依次执行,还好nodejs提供了方法:

// Build all
gulp.task('build', function () {
  plugins.runSequence('clean', 'script-build', 'css-build');
});

就是依次执行这三个任务,关于runSequence这个方法在下面这个文件中有定义,感兴趣的可以看看源码。

怎么用yarn打包构建前端项目 打包前端代码_打包_08

这样我们定制的所有任务在webstorm中都有提示:

怎么用yarn打包构建前端项目 打包前端代码_gulp_09

我们切换到build目录下看看我们生成的编译压缩的文件:只要将这两个文件引入到index.html文件中就可以正常的使用,正常的访问项目了,有没有觉得很酷呢

          

怎么用yarn打包构建前端项目 打包前端代码_打包_10