【译】用gulp来实现web服务器

最近在研究gulp,npm里的文档有些过于简洁,并看不出来到底每一步操作是为什么,api到底是做什么用。
于是各种查资料,看到一篇英文版的,说的不错,趁着周末翻译过来,以备我自己以后想看不用再翻译一遍,也可以造福下正好看到这篇文章的同学。

点这里查看原文


gulp现在是越来越流行了。它可以做的事情实在是太多了,比如,拼接js文件,压缩图片。如果你是一个gulp.js的新手,建议从这篇文章开始入门吧!

在这个教程里,你会了解怎么使用gulp.js来实现一个应用了内置的livereload功能的本地web服务。

以前的实现方式

假设我们要开发一个单页应用。这个app的入口是index.html。我们的目标是可以让浏览器通过localhost来访问这个页面。以前,你需要安装一个Apache或者Nginx这样的服务器软件来实现这样的功能。

更棒的实现方式

时至今日,javascript无所不能了,就要称霸天下了,甚至它都可以去实现一个web服务。这篇文章里,我们就要用一个gulp的插件,人称gulp-connect。用这个插件来实现一个WEB服务。

接下来的篇幅,我们就要来为我们的单页应用来配置一个本地服务。

开始下文之前,我假定你已经把准备工作都已经做好了,比如gulpfile文件已建好!

第一步,安装

第一步,我们要来安装下gulp-connect插件
安装的命令如下:

npm install --save-dev gulp-connect

小提示:npm install --save-dev 可以简写为npm i -D

现在,我们来定义web服务,gulpfile.js的代码如下

var gulp = require('gulp'),
connect = require('gulp-connect');

gulp.task('webserver',function(){
    connect.server();
})

gulp.task('default',['webserver']);

只要在终端执行gulp命令,然后在浏览器地址栏输入localhost:8080就可以看到index.html啦。
localhost:8080所指向的就是gulpfile文件所在的那一级目录。
在终端输入ctrl+c会结束当前任务。

在github可以找到本文所有例子的源码。
点这里看github

加入livereload的支持

创建一个基础的web服务很简单,是不是?那现在我们继续来把livereload加入web服务中。
我们需要做两件事情:
首先,告诉web服务启动的时候运行livereload。
其次,在页面有更新的时候通知livereload刷新页面。

第一步很简单是不是,我们只要将livereload的属性设置为true,将webserver这个任务写成下面的样子。

gulp.task('webtask',function(){
    connect.server({
        livereload:true
    });
});

第二步的话就取决于你具体的实例了。比如说,我们要将less文件自动编译成css样式表,并让其被浏览器识别。
我们来将这个例子分步处理下:
首先,需要一个'watcher',用来监控less文件的变化,监控到变化后这个'watcher'就会去触发less的编译器,将其输出为一个css文件。之后这个css文件有更新了之后就会去通知livereload,让其刷新页面。

在这个例子里面,还需要用到gulp-less插件。
插件的安装命令如下

npm install --save-dev gulp-less

gulp里已经有了watch这个方法,可以来充当'watcher'

我们的文档结构大致可以如下:
.
├── node_modules
│ └── ...
├── styles
│ └── main.less
├── gulpfile.js
├── index.html
└── package.json

watch任务执行的时候,gulp.js监听styles文件夹里less文件的所有改动,当有改动的时候就会触发less任务。每一次编译之后,结果会自动返回给浏览器。
gulpfile.js文件的代码如下所示(作者允许将下列代码使用于你自己的项目):

var gulp = require('gulp'),
connect = require('gulp-connect'),
less = require('gulp-less');

gulp.task('webserver',function(){
    connect.server({
        livereload:true
    });
});

gulp.task('less',function(){
    gulp.src('styles/main.less')
    .pipe(less())
    .pipe(gulp.dest(styles))
    .pipe(connect.reload());
});

gulp.task('watch',function(){
    gulp.watch('style/*.less',['less']);
})

gulp.task('default',['less','webserver','watch']);

现在我们重新在终端执行gulp,然后再在浏览器打开localhost:8080。
做完这些,我们就可以试着在style文件夹的less文件里做一些改动。它会立即编译并刷新浏览器。
看吧,这样我们并不需要依赖什么浏览器插件,就可以实现页面的自动刷新啦!

一些小小调整

注意,我们之前写的gulpfile.js文件只是一个小小的示例用于示范怎么来实现一个运用了livereload的web服务。
我非常建议大家可以把将其他gulp插件一起玩起来。
你也可以试着重新修改下你写的各个task的结构,用一用不是gulp内置的watch方法,这个方法可以只监控有改动的文件。这个对于以后你如果使用更大的代码库来说尤为重要。

本教程的接下来部分,我们来看一看对于以上实现web服务的另一个方案。

更换Hostname和Port

gulp-connect插件本身有很多可选的配置。
比如说,你可以更改web服务的端口号或者hostname。你甚至可以用一个你习惯使用的hostname配上80端口(默认的是localhost:8080)
代码如下:

connect.server({
    port:80,
    host:'gulp.dev'
});

进行了这个配置之后,我们要在hosts文件里面加上gulp.dev,然后运行sudo gulp,因为要使用80端口的话,是需要管理员权限的。

一些进阶特性

你可以同时启动多个web server。这个很有用的。比如说,如果你要同时启动一个开发和一个测试的服务。

gulp-connect也可以设置多个根目录。
比如,你要用coffeescript,然后将压缩过得js文件放到一个临时的文件夹,那就可以在根目录root中加上这个临时的文件夹而不去影响原来的源文件夹。

在GitHub上你可以获得更多的示例,链接如下:
https://github.com/AveVlad/gulp-connect

重构我们的代码

在以上的例子中,我们只是写了一个小小的将less编译成css文件,并让其立即体现在浏览器中的例子。
虽然它奏效了,但是我们可以做的更好。
当把编译和livereload混合起来用的时候,可能会有一些问题。
所以,我们将他们拆分开来并用watch来监控。
为此,就需要用到上面提到的gulp-watch插件。

我们可以再加入一个coffeeScript的编译步骤。这个增加的步骤会使我们的新结构更加清晰。

安装新插件的命令

npm install --save-dev gulp-watch gulp-coffee

在gulpfile.js文件的最顶部引用这两个插件。在下面的步骤中,我假设你已经在scripts文件夹里有了以.coffee为后缀的文件。
重写的gulpfile文件,如下所示:

var gulp = require('gulp'),
connect = require('gulp-connect'),
watch = require('gulp-watch'),
coffee = require('gulp-coffee'),
less = require('gulp-less');

gulp.task('webserver',function(){
    connect.server({
        live reload:true,
        root:['.','.tmp']
    });
});

gulp.task('livereload',function(){
    gulp.src(['.tmp/styles/*.css','.tmp/scripts/*.js'])
    .pipe(watch()) //注意此处的watch是gulp-watch插件
    .pipe(connect.reload());
});

gulp.task('coffee',function(){
    gulp.src('scripts/*.coffee')
    .pipe(coffee())
    .pipe(dest('.tmp/scripts'));
});
gulp.task('less',function(){
    gulp.src('styles/main.less')
    .pipe(less())
    .pipe(gulp.dest('.tmp/styles'));
});

gulp.task('watch',function(){
    gulp.watch('style/*.less',['less']);
    gulp.watch('scripts/*.coffee',['coffee']);
})

gulp.task('default',['less','coffee','watch','webserver','livereload']);

最大的变化,是增加的livereload任务。这个任务仅仅是监听了编译之后的文件,然后如果有变化就刷新浏览器。watch()方法可以仅仅只重新加载有变化的文件。gulp自带的gulp.watch()会将整个项目都重新加载。
因为添加了livereload这个任务,我们就不需要在每一步的编译之后都加上.pipe(connect.reload())了。所以,我们把每个任务按照他们各自关注的点分开定义,这样对于项目开发来说比较好。
同时,我们也发现,编译之后的文件不再保存至他们各自的文件夹去了。现在它们存储在一个临时文件夹.tmp中。文件夹的内容就是生成的文件,它们存储在临时文件夹,不再去污染scripts和styles文件夹。我们也建议不要将临时文件夹加入版本控制系统。
我们要做的就是把临时文件夹也视为一个根目录
代码如下

root:['.','.tmp']

这边经过我的测试,经过编译之后会自动生成.tmp文件夹,这个文件夹里有一个styles文件夹存储css文件有一个scripts文件夹存储js文件。然后我们的版本控制系统是git,那么在.gitignore文件里就要写上.tmp,不要让.tmp这个临时文件夹加入版本控制系统。因为在本地预览,这样html就得要能获取到css和js文件,那么就在root里把.tmp也设置为根目录。这样gulp执行的时候,就能读取到css和js文件啦~
提交git的话,就提交html,styles folder,scripts folder.
协同开发者如果clone的话,再执行下gulp就会再次生成临时文件夹,进行预览。

总结

现在,你已经可以用gulp来构建一个本地web服务了。
你也可以尝试和其他gulp插件配合使用,来构建或者测试一个单页应用。
这里的web服务仅仅是本地服务,如果你要作为生产,就得要用一些类似Nginx或者CDN这样的高效解决方案。

Grunt及类似的项目都可以实现以上的功能,gulp只是提供了一个比较简便的方法来实现这个功能。

译文带着我自己的实践与想法,如果有翻译的不对或者不好的地方,希望大家多多指教~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容

  • gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学...
    依依玖玥阅读 3,146评论 7 55
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,419评论 1 32
  • 前言 本文默认你已经安装好node环境,并且熟悉node命令,和window cd命令。 gulp简介 基于nod...
    9I阅读 1,969评论 4 50
  • 1、gulp的安装 首先确保你已经正确安装了nodejs环境。然后以全局方式安装gulp: npm install...
    F_imok阅读 2,342评论 1 11
  • gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简单,学...
    井皮皮阅读 1,289评论 0 10