深入介绍

返回导航

This document aims to explain all mechanisms included in the project generated from this generator.

When you have a problem or want to understand why it's working, check this file to try to understand what's happening.

gulpfile.js

As the gulpfile was becoming enormous, we decided to split it up into several files inside the gulp directory. Now, the gulpfile does nothing more than loading all .js or .coffee files inside the gulp directory.

It only defines one task which is the default one which will be launched if you pass no arguments to the gulp command. It will be the clean task followed by the build.

gulp/conf.js

The conf module doesn't define any gulp tasks. It's there to define some global values used across multiple gulp files.

We don't abuse of global configurations as a respect of the Gulp main principal Code over configuration (and also because we're still a bit traumatized by Grunt) but still there is the need of some global values such as:

  • paths: main paths of the project such as src and .tmp.
  • wiredep: wiredep is used in several tasks and needs to be configured the same way in all tasks.
  • errorHandler: the main weakness of Gulp 3 is the error handler, we keep a centralized error handler implementation here.

gulp/inject.js

The inject task is intended to centralized all modifications on the index.html of your project in the development phase. As we propose today a complete system of injection of all your files, there is several steps to organize.

As we never want to modify a source file, the injected index.html is targeted inside the temporary folder. You could look there to check if the changes are ok.

The task is organized by preparing first all settings of the injections the making the changes in one Gulp stream at the end.

The 3 steps of injections are:

  • Inject styles: use of gulp-inject to list all the CSS files inside the head of the page.
  • Inject scripts: use of gulp-inject to list all the JS files inside the body of the page (below the app).
  • Wiredep: use of wiredep streams to add CSS and JS files of the Bower dependencies.

将注入内容排序

For the first 2 tasks of injection. When you use plain JS, the list is made by listing the src folder. When there are pre-processing, the transformations are launched before (the inject task depends on scripts and styles) and the injection are performed after by listing the tmp/serve folder.

As the script files has to be sorted in order to work. We use a magic script which analyze the content of files and order them following the Angular modules declaration. It's used at the end of the inject stream just before writing. Warning, this plugin requires to have the content of the files and fail if you use the {read: false} option from gulp.src.

填充 index.html

gulp-inject put the <script> and <link> tags insides comments starting by or and ending by ``.

wiredep put the <script> and <link> tags insides comments starting by or and ending by ``.

Don't put anything inside this comments in your sources because the inject task will override it without warning you.

gulp/scripts.js

The scripts task is launched at build, dev and test time and at the watch of any change on a script file. It's this task which will trigger a Browser Sync reload when needed.

不适用 JS 预处理器

When you don't have JS preprocessor, the scripts task goal is to pass the linter (ESLint) on your code.

使用 Coffee

This task will launch the CoffeeLint analyze and the Coffee compilation and put result files in the .tmp/serve folder.

使用 TypeScript

The scripts task has a dependency which is the installation of typings with the tsd:install gulp task. Once the typings ready, TSLint, TypeScript compilation and finally a concatenation of all JavaScript files produced in the right order are done.

tsd:install is located in the gulp/tsd.js which is created only when choosing TypeScript. It will automatically download typings files for the dependency found in Bower with a popular library TSD

使用 ES6

The scripts task changes a bit for ES6 to handle CommonJS modularization used by the ES6 preprocessors. The standard gulp stream is replaced by Webpack through its stream feature. It's Webpack which become responsible for compilation, sourcemap and linting.

As Webpack as a good watch feature, 2 tasks are produced: scripts and scripts:watch. In the second we delegates to Webpack the watching of the source script files.

gulp/styles.js

The styles task is launched at build, dev and test time and at the watch of any change on a style file. It's this task which will trigger a Browser Sync reload when needed.

This file exists only if you choose a style pre-processor.

注入

As all styles pre-processors handle themselves the inclusions of all dependency files, as an exception, the style task is part of the injection process.

Like in the gulp/inject.js, there is two kinds of injection, first, your files and the one from Bower dependencies. Still like in the standard injection, it's controlled by comments but this time in the format of the pre-processor: // bower:(scss|less|styl) -> // endbower & // injector -> // endinjector.

The injection is on step of the main Gulp stream for the styles. Once processed, the uniq file inside .tmp/serve will follow the standard injection process to be included in the index.html.

样式流

All transformations are made in a single stream. As it includes injection and pre-processing, it could be disturbing because there is no work files but this is the magic and power of Gulp! If you intend to debug or understanding the process, the better way is to comment one or several transformations of the stream to look at single step.

The stream by itself is composed of some very identifiable steps:

  • Injection with gulp-inject
  • Injection with Wiredep
  • Start of sourcemap
  • Style pre-processing with one of the one supported: Sass, Less or Stylus
  • Autoprefixer with gulp-autoprefixer
  • End of sourcemap
  • Writing files in .tmp/serve
  • Reloading files in Browser Sync if present

Ruby Sass

Ruby Sass (the original implementation) caused us some pains fitting in the process. The Gulp plugin is a bit "touchy" (it's not supporting Gulp sourcemap system for example) and the options are not the same as for node-sass.

In order to have the sourcemaps working, there is some exceptions. The main trick is to ask Ruby Sass to generate its own sourcemaps and then, load them with Gulp with $.sourcemaps.init({ loadMaps: true }) and continue the normal process.

gulp/markups.js

The generator handles template pre-processing even if there is no "examples" in the created project (only because it's a lot of work to maintain all versions).

When a HTML pre-processor is chosen, the markups task is inserted and works the same as styles and scripts one.

The transformation is handled by Consolidate the reference library which also handle template processing inside Express.

gulp/watch.js

You can use the watch task directly if you just want the pre-processing of your files to be triggered automatically but it's mainly used through Browser Sync with the server task.

The watch task is responsible for watching all the files of the project in order to relaunch all the processings needed.

标准 Gulp 监听

We intentionally kept using the official Gulp watch even if we know that it has some weakness (first file of a directory not seen for example). But we know that there is some external lib which can go further. We just want to keep things simple and hope to have the Gulp 4 release which will fix that.

监听回调

The most common use of the watch API is to list files and just indicate which tasks to launch on a change. To gain some performance we go further by using the function version which ables us to have a function called on every change. As we have an event object which describe the change, we can be more specific.

The use case is the need of the injection. Many changes will only be a change on an existing files. This needs to trigger the pre-processing but not the injection. On the oposite, when it's a file creation, we need to relaunch the injection which will trigger the pre-processing by dependency.

监听了什么文件

As you can imagine, there is one watch expression for each type of files which trigger the related task.

Two remarks could be made:

  • Root HTML files and the bower.json are watched to trigger the injection in order to react on modification in the index.html or an modification of the list of the dependencies.
  • All HTML modification trigger a Browser Sync, indeed, as Gulp is responsible to trigger Browser Sync reload, a template modification needs to trigger a reload even when there is no other processing to launch.

gulp/server.js

The generator ship a fully featured development server through the use of Browser Sync. Don't hesitate to look at its website to know more about all its features and options.

The serve task has as only goal to configure and launch it.

Browser Sync 配置

The base directories for Browser Sync are .tmp/serve and src with a priority for .tmp/serve. The processed version of a file has to be chosen over the source one.

As the bower_components folder is not located in any of the base paths, a special routes is added for this folder to be addressed by /bower_components.

The default Browser Sync port is 3000, if you ever need to change it, head over to the gulp/server.js file and add the port attribute to the server variable.
Example below :

browserSync.instance = browserSync.init({
    startPath: '/',
    server: server,
    browser: browser,
    port: 4000 // Add this line to change the default port
  });

Last configuration, the browser option is used to open the default browser to the root page.

Head over to Browser Sync list of options for the full list of available configurations for BrowserSync.

代理

Browser Sync is powered by an express server. The API allows us to inject any Express middleware. Behind comments, an example of use of http-proxy-middleware is prepared.

The middleware allows very simply to add a proxy which takes all requests to a specific context a redirect it to another server.

It allows to work very simply with a backend server without dealing with CORS configurations.

gulp/unit-test.js

The test task is targeted to launch a fully configured Karma / Jasmine / PhantomJS configuration.

Gulp 与 Karma 协作

Inside the Gulp file, there is not much as the most part of the Karma configuration stays in the karma.conf.js. The Gulp file mainly launch Karma through its Node API (gulp-karma is deprecated in profit of the Node API).

Our objective are to allow user to use Karma without Gulp if needed. Most of the times to be plugged inside an IDE.

As we wanted to keep some useful tools from the generator. It's from the Karma configuration file that some tools or configuration of the generator which are called.

karma.conf.js

The listFiles function at the start of the file use wiredep and the gulp/conf.js file to list the files of the project the same way the injection does. This way, the user should never has to change the file list in the Karma configuration.

Past that two Karma plugin are used:

gulp/e2e-tests.js

The protractor task is build on top of the gulp-protractor plugin which handles the downloading and the launching of an embedded Webdriver with Protractor.

With a dependency on the task serve:e2e which launch the server without opening a browser on it, the server is started and a dependency on the initialization of Webdriver, the protractor tests can be launched.

The protractor.conf.js are mainly default configurations.

gulp/build.js

Inside this files, there is several Gulp tasks to organize the whole optimization process of the application.

The main goal is to create a dist folder fully portable which behave exactly like the source version.

主进程

The main process is located in the html task. It contains the re-writing of the index.html, the concatenation and minifying of all files in one single Gulp stream.

As all files will be in the same stream, we use Gulp filters to filter a type of files to perform some transformation and remove the filter with the restore() method.

代码片段

One of the optimization is to mount all the partials or templates inside the script bundle in order to reduce the number of request at the loading. We do that in the partials task which use the gulp-angularTemplatecache plugin in order to transform the HTML files in valid JavaScript Angular desclaration.

The Gulp stream load the HTML files from the sources, minify the code HTML, apply the AngularTemplateCache transformation and put them in a .tmp/partials to be injected in the main process with the same gulp-inject plugin already used.

文本处理

gulp-useref is the backbone of the optimization process. Starting by the index.html it loads all the files using the `` comments.

It adds all the files in the Gulp stream which ables us to filter them and apply transformations (line .pipe(assets = $.useref.assets())).

It also perform the concatenation and rewrite the index.html pointing on the new file (line .pipe($.useref())).

To understand where the files are located and how to call the targeted files, you have to look at the comments (not the Gulp file), basically, the syntax is: ``.

More information on gulp-useref.

版本控制

Another great feature of the generator is to rename your optimized files with the hashcode of the content. It prevent all problems of client caches which prevent them to reload new version of the files. With the content hashcode, only the files which has changed will change names.

This feature is possible thanks to the gulp-rev which is used inside the main process. A second step gulp-revReplace is needed for the files to be renamed inside the new index.html created by Useref.

图片

Proposed as an advanced option, there is a task named images which can use gulp-imagemin to optimize your images before putting them in the dist folder.

It has been removed by default and put behind an advanced option because the NPM dependency is heavy and the image optimization slow so finally lots of people didn't want it anymore.

字体

Some Bower dependencies embed font files. To handle this particular case, there is fonts task which copies font files located by wiredep. This task only copy the in the dist/font directory.

As we can't keep the original relative path of the font with the CSS file which include it, there is the need of replacing the link. It's why you find with some options the use of gulp-replace inside the main process. But this solution is not generic and could need to be duplicate with the use of others dependencies than default ones.

其他

We don't know what files you'll have in the src folder. We only knows about some types we have specific rules to handle them.

The task other simply locate all the files which are not already processed in the src folder and copy at them at the same location in the dist folder in order to keep the same paths.

返回导航

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

推荐阅读更多精彩内容

  • **2014真题Directions:Read the following text. Choose the be...
    又是夜半惊坐起阅读 9,399评论 0 23
  • 函数和lambda表达式 函数声明 函数调用 默认参数 命名参数 可变数量的参数(Varargs)函数的参数(通常...
    熹哥阅读 508评论 0 0
  • 我不是第一个,当然也不是最后一个来到这里的人。 我不知道有多少人在这里书写独家记忆,多少人在这里被关注、被回应。 ...
    不着子阅读 225评论 0 0
  • 昨天本来是孩子上美育课程的时间,按照以往的惯例,早上吃完饭,去梳头,然后送她上课,然后外面吃小火锅。 结果吃完饭,...
    冠世墨玉yanzi阅读 171评论 6 0