gulp创建项目

原文地址:https://css-tricks.com/gulp-for-beginners/
原文代码:https://github.com/zellwk/gulp-starter-csstricks

Gulp是一个在你开发web时,帮助你完成几个任务的工具。它经常用来进行一些前端任务,比如:

  • 生成一个Web服务器

  • 当一个文件保存时,浏览器自动刷新

  • 编译像Sass或者LESS一样的预处理器

  • 优化资源文件,像CSS,JavaScript和图片等

这些并不是Gulp的全部功能。如果你足够疯狂,你甚至可以使用Gulp创造一个静态页面生成器(我已经做到了!)。所以,Gulp是非常强大的,但是如果你想创建你自己的构建流程,你就要去学习如何使用Gulp。

所以这就是这篇文章所要做的。它将帮助你入门Gulp,你就可以自己探索其他任何东西。

我们要配置什么

在看完这篇文章后,你将拥有一个工作流,来进行我们文章开始所说的一些任务:

生成一个Web服务器
当一个文件保存时,浏览器自动刷新
编译像Sass或者LESS一样的预处理器
优化资源文件,像CSS,JavaScript和图片等
你也将学习如何使用容易理解和执行的命令行,将不同的任务捆绑在一起。

安装Gulp

在你安装Gulp之前,需要安装Node.js(Node)环境。
如果你没有安装,你可以在这个网页来获取安装包
当你安装好Node后,你可以通过使用下列命令行来安装Gulp(全局安装)

$sudo npm install gulp -g

提示:只有Mac用户需要sudo
-g标志代表这个安装时全局安装到你的电脑上,这就运行你在电脑的任何地方都能使用gulp
Mac用户需要额外的sudo,因为他们需要管理员权限来全局安装Gulp
现在你已经安装好了Gulp,让我们使用Gulp来创建一个项目吧。

创建一个Gulp项目

1.我们要创建一个叫project文件夹作为我们的根目录。
2.在目录里运行npm init命令行来初始化项目。

npm init命令行创建一个package.json文件,用来保存关于项目的信息,比如一些在项目中使用的依赖(Gulp就是一个依赖)。
npm init将提示你:

npm-init

3.一旦package.json文件创建后,我们可以使用下面命令行,在项目中安装Gulp

$npm install gulp --save-dev

这时候,我们就将Gulp安装到项目里了,而不是全局安装,这就是为什么命令行有些不一样。
你将会看到在这里不需要sudo,因为我们没有全局安装Gulp,所以-g也是不需要的。我们增加--save-dev,来告诉计算机增加gulppackage.jsondev依赖

package-json.png

如果你查看项目文件夹,在命令执行结束,你应该能看到Gulpnode_modules文件夹里。

node-modules.png

决定项目文件夹结构

Gulp对于很多文件夹结构都可以足够灵活的使用。在对项目结构进行调整之前,你只需要理解内部工作原理。
对于这篇文章,我们将使用以下结构来构建项目:

|- app/
-----|- css/
-----|- fonts/
-----|- images/
-----|- index.html
-----|- js/
-----|- scss/
|- dist/
|- gulpfile.js
|- node_modules/
|- package.json

在这个结构里,我们将使用app文件夹用于开发目的,当dist文件夹内包括了优化后的文件,用于生产时候的页面。
自从app被用来开发目的后,我们所有的代码都要放到app文件夹中。
我们将不得不保持目录结构当我们运行我们的Glup配置。现在,让我们开始在gulpfile.js中,创建我们第一个Gulp任务。

编写你的第一个Gulp任务

第一步是在gulpfile中requireGulp

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

为了测试它,让我们创建一个hello任务,来说Hello Zell!

gulp.task('hello', function(){
    console.log('Hello Zell!');
});

我们可以在命令行中通过gulp hello来运行这个任务

$gulp hello

命令行将会返回一个日志,打印出Hello Zell!

hello.png

Gulp任务通常要比这个复杂一点。它通常包括两个附加的Gulp时间,加上各种各样的Gulp插件。
这儿是一个真实任务的样子

gulp.task('task-name',function(){
    return gulp.src('source-files')
        .pipe(aGulpPlugin())
        .pipe(gulp.dest('destination'))
});

正如你能看到的,一个真实的任务有两个额外的事件gulp.srcgulp.destgulp.src告诉Gulp任务,所要使用的文件。gulp.dest告知当任务完成后,Gulp输出文件的地址。
让我们来尝试构造一个真实的任务,将Sass文件编译成CSS文件。

Gulp预处理

Gulp中,我们可以将Sass编译成CSS,使用一个叫做
gulp-sass的插件。你可以安装gulp-sass到你的项目中,通过使用以下命令

$ npm install gulp-sass --save-dev

在我们使用插件之前,我们需要从node_moudles文件夹中require gulp-sass,就像我们引入gulp一样

var gulp = require('gulp');
// Requires the gulp-sass plugin
var sass = require('gulp-sass');

我们可以使用gulp-sass通过将aGulpPlugin()替换成sass(),因为任务用来将Sass编译成CSS,所以让我们将他命名为'sass'

gulp.task('sass', function(){
    return gulp.src('source-files')
        .pipe(sass())
        .pipe(gulp.dest('destination'));
});

我们想测试sass任务是否能像我们预想的工作。我们可以在styules.scss中增加一个Sass函数

.testing{
    width:percentage(5/7);
}

如果你在命令行中运行gulp sass,你应该就能看到app/css中会有一个styles.css文件被创建。此外,它代码中的percentage(5/7)被计算出来了71.42857%

/* styles.css */
.testing{
    width: 71.42857%;
}

我们知道了sass任务是如何工作。
有时我们需要能够编译多个.scss文件成CSS文件。我们可以在Node globs的帮助下完成(globs参数是文件匹配模式,类似正则表达式,用来匹配文件路径包括文件名)。

供参考:Gulp-sass使用LibSass来将Sass转换成CSS。这比基于Ruby的方法要快。如果你希望Ruby方法,你也可以使用gulp-ruby-sass或者
gulp-compass插件来代替。

Node的Globbing

Globs是匹配文件模式,允许你在gulp.src中增加多个文件。它就像正则表达式一样,但是只用来表示文件路径。
当你使用glob,计算机检查文件名和路径以特定的特征。如果特征存在,文件就会被匹配。
大部分Gulp工作流倾向于只要求4个不同的匹配模式。

  1. *.scss : * 特征是一个通配符,用来匹配当前路径中的一些特征文件。倘若这样,我们将匹配根路径下,所有以.scss为后缀名的文件
    2.**/*.scss:这是一个更极端版本的*特征,匹配在根路径和一些子路径的以.scss结尾的文件
    3.!not-me.scss : !表明,Gulp应该排除这个匹配的特征,当你要在匹配的文件中,排除一个文件,是非常有用的。倘若这样,not-me.scss将被排除出匹配。
    4.*.+(scss|sass) : 加号+和括号()允许Gulp匹配大量的特征,不同的特征使用|分隔开。倘若这样,Gulp将匹配根目录下所有以.scss或者.sass结尾的文件。

在我们现在知道glob之后,我们可以将app/scss/styles.scss替换成scss/**/*.scss,这样可以匹配app/scss或者子路径下的.scss文件。

gulp.task('sass', function(){
    return gulp.src('app/scss/**/*.scss)
        .pipe(sass())
        .pipe(gulp.dest('app/css'))
})

其他在app/scss文件夹下找到的Sass文件,将自动被包括到sass任务中。如果你增加一个print.scss文件到项目中,你将看到print.css被创建到app/css

second-stylesheet.png

我们现在可以通过一个命令,管理所有Sass文件编译成CSS文件。但是问题是,有什么可以让我们不用每次都手动运行gulp sass,将Sass编译成CSS

监视Sass文件更改

Gulp提供我们一个watch方法,监视是否有文件更改。watch文件的语法是:

//Gulp watch syntax
gulp.watch('files-to-watch',['tasks','to','run']);

如果我们希望监视多个Sass文件以及运行sass任务,当一个Sass文件被保存,我们只要将files-to-watch替换成app/scss/**/*.scss,将['task','to','run']替换成[sass]:

//Gulp watch syntax
gulp.watch('app/scss/**/*.scss',['sass']);

虽然更多时候,我们希望同时监视多种类型文件。为了实现,我们可以将多个监视进程加入到一个组里,放到一个watch任务:

gulp.task('watch',function(){
    gulp.watch('app/scss/**/*.scss',['sass']);
    //other watchers
});

如果你在命令行中运行gulp watch,你将立即看到看Gulp的监视。

gulp-watch-start.png

它将自动运行sass任务,当你保存一个.scss文件。
watch-compile.gif

让我们来进行下一步,以及让Gulp重新加载浏览器,当我们保存一个.scss文件,通过Browser Sync

Browser Sync的实时加载

Browser Sync使开发Web更加容易,通过创建一个Web服务器,帮助我们更容易的实时加载。它有其他的特性,比如跨多设备同步操作

我们首先要安装Browser Sync:

$ npm install browser-sync --save-dev

你或许会注意到,当我们安装Browser Sync时,没有gulp-前缀。这是因为Browser SyncGulp兼容,所以我们不需要用到插件。
要使用Browser Sync,我们要requireBrowser 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能够注入新的CSS样式(更新CSS)到浏览器,当sass任务运行时。

gulp.task('sass',function(){
    return gulp.src('app/scss/**/*.scss')
        .pipe(sass())
        .pipe(gulp.dest('app/css'))
        .pipe(browserSync.reload({
            stream: true
        }))
});

我们已经配置好了Browser Sync。现在,我们需要同时运行watchbrowserSync任务来进行实时加载。
这个将要笨重的打开两个命令行窗口以及独立运行gulp browserSyncgulp watch,所以,让我们使用Gulp来让他们一起运行,通过告知watch任务,browserSync必须在watch之前完成,watch才能运行。
我们能做到,通过给watch任务添加第二参数。语法如下:

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
  // ...
})

在这种情况下,我们添加了browserSync任务。

gulp.task('watch',['browserSync'],function(){
    gulp.watch('apjp/scss/**/*.scss',['sass']);
    //other watchers
}

现在,如果你在命令行中运行gulp watch,Gulp会同时开启sassbrowserSync任务。当两个任务都完成后,watch将会运行

bs-watch.png

同时,一个显示app/index.html文件的浏览器窗口也将突然弹出。如果你改变了styles.scss文件,你将会看到浏览器自动刷新效果。

bs-change-bg.gif

在我们结束这个实时更新小节之前,还有一个件事情。既然我们已经监视了.scss文件,并重新加载,为什么不更进一步,当HTML文件和JavaScript文件保存后,重新加载浏览器呢?
我们可以通过增加两个监视进程,以及当一个文件保存后,唤起browserSync.reload函数。

gulp.task('watch',['browserSync','sass'], function(){
    gulp.watch('app/scss/**/*.scss',['sass']);
    //Reloads the browser whenever HTML or JS files changes
    gulp.watch('app/*.html',browserSync.reload);
    gulp.watch('app/js/**/*.js', browserSync.reload);
});

到目前为止,在这个教程中,我们已经处理了三件事:

1.创建一个开发用的WEB服务器
2.使用Sass编译器
3.当文件改变后,自动重新加载浏览器

让我们进入下一届,讨论优化资源文件的部分。我们将从优化CSS和JavaScript文件开始。

优化CSS和JavaScript文件

当我们尝试优化CSS和JavaScript文件给生产使用,开发者有两个任务来执行:压缩和串联。

开发者面对一个问题是,当自动化运行这个进程时,很难将你的脚本串联成正确的顺序。

比如说我们在index.html有三个脚本标签

<body>
    <script src="js/lib/a-library.js"></script>
    <script src="js/lib/another-library.js"></script>
    <script src="js/main.js"></script>
</body>

这些脚本在两个不同的路径。这将很难使用传统的插件(比如gulp-concatenate)来链接他们。

很感激,这儿有一个有用的Gulp插件,gulp-useref解决了这个问题。
Gulp-useref 连接一定数量的CSSJavaScript文件在一个单独的文件里,通过寻找一个注释,以“”.他的语法是:

<!-- build:<type> <path> -->
<!-- endbuild -->

<type>可以为js,css或者remove。最好设置type为你试图连接的文件的类型。如果你设置typeremove,Gulp将移除整个构件块,而不生成文件。
<path>指的是生成文件的目标地址。
我们希望最终生成的js文件在js文件夹,名为main.min.js因此标记应为:

<!-- build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->

现在让我们在gulpfile中配置gulp-useref插件。我们将安装这个插件,然后在gulpfile中引入它。

$ npm install gulp-useref --save-dev
var useref = require('gulp-useref');

设置useref任务和我们到目前为止设置的其他任务相似。这儿是代码:

gulp.task('useref',function(){
    return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulp.dest('dist'))
});

现在如果你运行这个useref任务,Gulp将贯穿三个脚本标签,以及连接他们到dist/js/main.min.js

main-min.png

但是这个文件现在并没有被压缩。我们将使用gulp-uglify插件,来压缩JavaScript文件。
我们也需要另一个插件,叫gulp-if,但是我们只能试图去压缩JavaScript文件。

$ npm install gulp-uglify --save-dev
var uglify = require('gulp-uglify');
var gulpIf = require('gulp-if');

gulp.task('useref', function(){
    return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulpIf('*.js',uglify()))
        .pipe(gulp.dest('dist')
});

Gulp现在应该自动压缩main.min.js文件,当你运行useref任务。
还有一件有关Gulp-useref的使没有透露,就是它自动改变所有在 ""中的标签成'js/main.min.js'.

useref-html.png

很棒是不是!
我们可以使用相同的方法来连接CSS文件(如果你打算增加多个)。我们将遵循相同的进程以及增加一个build注释。

<!--build:css css/styles.min.css-->
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/another-stylesheet.css">
<!--endbuild-->

我们也要压缩连接后的CSS文件。我们需要使用一个叫做gulp-cssnano的插件来帮助我们压缩。

$ npm install gulp-cssnano --save-dev
var cssnano = require('gulp-cssnano');
gulp.task('useref',function(){
    return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulpIf('*.js',uglify()))
        .pipe(gulpIf('*.css',cssnano()))
        .pipe(gulp.dest('dist'))
});

现在当你运行useref任务,你将得到一个优化后的CSS文件以及一个优化后的JavaScript文件。
让我们继续来优化图片。

优化图片

你可能已经猜到了;我们需要使用gulp-imagemin来帮助我们压缩图片

$ npm install gulp-imagemin --save-dev
var imagemin = require('gulp-imagemin');

通过gulp-imagemin的帮助,我们能压缩png,jpg,gif甚至使svg。让我们创建一个images任务来完成这个压缩进程。

gulp.task('images',function(){
    return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
        .pipe(imagemin())
        .pipe(gulp.dest('dist/iamges'))
}

由于不同文件类型要使用不同的方式压缩,你或许要在imagemin中增加选项,来自定义如何压缩文件。
比如你可以通过设置interlaced
选项为true,来创建 interlacedGIFs

gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  .pipe(imagemin({
      // Setting interlaced to true
      interlaced: true
    }))
  .pipe(gulp.dest('dist/images'))
});

你可以玩玩其他选项,如果你希望的话。
压缩图片,是一个极其缓慢的进程,除非必要,你是不会想重复的。为了做好这个,我们可以使用gulp-cache插件。

$ npm install gulp-cache --save-dev
var cache = require('gulp-cache');

gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  // Caching images that ran through imagemin
  .pipe(cache(imagemin({
      interlaced: true
    })))
  .pipe(gulp.dest('dist/images'))
});

我们几乎完成了优化进程。这儿有多个文件夹,我们需要从app文件夹编译到dist文件夹中,比如字体文件夹。让我们来做这件事。

将字体文件夹赋值到Dist文件夹

由于字体文件已经压缩了,所以我们不需要做额外的事。我们需要做的就是将字体复制到dist。
我们可以使用Gulp复制文件通过gulp.srcgulp.dest,不需要其他插件。

gulp.task('fonts', function() {
  return gulp.src('app/fonts/**/*')
  .pipe(gulp.dest('dist/fonts'))
})

现在当你运行gulp fonts,Gulp将会复制字体文件到dist中。

font-copy.png

现在我们有六个不同的任务在gulpfile中,以及他们每个都需要单独调用一个命令行,这是有点麻烦的,所以我们希望把所有都放到一个命令中。
在我们做那个之前,让我们来看看如何自动清理生成的文件。

自动清理生成的文件

由于我们自动生成文件,我们希望确定那些不再使用的文件不保留在我们不知道的地方
这个进程被叫做清理(或者用更简单的术语来说,删除文件)
我们将使用del帮助我们完成清理。

$ npm install del --save-dev
var del = require('del');

del函数接受一组node globs数组,告知那些文件夹需要删除。
Gulp任务中设置它就和我们第一个“hello”的示例一样

gulp.task('clean:dist',function(){
    return del.sync('dist');
})

现在当你运行gulp clean:dist时,Gulp将删除dist文件夹
提示:我们不必担心删除dist/images文件夹。因为gulp-cache已经存储了图片的缓存在你本地系统里。
要在你本地系统中删除缓存,你要创建一个单独的任务,叫做cache:clear

gulp.task('cache:clear',function(callback){
    return cache.clearAll(callback)
})

Phew, that's a mouthful(真绕口?)。现在让我们把所有任务都组合到一起吧。

组合Gulp任务

让我们总结一下我们做的吧。到目前为止,我们创建了两个不同Gulp任务集。
第一个任务集是一个开发进程,我们可以用它编译Sass到CSS,监视文件的修改,从而重新加载浏览器。
第二个任务集是压缩进程,我们为生产网站准备了所有文件。我们压缩资源文件,像CSS,JavaScript和图片在这个进程以及从app文件夹复制字体文件到dist文件夹。
我们已经将第一个任务集集合到一个简单的工作流,通过gulp watch命令:

gulp.task('watch',['browserSync','sass'], function(){
//...watchers
})

第二个任务集包括我们需要运行来生成生产用的网页的任务。这包括了
clean:dist,sass,useref,imagesfonts
如果我们有同样的思路,我们能创建一个build任务来联系所有。

gulp.task('build', ['clean:dist','sass','useref','images','fonts'], function(){
    console.log('building files');
})

不幸的是,我们这样构建build任务,因为这样会导致Gulp将第二个参数全部同时运行。
这可能会使useref,images或者甚至fontsclean之前运行完成,这就意味着,最后整个dist文件夹被删除。
所以要确定删除任务要在所有任务之前完成,我们需要使用一个额外的插件,叫做Run Sequence

$ npm install run-sequence --save-dev

这是一个使用run-sequence的任务队列的语法:

var runSequence = require('run-sequence');
gulp.task('task-name',function(callback){
    runSequence('task-one','task-two','task-three',callback);
});

task-name被唤起,Gulp将先运行task-one.当task-one结束后,Gulp将自动启动task-two.最后当task-two完成后,Gulp将运行task-three
Run Requence 也允许你同时运行任务,如果你把他们放在一个数组里:

gulp.task('task-name',function(callback){
    runSequence('task-one',['tasks','two','run','in','parallel'],'task-three',callback);
})

在这种情况下,Gulp第一个运行task-one.当task-one完成后,Gulp同时运行第二个参数里每个任务。第二个参数中所有任务运行完成后,task-three才能运行。
所以我们现在能创建一个任务,确定clean:dist第一个运行,然后其他任务运行:

gulp.task('build',function(callback){
    runSequence('clean:dist',['sass','useref','images','fonts'],
        callback
    );
});

为了保持事情的一致性,我们也构建相同的队列在第一组。让我们使用default作为任务名:

gulp.task('default',function(callback){
    runSequence(['sass','browserSync','watch'],
        callback
    );
})

为什么用default?因为当你有个任务叫default,你就可以很简单的使用
gulp命令运行,会省去键盘的敲击次数。。。
最后这里是一个Github repo,里面都是我们所做的工作。

结束

我们已经经过了Gulp的基础以及创建了一个工作流,可以将Sass编译成CSS,同时监测HTMLJS文件发生改变。我们可以在命令行通过gulp命令运行这个任务。
我们也构建了第二个任务,build,创建一个dist文件夹给生产用网页。我们编译SassCSS,压缩我们所有的资源文件以及复制必要的文件夹到dist文件夹。我们可以在命令行中运行gulp build来运行这个任务。
最后,我们有一个clean 任务,用来清理生成的dist文件夹和一些创建的图片缓存,允许我们移除一些没注意的留在dist文件夹里的旧的文件。
我们已经创建了一个强健的工作流,到目前为止,这个已经有足够能力来进行大多数WEB开发。这儿有一些Gulp和工作流,你可以探索来是这个进程更加完美。这里有一些资源:
For development:

For optimization:

  • Removing unused CSS with unCSS
  • Further optimizing CSS with CSSO
  • Generating inline CSS for performance with Critical

转自简书治电小白

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

推荐阅读更多精彩内容

  • 安装Gulp首先需要安装Node.js,并在控制台输入$ npm install gulp -gMac端需要写成$...
    LaBaby_阅读 906评论 0 1
  • 原文标题:Gulp for Beginners作者: Zell Liew翻译:治电小白菜原文地址:https://...
    ZZES_ZCDC阅读 1,570评论 6 18
  • 参照Gulp for Beginners来学习Gulp基本内容。以下为学习记录笔记。 安装Gulp 首先需要安装N...
    JenniferYe阅读 2,522评论 1 17
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,428评论 1 32
  • 觉得此文甚好,转发来自[http://w3ctrain.com/2015/12/22/gulp-for-begin...
    Tinazbh阅读 456评论 0 0