示例项目介绍

文中使用的例子是一个基于 Angular.js 实现的网页版 Todo App,在 Github 中下载angular-quickstart。项目代码结构如下

清单 5. 项目目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|--bower_components
|--build
|--node_modules
|--static_pages
|--js
   |--controllers
   |--services
   |--app.js          // app 启动配置
|--style
   |--main.css
|--view
   |--note.html
|--gulpfile.js      // gulp 配置
|--bower.json           // bower 配置
|--package.json         // node module 配置
|--index.html           // app 启动文件

架构上使用如下 libs

  • Angular:JavaScript 架构
  • Bootstrap:样式控件库
  • bower:管理项目依赖包
  • npm:管理项目运行的依赖工具
  • gulp:自动化构建工具

设计 build process

因为项目中使用到的 source code 有 JavaScript,,CSS,HTML 以及依赖 bower 导入的依赖包,所以我们将构建分成以下几个 task:

  1. jshint:编译 JavaScript
  2. clean:清空 build 目录
  3. template:合并并打包所有 HTML 模板文件生成 template.js
  4. js:压缩、混淆 JavaScript,并生成 sourcemap
  5. deployCSS:合并压缩 CSS
  6. devIndex:组织 develop 时的 index.html
  7. deployIndex:组织 deploy 时的 index.html,区别于第 6 个 task,这个 index.html 中 link 的将是压缩过的 CSS 和 JavaScript

接下来,我们分条介绍上面的 task。

设定全局变量 paths,记录 source code 的路径

清单 6. 项目 paths
1
2
3
4
5
6
7
var paths = {
 js: ['./js/app.js', 'js/**/*.js'],
 css: ['./style/**/*.css'],
 templates: './js/templates.js',
 buildjs: ['./build/**/*.js'],
 buildcss: ['./build/**/*.css']
};

task 1: jshint

这个 task 主要用来编译 JavaScript 代码。依赖插件 glup-jshint,需要在配置之前将这个插件安装好,之后如下配置:

清单 7. jshint
1
2
3
4
5
6
var jshint = require('gulp-jshint');
gulp.task('jshint', function() {
 gulp.src(paths.js)
 .pipe(jshint())
 .pipe(jshint.reporter('default'));
});

task 2: clean

我们可以看到项目目录中有个 build 文件夹,这个目录是用来存放所有 build 之后的 CSS/JS/HTML 文件。所以 clean 的任务是在每次 build 之前清理上一次 build 的 outputs,也就是清空 build 文件夹。依赖 del 模块:

清单 8. clean
1
2
3
4
5
var del = require('del');
gulp.task('clean', function() {
 // You can use multiple globbing patterns as you would with `gulp.src`
 return del(['./build', paths.templates]);
});

task 3: template

开发过程中一般按照功能模块将页面分成不同的 HTML 片段模板,每个片段对应一个相应 controller,客户端浏览器访问网页时会分别请求下载 HTML 文件。当业务逻辑较为复杂时,项目中将会存在很多的 HTML 小文件,此时下载的请求数目也会很大,影响 performance。我们的想法是使用插件 gulp-angular-templatecache,将这些 HTML 模版片段合并成一个文件。这个插件会将所有模板文件合并成一个 template.js, 并将其作为项目中的一个 module 而存在。

清单 9. template
1
2
3
4
5
6
var templateCache = require('gulp-angular-templatecache');
gulp.task('template', function () {
 return gulp.src('./view/**/*.html')
 .pipe(templateCache({module: 'myApp'}))
 .pipe(gulp.dest('./js'))
});

task 4: js

JavaScript 的 build 分成两种情况:

  1. DEV 模式:在开发环境中,为了方便 debug,JavaScript 通常不做压缩和混淆;
  2. PROD 模式:上生产环境时,JavaScript 必须并合压缩、混淆并成一个文件,同时需要去除所有的 log 输出语句。

JavaScript 混淆使用了插件 gulp-uglify;合并压缩使用了插件 gulp-concat,以及 gulp-sourcemaps;

去除 log 语句使用了插件 gulp-strip-debug。

清单 10. gulp 任务 js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gulp.task('js', function() {
 if (deployEnvironment == Environment.DEV) { // DEV
 return gulp.src(paths.js)
 .pipe(concat('all.js'))
 .pipe(gulp.dest('./build'));
 } else { // PROD
 return gulp.src(paths.js)
 .pipe(sourcemaps.init())
 .pipe(stripDebug())
 .pipe(uglify())
 .pipe(concat('all.min.js'))
 .pipe(sourcemaps.write())
 .pipe(gulp.dest('./build'));
 }
});

task 5: css

文中示例的样式表使用的是原生的 CSS 文件,所以使用 cssmin 完成了所有 CSS 文件的合并及压缩。

清单 11. gulp 任务 css
1
2
3
4
5
6
7
var cssmin = require('gulp-cssmin');
gulp.task('deployCSS', function() {
 return gulp.src(paths.css)
 .pipe(cssmin())
 .pipe(concat('all.css'))
 .pipe(gulp.dest('./build'));
});

task 6: devIndex

这个 task 主要是管理开发使用的 index.html 文件中对静态资源的引用。因为我们使用了 bower 来管理项目的依赖包,比如 jQuery 和 Angular,我们使用下面这种方式来导入项目:

清单 12. 引用静态资源
1
2
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>

可以看出,当我们需要引用的静态资源变得很多时,这个 list 也将会变得很长很不好管理。这时可以使用插件 gulp-inject。

1. 使用 bower 命令安装项目依赖包时添加--save-dev 参数,使配置写入 bower.json 文件。比如安装 angular 使用如下命令:

清单 13. 安装本地 angular 模块
1
$ bower install –-save-dev angular

安装成功以后 bower.json 文件的 dependencies 中会自动生成 angular 的依赖关系。

清单 14.bower.json
1
2
3
"dependencies": {
 "angular": "^1.5.7"
},

2. 在 index.html 中使用 inject 标签管理需要插入依赖包的位置。整理 index.html 成如下格式:

清单 15. 为 gulp-inject 准备的 index.html 模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <!-- endinject -->
 
 <!-- inject:css -->
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 <!-- bower:js -->
 <!-- endinject -->
 
 <!-- inject:js -->
 <!-- endinject -->
</body>
</html>

3. 配置 inject 的 task

清单 16.gulp 任务 inject
1
2
3
4
5
6
7
8
gulp.task('devIndex', ['clean', 'jshint'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.js, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.css, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

4. 执行命令 gulp devIndex,我们可以得到注入以后的 index.html 如下:

清单 17.Inject 后生成的 index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <link rel="stylesheet" href="bower_components/normalize-css/normalize.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.css">
 <!-- endinject -->
 
 <!-- inject:css -->
 <link rel="stylesheet" href="style/main.css">
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 
 <!-- bower:js -->
 <script src="bower_components/angular/angular.js"></script>
 <!-- endinject -->
 
 <!-- inject:js -->
 <script src="js/app.js"></script>
 <script src="js/controllers/note.js"></script>
 <script src="js/services/note.js"></script>
 <!-- endinject -->
</body>
</html>

task 7: deployIndex

deployIndex 主要是用来组织部署到测试或者生产环境时需要的 index.html。和 devIndex 的区别在于页面中引用的是合并压缩混淆后的静态资源,也就是项目目录 build 中的文件。此处同样也是使用的 gulp-inject,我们直接看一下 task。

清单 18. gulp 任务 deployIndex
1
2
3
4
5
6
7
8
gulp.task('deployIndex', ['clean', 'jshint', 'template', 'deployJS', 'deployCSS'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.buildjs, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.buildcss, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

上面这段代码在配置 deployIndex 时使用了三个参数,其中第二个参数表示当前 task 所依赖的 task list。

示例项目介绍

文中使用的例子是一个基于 Angular.js 实现的网页版 Todo App,在 Github 中下载angular-quickstart。项目代码结构如下

清单 5. 项目目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|--bower_components
|--build
|--node_modules
|--static_pages
|--js
   |--controllers
   |--services
   |--app.js          // app 启动配置
|--style
   |--main.css
|--view
   |--note.html
|--gulpfile.js      // gulp 配置
|--bower.json           // bower 配置
|--package.json         // node module 配置
|--index.html           // app 启动文件

架构上使用如下 libs

  • Angular:JavaScript 架构
  • Bootstrap:样式控件库
  • bower:管理项目依赖包
  • npm:管理项目运行的依赖工具
  • gulp:自动化构建工具

设计 build process

因为项目中使用到的 source code 有 JavaScript,,CSS,HTML 以及依赖 bower 导入的依赖包,所以我们将构建分成以下几个 task:

  1. jshint:编译 JavaScript
  2. clean:清空 build 目录
  3. template:合并并打包所有 HTML 模板文件生成 template.js
  4. js:压缩、混淆 JavaScript,并生成 sourcemap
  5. deployCSS:合并压缩 CSS
  6. devIndex:组织 develop 时的 index.html
  7. deployIndex:组织 deploy 时的 index.html,区别于第 6 个 task,这个 index.html 中 link 的将是压缩过的 CSS 和 JavaScript

接下来,我们分条介绍上面的 task。

设定全局变量 paths,记录 source code 的路径

清单 6. 项目 paths
1
2
3
4
5
6
7
var paths = {
 js: ['./js/app.js', 'js/**/*.js'],
 css: ['./style/**/*.css'],
 templates: './js/templates.js',
 buildjs: ['./build/**/*.js'],
 buildcss: ['./build/**/*.css']
};

task 1: jshint

这个 task 主要用来编译 JavaScript 代码。依赖插件 glup-jshint,需要在配置之前将这个插件安装好,之后如下配置:

清单 7. jshint
1
2
3
4
5
6
var jshint = require('gulp-jshint');
gulp.task('jshint', function() {
 gulp.src(paths.js)
 .pipe(jshint())
 .pipe(jshint.reporter('default'));
});

task 2: clean

我们可以看到项目目录中有个 build 文件夹,这个目录是用来存放所有 build 之后的 CSS/JS/HTML 文件。所以 clean 的任务是在每次 build 之前清理上一次 build 的 outputs,也就是清空 build 文件夹。依赖 del 模块:

清单 8. clean
1
2
3
4
5
var del = require('del');
gulp.task('clean', function() {
 // You can use multiple globbing patterns as you would with `gulp.src`
 return del(['./build', paths.templates]);
});

task 3: template

开发过程中一般按照功能模块将页面分成不同的 HTML 片段模板,每个片段对应一个相应 controller,客户端浏览器访问网页时会分别请求下载 HTML 文件。当业务逻辑较为复杂时,项目中将会存在很多的 HTML 小文件,此时下载的请求数目也会很大,影响 performance。我们的想法是使用插件 gulp-angular-templatecache,将这些 HTML 模版片段合并成一个文件。这个插件会将所有模板文件合并成一个 template.js, 并将其作为项目中的一个 module 而存在。

清单 9. template
1
2
3
4
5
6
var templateCache = require('gulp-angular-templatecache');
gulp.task('template', function () {
 return gulp.src('./view/**/*.html')
 .pipe(templateCache({module: 'myApp'}))
 .pipe(gulp.dest('./js'))
});

task 4: js

JavaScript 的 build 分成两种情况:

  1. DEV 模式:在开发环境中,为了方便 debug,JavaScript 通常不做压缩和混淆;
  2. PROD 模式:上生产环境时,JavaScript 必须并合压缩、混淆并成一个文件,同时需要去除所有的 log 输出语句。

JavaScript 混淆使用了插件 gulp-uglify;合并压缩使用了插件 gulp-concat,以及 gulp-sourcemaps;

去除 log 语句使用了插件 gulp-strip-debug。

清单 10. gulp 任务 js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gulp.task('js', function() {
 if (deployEnvironment == Environment.DEV) { // DEV
 return gulp.src(paths.js)
 .pipe(concat('all.js'))
 .pipe(gulp.dest('./build'));
 } else { // PROD
 return gulp.src(paths.js)
 .pipe(sourcemaps.init())
 .pipe(stripDebug())
 .pipe(uglify())
 .pipe(concat('all.min.js'))
 .pipe(sourcemaps.write())
 .pipe(gulp.dest('./build'));
 }
});

task 5: css

文中示例的样式表使用的是原生的 CSS 文件,所以使用 cssmin 完成了所有 CSS 文件的合并及压缩。

清单 11. gulp 任务 css
1
2
3
4
5
6
7
var cssmin = require('gulp-cssmin');
gulp.task('deployCSS', function() {
 return gulp.src(paths.css)
 .pipe(cssmin())
 .pipe(concat('all.css'))
 .pipe(gulp.dest('./build'));
});

task 6: devIndex

这个 task 主要是管理开发使用的 index.html 文件中对静态资源的引用。因为我们使用了 bower 来管理项目的依赖包,比如 jQuery 和 Angular,我们使用下面这种方式来导入项目:

清单 12. 引用静态资源
1
2
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>

可以看出,当我们需要引用的静态资源变得很多时,这个 list 也将会变得很长很不好管理。这时可以使用插件 gulp-inject。

1. 使用 bower 命令安装项目依赖包时添加--save-dev 参数,使配置写入 bower.json 文件。比如安装 angular 使用如下命令:

清单 13. 安装本地 angular 模块
1
$ bower install –-save-dev angular

安装成功以后 bower.json 文件的 dependencies 中会自动生成 angular 的依赖关系。

清单 14.bower.json
1
2
3
"dependencies": {
 "angular": "^1.5.7"
},

2. 在 index.html 中使用 inject 标签管理需要插入依赖包的位置。整理 index.html 成如下格式:

清单 15. 为 gulp-inject 准备的 index.html 模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <!-- endinject -->
 
 <!-- inject:css -->
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 <!-- bower:js -->
 <!-- endinject -->
 
 <!-- inject:js -->
 <!-- endinject -->
</body>
</html>

3. 配置 inject 的 task

清单 16.gulp 任务 inject
1
2
3
4
5
6
7
8
gulp.task('devIndex', ['clean', 'jshint'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.js, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.css, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

4. 执行命令 gulp devIndex,我们可以得到注入以后的 index.html 如下:

清单 17.Inject 后生成的 index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <link rel="stylesheet" href="bower_components/normalize-css/normalize.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.css">
 <!-- endinject -->
 
 <!-- inject:css -->
 <link rel="stylesheet" href="style/main.css">
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 
 <!-- bower:js -->
 <script src="bower_components/angular/angular.js"></script>
 <!-- endinject -->
 
 <!-- inject:js -->
 <script src="js/app.js"></script>
 <script src="js/controllers/note.js"></script>
 <script src="js/services/note.js"></script>
 <!-- endinject -->
</body>
</html>

task 7: deployIndex

deployIndex 主要是用来组织部署到测试或者生产环境时需要的 index.html。和 devIndex 的区别在于页面中引用的是合并压缩混淆后的静态资源,也就是项目目录 build 中的文件。此处同样也是使用的 gulp-inject,我们直接看一下 task。

清单 18. gulp 任务 deployIndex
1
2
3
4
5
6
7
8
gulp.task('deployIndex', ['clean', 'jshint', 'template', 'deployJS', 'deployCSS'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.buildjs, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.buildcss, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

上面这段代码在配置 deployIndex 时使用了三个参数,其中第二个参数表示当前 task 所依赖的 task list。

调用 gulp deployIndex,生成的 index.html 和上一个 task 类似,不过 CSS 和 JS 的引用会修改如下:

清单 19. Inject 之后生成的 index.html
1
2
3
4
5
6
<!-- inject:css -->
<link rel="stylesheet" href="build/all.css">
<!-- endinject -->
<!-- inject:js -->
<script src="build/all.min.js"></script>
<!-- endinject -->

结束语

随着"前后端分离"架构的日渐普及,前台的自动化构建将越来越被重视。本文着重介绍了 gulp 的使用方式,以及 Web 前台开发过程中涉及的一些自动化构建切入点,希望读者可以通过本文了解 Web 前台的自动化构建相关知识。

调用 gulp deployIndex,生成的 index.html 和上一个 task 类似,不过 CSS 和 JS 的引用会修改如下:

清单 19. Inject 之后生成的 index.html
1
2
3
4
5
6
<!-- inject:css -->
<link rel="stylesheet" href="build/all.css">
<!-- endinject -->
<!-- inject:js -->
<script src="build/all.min.js"></script>
<!-- endinject -->

结束语

随着"前后端分离"架构的日渐普及,前台的自动化构建将越来越被重视。本文着重介绍了 gulp 的使用方式,以及 Web 前台开发过程中涉及的一些自动化构建切入点,希望读者可以通过本文了解 Web 前台的自动化构建相关知识。

示例项目介绍

文中使用的例子是一个基于 Angular.js 实现的网页版 Todo App,在 Github 中下载angular-quickstart。项目代码结构如下

清单 5. 项目目录结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|--bower_components
|--build
|--node_modules
|--static_pages
|--js
   |--controllers
   |--services
   |--app.js          // app 启动配置
|--style
   |--main.css
|--view
   |--note.html
|--gulpfile.js      // gulp 配置
|--bower.json           // bower 配置
|--package.json         // node module 配置
|--index.html           // app 启动文件

架构上使用如下 libs

  • Angular:JavaScript 架构
  • Bootstrap:样式控件库
  • bower:管理项目依赖包
  • npm:管理项目运行的依赖工具
  • gulp:自动化构建工具

设计 build process

因为项目中使用到的 source code 有 JavaScript,,CSS,HTML 以及依赖 bower 导入的依赖包,所以我们将构建分成以下几个 task:

  1. jshint:编译 JavaScript
  2. clean:清空 build 目录
  3. template:合并并打包所有 HTML 模板文件生成 template.js
  4. js:压缩、混淆 JavaScript,并生成 sourcemap
  5. deployCSS:合并压缩 CSS
  6. devIndex:组织 develop 时的 index.html
  7. deployIndex:组织 deploy 时的 index.html,区别于第 6 个 task,这个 index.html 中 link 的将是压缩过的 CSS 和 JavaScript

接下来,我们分条介绍上面的 task。

设定全局变量 paths,记录 source code 的路径

清单 6. 项目 paths
1
2
3
4
5
6
7
var paths = {
 js: ['./js/app.js', 'js/**/*.js'],
 css: ['./style/**/*.css'],
 templates: './js/templates.js',
 buildjs: ['./build/**/*.js'],
 buildcss: ['./build/**/*.css']
};

task 1: jshint

这个 task 主要用来编译 JavaScript 代码。依赖插件 glup-jshint,需要在配置之前将这个插件安装好,之后如下配置:

清单 7. jshint
1
2
3
4
5
6
var jshint = require('gulp-jshint');
gulp.task('jshint', function() {
 gulp.src(paths.js)
 .pipe(jshint())
 .pipe(jshint.reporter('default'));
});

task 2: clean

我们可以看到项目目录中有个 build 文件夹,这个目录是用来存放所有 build 之后的 CSS/JS/HTML 文件。所以 clean 的任务是在每次 build 之前清理上一次 build 的 outputs,也就是清空 build 文件夹。依赖 del 模块:

清单 8. clean
1
2
3
4
5
var del = require('del');
gulp.task('clean', function() {
 // You can use multiple globbing patterns as you would with `gulp.src`
 return del(['./build', paths.templates]);
});

task 3: template

开发过程中一般按照功能模块将页面分成不同的 HTML 片段模板,每个片段对应一个相应 controller,客户端浏览器访问网页时会分别请求下载 HTML 文件。当业务逻辑较为复杂时,项目中将会存在很多的 HTML 小文件,此时下载的请求数目也会很大,影响 performance。我们的想法是使用插件 gulp-angular-templatecache,将这些 HTML 模版片段合并成一个文件。这个插件会将所有模板文件合并成一个 template.js, 并将其作为项目中的一个 module 而存在。

清单 9. template
1
2
3
4
5
6
var templateCache = require('gulp-angular-templatecache');
gulp.task('template', function () {
 return gulp.src('./view/**/*.html')
 .pipe(templateCache({module: 'myApp'}))
 .pipe(gulp.dest('./js'))
});

task 4: js

JavaScript 的 build 分成两种情况:

  1. DEV 模式:在开发环境中,为了方便 debug,JavaScript 通常不做压缩和混淆;
  2. PROD 模式:上生产环境时,JavaScript 必须并合压缩、混淆并成一个文件,同时需要去除所有的 log 输出语句。

JavaScript 混淆使用了插件 gulp-uglify;合并压缩使用了插件 gulp-concat,以及 gulp-sourcemaps;

去除 log 语句使用了插件 gulp-strip-debug。

清单 10. gulp 任务 js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gulp.task('js', function() {
 if (deployEnvironment == Environment.DEV) { // DEV
 return gulp.src(paths.js)
 .pipe(concat('all.js'))
 .pipe(gulp.dest('./build'));
 } else { // PROD
 return gulp.src(paths.js)
 .pipe(sourcemaps.init())
 .pipe(stripDebug())
 .pipe(uglify())
 .pipe(concat('all.min.js'))
 .pipe(sourcemaps.write())
 .pipe(gulp.dest('./build'));
 }
});

task 5: css

文中示例的样式表使用的是原生的 CSS 文件,所以使用 cssmin 完成了所有 CSS 文件的合并及压缩。

清单 11. gulp 任务 css
1
2
3
4
5
6
7
var cssmin = require('gulp-cssmin');
gulp.task('deployCSS', function() {
 return gulp.src(paths.css)
 .pipe(cssmin())
 .pipe(concat('all.css'))
 .pipe(gulp.dest('./build'));
});

task 6: devIndex

这个 task 主要是管理开发使用的 index.html 文件中对静态资源的引用。因为我们使用了 bower 来管理项目的依赖包,比如 jQuery 和 Angular,我们使用下面这种方式来导入项目:

清单 12. 引用静态资源
1
2
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>

可以看出,当我们需要引用的静态资源变得很多时,这个 list 也将会变得很长很不好管理。这时可以使用插件 gulp-inject。

1. 使用 bower 命令安装项目依赖包时添加--save-dev 参数,使配置写入 bower.json 文件。比如安装 angular 使用如下命令:

清单 13. 安装本地 angular 模块
1
$ bower install –-save-dev angular

安装成功以后 bower.json 文件的 dependencies 中会自动生成 angular 的依赖关系。

清单 14.bower.json
1
2
3
"dependencies": {
 "angular": "^1.5.7"
},

2. 在 index.html 中使用 inject 标签管理需要插入依赖包的位置。整理 index.html 成如下格式:

清单 15. 为 gulp-inject 准备的 index.html 模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <!-- endinject -->
 
 <!-- inject:css -->
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 <!-- bower:js -->
 <!-- endinject -->
 
 <!-- inject:js -->
 <!-- endinject -->
</body>
</html>

3. 配置 inject 的 task

清单 16.gulp 任务 inject
1
2
3
4
5
6
7
8
gulp.task('devIndex', ['clean', 'jshint'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.js, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.css, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

4. 执行命令 gulp devIndex,我们可以得到注入以后的 index.html 如下:

清单 17.Inject 后生成的 index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en" data-ng-app="myApp">
<head>
<meta charset="utf-8">
 <title>Angular UI Router</title>
 <!-- bower:css -->
 <link rel="stylesheet" href="bower_components/normalize-css/normalize.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap-theme.css">
 <!-- endinject -->
 
 <!-- inject:css -->
 <link rel="stylesheet" href="style/main.css">
 <!-- endinject -->
</head>
<body>
 <a ui-sref="note">go note</a>
 <div ui-view></div>
 
 <!-- bower:js -->
 <script src="bower_components/angular/angular.js"></script>
 <!-- endinject -->
 
 <!-- inject:js -->
 <script src="js/app.js"></script>
 <script src="js/controllers/note.js"></script>
 <script src="js/services/note.js"></script>
 <!-- endinject -->
</body>
</html>

task 7: deployIndex

deployIndex 主要是用来组织部署到测试或者生产环境时需要的 index.html。和 devIndex 的区别在于页面中引用的是合并压缩混淆后的静态资源,也就是项目目录 build 中的文件。此处同样也是使用的 gulp-inject,我们直接看一下 task。

清单 18. gulp 任务 deployIndex
1
2
3
4
5
6
7
8
gulp.task('deployIndex', ['clean', 'jshint', 'template', 'deployJS', 'deployCSS'], function () {
 // It's not necessary to read the files (will speed up things), we're only after their paths:
 return gulp.src('./index.html')
 .pipe(inject(gulp.src(paths.buildjs, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(paths.buildcss, {read: false}), {relative: true}))
 .pipe(inject(gulp.src(bowerFiles(), {read: false}), {name: 'bower', relative: true}))
 .pipe(gulp.dest('./'));
});

上面这段代码在配置 deployIndex 时使用了三个参数,其中第二个参数表示当前 task 所依赖的 task list。

调用 gulp deployIndex,生成的 index.html 和上一个 task 类似,不过 CSS 和 JS 的引用会修改如下:

清单 19. Inject 之后生成的 index.html
1
2
3
4
5
6
<!-- inject:css -->
<link rel="stylesheet" href="build/all.css">
<!-- endinject -->
<!-- inject:js -->
<script src="build/all.min.js"></script>
<!-- endinject -->

结束语

随着"前后端分离"架构的日渐普及,前台的自动化构建将越来越被重视。本文着重介绍了 gulp 的使用方式,以及 Web 前台开发过程中涉及的一些自动化构建切入点,希望读者可以通过本文了解 Web 前台的自动化构建相关知识。

gulp + angularjs的更多相关文章

  1. 记项目中ES6+gulp+angularjs里的问题

    AngualrJs中可用来注入的有三种类型,service.factory.provider,这三种写法不样,用法也都不一样.其中,service只实例化一次,其实就是单例模式的思想.无论我们在什么地 ...

  2. gulp 在 angular 项目中的使用

    gulp 在 angular 项目中的使用 keyword:gulp,angularjs,ng,ngAnnotate,jshint,gulpfile 最后附完整简洁的ng项目gulpfile.js 准 ...

  3. 新建一个angularjs+requirejs+bootstrap+typescript+gulp+vscode+git的项目

    环境 windows 10 准备工具 Visual Studio Code Node.js Git 需求 必须支持IE8 步骤开始: 执行命令行工具 mkdir Demo && cd ...

  4. angularjs, nodejs, express, gulp, karma, jasmine 前端方案整合

    今年转向做前端开发,主要是做angularjs开发,期间接触了nodejs平台,从此一发不可收拾. npm丰富的插件库,express 开发框架, grunt, gulp构建工具,karma测试管理工 ...

  5. Angularjs E2E test Report/CoverageReport - 使用Gulp

    上一篇(http://www.cnblogs.com/xiaoningz/p/7122633.html)使用grunt-protractor-coverage 做为覆盖率测试插件,如果项目的管理工具刚 ...

  6. 前端自动化工具 -- gulp https://angularjs.org/

    gulp是基于流的前端自动化构建工具. gulp是基于stream流的形式,也就是前一个函数(工厂)制造出结果,提供后者使用. 同样的,也是包括基本用法和各插件的使用. 二.基本用法--插件使用 gu ...

  7. 基于AngularJS的个推前端云组件探秘

    基于AngularJS的个推前端云组件探秘 AngularJS是google设计和开发的一套前端开发框架,帮助开发人员简化前端开发的负担.AngularJS将帮助标准化的开发web应用结构并且提供了针 ...

  8. 基于AngularJS的企业软件前端架构[转载]

    这篇是我参加QCon北京2014的演讲内容: 提纲: 企业应用在软件行业中占有很大的比重,而这类软件多数现在也都采用B/S的模式开发,在这个日新月异的时代,它们的前端开发技术找到了什么改进点呢? B/ ...

  9. 如何在 ASP.NET MVC 中集成 AngularJS(3)

    今天来为大家介绍如何在 ASP.NET MVC 中集成 AngularJS 的最后一部分内容. 调试路由表 - HTML 缓存清除 就在我以为示例应用程序完成之后,我意识到,我必须提供两个版本的路由表 ...

随机推荐

  1. C语言专项错题集

    2020-08-10 记录 #1 1 struct student{ 2 int num; 3 int age; 4 }; 5 struct student stu[3]={{6001,20},{60 ...

  2. 2020 Java开发者数据分析:中国已成为 Java 第一大国

    最近知名开发工具供应商Jetbrains在Java 25周年之际,对开发群体做了一次有意思的数据分析. 全文内容可见:https://blog.jetbrains.com/idea/2020/09/a ...

  3. C语言普通写法实现:针对多次同步失败的节能处理机制

    程序不美, 不来一一整理了. 以后有时间可以把这个功能封装为一个类的对象来操作.即使不封装为类,至少也该封装为一个独立的函数吧... 关键代码摘要如下: 无线同步信号发射端,每分钟发一次,每次发射的时 ...

  4. Linux学习笔记-vi(一)

    vim编辑命令 vim命令的三种模式: 1.命令模式: vi file.txt  进入vi模式,默认为命令模式,命令模式移动光标. 2.插入模式 i (insert):在光标前插入内容 a(appen ...

  5. 小伙伴想学Jenkins自动构建发布项目,我:安排上了!!

    写在前面 趁着十一长假,很多小伙伴都在悄悄学习,有些是为了能够顺利通过面试,进入大厂升职加薪.有些则是为了进一步巩固和提高自己的专业技能,希望有朝一日能过成为互联网架构师乃至技术专家.这不,就有小伙伴 ...

  6. DOJO dataGrid 单击单元格选中行

    onCellClick: lang.hitch(this, function(event){ //单元格单击事件 var grid = dijit.byId("__geodisa_grid& ...

  7. shiro入门学习--使用MD5和salt进行加密|练气后期

    写在前面 在上一篇文章<Shiro入门学习---使用自定义Realm完成认证|练气中期>当中,我们学会了使用自定义Realm实现shiro数据源的切换,我们可以切换成从关系数据库如MySQ ...

  8. Eclipse4.5 Mars版本安装activiti插件 亲测可用

    Eclipse4.5 Mars版本安装activiti插件 亲测可用 学习使用activiti 在线安装一直,国内的网络真心的是 很苦 啊:在茫茫网络上面找到了很多插件的离线包 终于找到一个可以使用的 ...

  9. 多测师讲解htm_L标题标签001_高级讲师 肖sir

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>百 ...

  10. 闭嘴,给你一个数!1分钟,学完C语言指针,不扎手只扎心的针!

    序言 指针是C语言学习者绕不过的一道坎,也是C语言学习者不得绕过的一道坎.辨别一个人C语言学的好赖就看他对指针的理解怎么样.指针内容也是工作面试经常问到的问题.本文将带你重新认识那个绊倒你的指针,以解 ...