Mastering PhoneGap Mobile Application Development
上QQ阅读APP看书,第一时间看更新

Integrating Sass with Gulp

Before we use Sass, we need to install it in our project and then add some additional code to gulpfile.js. Thankfully, all the steps are fairly simple. The steps are as follows:

  1. Install a version of Sass that Gulp can use by executing the following command:
    $ npm install --save-dev gulp-sass@2.0.4
    
  2. Next, modify gulp/config.js to define where our SCSS files live, and where the output should be placed:
    assets: {
        copy: […],
        code: {…},
        styles: {src:  "www/scss/app.scss",  
                 dest: "www/css"}
    }
  3. Now, create gulp/tasks/copy-scss.js:
    var gulp = require("gulp"),
        sass = require("gulp-sass"),
        notify = require("gulp-notify"),
        sourcemaps = require("gulp-sourcemaps"),
        gutil = require("gulp-util"),
        config = require("../config"),
        settings = require("../settings"),
        paths = require("../utils/paths");
    
    function copySCSS() {
      var isRelease = (settings.BUILD_MODE === "release");
      var includePaths = []; // [1]
      var includeModules = config.sass &&
            config.sass.includeModules;
      if (includeModules instanceof Array) {
        includePaths = includePaths.concat(
          includeModules.map(function(moduleName) {
            var module = require(moduleName);
            return module.includePath;
          }));
      }
      var moreIncludePaths = config.sass && 
          config.sass.includePaths;
      if (moreIncludePaths instanceof Array) {
        includePaths = includePaths.concat(moreIncludePaths);
      }
      return gulp.src(paths.makeFullPath(
                      config.assets.styles.src, 
                      paths.SRC)) //[2]
        .pipe(isRelease?gutil.noop():sourcemaps.init()) //[3]
        .pipe(sass({
          includePaths: includePaths, //[4]
          outputStyle: (isRelease?"compressed":"nested") //[5]
        }))
        .on("error", function(error) {
          this.emit("end");
        })
        .on("error", notify.onError(function(error) {
          return "SASS: " + error.message;
        }))
        .pipe(isRelease?gutil.noop():sourcemaps.write()) //[3]
        .pipe(gulp.dest(paths.makeFullPath(
              config.assets.styles.dest, paths.DEST)));
    }
    module.exports = {
      task: copySCSS
    }

This should look somewhat familiar—there are several lines in here that are pretty close to the copy-code.js task we worked on in the previous chapter. That said, let's go over a few of the details:

  • Near the beginning of the file ([1]), we check our configuration file to see whether there are any directories we want Sass to search through while executing @import. We can either specify these paths in sass.includePaths as an array, or we can specify various npm modules that have exposed includePath by listing them in the sass.includeModules array. We'll go over an example of this shortly. These paths are actually utilized in [3].
  • Notice that we only passed one file to gulp.src() ([4]). Just like babelify in the previous chapter, we only need to pass the top-level Sass file. Sass will discover the other files it needs to process based on the imports contained within the top-level file. Then, we'll only need to include one style sheet in our index.html file. That said, if you want to process multiple Sass files, nothing will stop you from including multiple files.
  • Like in the prior chapter, we will only render source maps if we're not building for production ([3]). Having source maps is extremely useful for debugging, but they take up space, which we don't need to pass on to the user.
  • outputStyle is compressed when we are building in the release mode ([5]). The resulting output is not intended to be human-readable, but the browser still understands it just fine. This helps in saving some space on the end user's device.

Before we can actually use this method, we need to modify the gulp/tasks/copy task to look as follows :

module.exports = {
  deps: ["copy-assets", "copy-scss", "copy-code"]
}

At this point, we can execute gulp copy and it will process app.scss in the src/www/scss/ folder. When it is finished, there will be an app.css file in build/www/css/. At this point, you can modify src/www/index.html to include the style sheet by adding the following line to the head section:

<link rel="stylesheet" type="text/css "href="./css/app.css">

Including the Stylesheets installed via npm

npm isn't solely for JavaScript—there are several modules that include the Sass stylesheets that we can utilize. Let's use a stylesheet "reset" (which clears out the various styles that browsers apply to the various elements) as a simple example. This "reset" is useful for obtaining visual consistency across different browsers and rendering engines, since different browsers may have different default styling for elements.

Note

Note: You may prefer normalizing element styles rather than clearing them. If that's the case, take a look at https://www.npmjs.com/package/normalize-scss.

First, execute the following command:

$ npm install --save node-reset-scss@1.0.1

Next, let's add the following object to gulp/config.js:

"sass": {
  "includeModules": [
    "node-reset-scss"
  ]
}

At this point, we can use @import "reset"; at the top of our Sass file. If we didn't use includePaths in our Gulp configuration, we would need to use @import "../../../node_modules/node-reset-scss/scss/reset";. Personally, I'll take the former—it's a lot easier to type!

There's no guarantee that a module will expose the location of its style sheets via includePath, though. If it doesn't, we can specify the path directly, as follows:

"sass": {
  "includePaths": [
    "./node_modules/node-reset-scss/scss"
  ]
}