参照Gulp for Beginners来学习Gulp基本内容。以下为学习记录笔记。
安装Gulp
首先需要安装Node.js,并在控制台输入$ npm install gulp -g
Mac端需要写成$ sudo npm install gulp -g
(因为Mac端需要在管理员下)运行来安装Gulp,-g
表示全局安装。
创建一个Gulp项目
学习过程,将使用一个名为project的文件夹作为项目根目录,在文件夹内运行$ npm init
,这将会为你的项目创建一个叫package.json的文件,文件会存储关于你的项目的信息,就像在项目里使用的依赖(Gulp就是依赖的一个例子)
在创建了package.json之后,就可以通过$ npm install gulp --save-dev
在项目中安装Gulp,这次我们是把Gulp安装到project项目中,而不是全局安装。(这次Mac端也不需要使用sudo)--save-dev
意思是把gulp作为依赖添加到当前项目。
现在,可以在原来的文件夹中看到一个node_modules
文件夹,在node_modules
文件夹中包含着gulp
文件夹。
已经做好使用Gulp的准备工作,在我们使用Gulp之前我们必须清楚我们将要怎么在项目中使用Gulp,其中之一就是决定目录结构。
确定文件结构
在这个结构中,
app
文件夹是用来做开发的,
dist
文件夹是用来包含生产现场的优化文件。
因为
app
是用于开发,所以我们所有的代码都会放在
app
文件夹下。
在配置Gulp时,我们必须记住文件夹的结构。现在就可以开始在存储所有Gulp配置的gulpfile.js创建第一个Gulp任务。
写你的第一个Gulp任务
使用Gulp的第一步是把它require
到gulpfile中
var gulp=require('gulp');
这个require
语句会告诉Node在node_modules
文件夹中查找一个叫gulp
的包,一旦找到,就会把包的内容赋值到变量gulp
中。
接下来就可以使用这个gulp
变量来写gulp
任务,一个gulp
任务的基础语法是:
gulp.task('task-name',function(){
//stuff here
});
task-name
指的是任务的名字,将会被用在你想在Gulp
运行一个任务的时候。你也可以使用命令行gulp task-name
来运行相同的任务。
测试例子:
var gulp=require('gulp');
gulp.task('hello',function(){
console.log('Hello world!');
});
我们可以通过在控制台输入$ gulp hello
来运行这个任务。
就可以在控制台看到以下的结果:
Gulp任务通常会比这个复杂,通常会包含两个额外的Gulp方法,和各种Gulp插件。
以下是一个真实任务可能的情况:
gulp.task('task-name', function () {
return gulp.src('source-files') // Get source files withgulp.src
.pipe(aGulpPlugin()) // Sends it through a gulp plugin
.pipe(gulp.dest('destination')) // Outputs the file in the destination folder
})
可以看到,一个真实的任务会用到两个额外的gulp方法——gulp.src
和gulp.dest
gulp.src
告诉Gulp 任务在这个任务中使用哪些文件。gulp.dest
告诉Gulp当任务完成时应该在哪里输出。
用Gulp预处理
使用一个叫gulp-sass
的插件可以在Gulp将Sass编译成CSS,使用像安装Gulp一样的npm install
命令安装gulp-sass
到项目中:
$ npm install gulp-sass --save-dev
使用--save-dev
标记来保证gulp-sass被添加到package.json
中的devDependencies
中。
PS:在下载插件的过程中可能会遇到下载较慢的问题,可通过调用国内镜像来解决 来源
镜像使用方法(三种办法任意一种都能解决问题,建议使用第三种,将配置写死,下次用的时候配置还在):
1.通过config命令
npm config set registry https://registry.npm.taobao.org npm info underscore (如果上面配置正确这个命令会有字符串response)
2.命令行指定
npm --registry https://registry.npm.taobao.org info underscore
3.编辑~/.npmrc
加入下面内容
registry = https://registry.npm.taobao.org
搜索镜像: https://npm.taobao.org
建立或使用镜像,参考: https://github.com/cnpm/cnpmjs.org
在安装过程中我自己还遇到另一个问题,错误信息
gyp verb check python checking for Python executable "python2" in the PATH
gyp verb `which` failed Error: not found: python2
解决办法: $ npm install python
在我们使用这个插件之前,我们必须像使用gulp那样先把gulp-sass
从node_modules
文件夹中require
进来。
var gulp = require('gulp');
// Requires the gulp-sass pluginvar
sass = require('gulp-sass');
现在就可以把上面的aGulpPlugin()
替换成sass()
。
gulp.task('sass', function(){
return gulp.src('source-files')
.pipe(sass()) // Using gulp-sass
.pipe(gulp.dest('destination'))
});
现在我们需要为sass
任务提供源文件和目标文件来使得任务运行,现在在app/scss创建一个styles.scss文件。这个文件将会在gulp.src()
中被添加到sass任务。
这里我们把最终的styles.css
文件输出到app/css
文件夹中,这将是gulp.dest
的destination
。
gulp.task('sass', function(){
return gulp.src('app/scss/styles.scss')
.pipe(sass()) // Converts Sass to CSS with gulp-sass
.pipe(gulp.dest('app/css'))
});
为了测试sass任务是否像我们希望的那样运行。我们会在styles.scss
中添加一个Sass方法。
// styles.scss
.testing { width: percentage(5/7);}
在控制台上运行gulp sass
后,回到app/css
目录下,可以看到一个styles.css
的文件。内容如下:
.testing {
width: 71.42857%; }
PS:Gulp-sass使用LibSass把Sass转换成CSS,这会比基于Ruby的方法更快。如果你想依然在gulp中使用Ruby方法的话,可以使用gulp-ruby-sass或者gulp-compass.
Node中的通配符(Globbing in Node)
Globs(通配符)是允许你添加多于一个文件进gulp.src()
中的匹配模式。这就像是普通的表达式,但是是专门给文件路径的。
当你使用一个glob的时候,电脑会根据特定的模式来检查你的文件名称和路径。若存在,则该文件就被匹配。
多数Gulp工作流通常只需要4种不同的通配符模式:
- ** *.scss: **
*
是一个在当前目录匹配所有模式的通配符。在这个栗子中,我们会匹配在根目录(project)下所有以.scss
结尾的文件。 - ******/*.scss :这是一个
*
模式更为极端的一个版本,它会匹配根目录和其它子目录的所有以.scss
结尾的文件。 - !not-me.scss:
!
表明Gulp会排除掉与之匹配的模式,这在你需要排除掉一个匹配中的文件时会很有用。在这个栗子中,not-me.scss
将会在匹配中被排除。 - ** .+(scss|sass) :*加号和括号(parentheses)允许Gulp去匹配多种模式,不同的模式被
|
(pipe)隔开。这个栗子中,Gulp会匹配根目录下所有以.scss
或.sass
结尾的所有文件。
现在我们就可以把app/scss/styles.scss
替换成scss/**/*.scss
模式。
gulp.task('sass', function() {
return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
.pipe(sass())
.pipe(gulp.dest('app/css'))
})
现在的问题是,我们每次都要手动去调用gulp sass
才能把Sass转换成CSS吗?
我们可以通过一个叫"watching"的进程让Gulp在sass保存的时候自动运行sass任务。
监视Sass文件的变化(Watching Sass files for changes)
Gulp为我们提供了一个watch
方法来检查文件是否被保存。watch
方法的语法是:
// Gulp watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run']);
如果我们想监听所有的Sass文件并在Sass文件被保存时运行sass任务,我们只需要把files-to-watch
换成app/scss/**/*.scss
,把['tasks', 'to', 'run']
换成['sass']:
// Gulp watch syntax
gulp.watch('app/scss/**/*.scss', ['sass']);
gulp.task('watch', function(){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Other watchers
})
当你运行了gulp watch
命令后,你就能看到Gulp马上开始监听了。
接下来就看看怎么让Gulp在Browser Sync的帮助下实现在保存一个.scss文件时重载浏览器。
Browser Sync实时重载(Live-reloading with Browser Sync)
通过spinning up web 服务器Browser Sync能让我们更容易实现实时重载。它也有其它特征,例如多设备同步动作。
- 第一步:安装Browser Sync
$ npm install browser-sync --save-dev
你会发现当我们安装Browser Sync时并没有gulp-
前缀。这是因为Browser Sync是和Gulp一起运行的,所以我们不需要使用插件。
- 第二步:require Browser Sync
var browserSync = require('browser-sync').create();
我们需要创建一个browserSync
任务使得Gulp可以使用Browser Sync旋转加速服务器。因为我们正在运行服务器,我们需要让Browser Sync知道服务器的根目录应该在哪里。在这里的栗子中是app
文件夹:
gulp.task('browserSync', function() {
browserSync.init({
server: {
baseDir: 'app'
},
})
})
- 第三步:同时我们需要对我们的
sass
任务做一点小小的改变,使得Browser Sync可以在sass
任务完成时向浏览器注入新的CSS样式(更新CSS)。
gulp.task('sass', function() {
return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
.pipe(sass())
.pipe(gulp.dest('app/css'))
.pipe(browserSync.reload({
stream: true
}))
});
到这里,我们就配置好Browser Sync了。现在我们需要同时运行watch
和browserSync
任务来做到实时重载。
如果我们要打开两个命令行窗口来分别运行gulp browserSync
和 gulp watch
这会十分笨重,所以我们要让Gulp同时运行它们,通过告诉watch
任务browserSync
必须在watch
运行前完成。
可以通过给watch
任务添加第二个参数来实现上述要求。
gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
// ...
})
在这个栗子中,我们会添加browerSync任务。
gulp.task('watch', ['browserSync'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Other watchers
})
同时,我们也要保证sass
在watch
前运行,以保证CSS在我们运行Gulp命令时都是最新的。
gulp.task('watch', ['browserSync', 'sass'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Other watchers
});
现在,当在命令行运行了gulp watch
,Gulp会马上启动sass
和'browserSync'。当两个任务都完成时,watch
才会运行。同时会打开app/index.html
。
如果你改变了styles.scss
文件,你会看到浏览器自动的重载。
既然我们已经监视了.scss
文件重载,接下来我们看看怎么在HTML或JS文件被保存的时候重载浏览器。
可以通过添加两个监听程序,并在文件被保存的时候调用browserSync.reload方法。
gulp.task('watch', ['browserSync', 'sass'], function (){
gulp.watch('app/scss/**/*.scss', ['sass']);
// Reloads the browser whenever HTML or JS files change
gulp.watch('app/*.html', browserSync.reload);
gulp.watch('app/js/**/*.js', browserSync.reload); });
目前我们已经解决了三件事情:
- 为开发旋转加速web服务器
- 使用Sass预处理器
- 在文件被保存时重载浏览器
接下来会处理优化资源的部分。首先冲优化CSS和JS文件开始。
优化CSS和JS文件
在为产品优化CSS和JS文件的时候,开发人员通常有两个任务要完成:缩小(minification)和串联(concatenation)。
- 其中一个开发人员面临的问题就是,在使程序自动化的时候很难把你的脚本按正确的顺序串联。
假设index.html
中包含3个