gulp 的使用(四):处理 css

这是我参与更文挑战的第17天,活动详情查看: 更文挑战

前言

在上一篇 gulp 的使用(三):处理 js 文章里介绍了 gulp 如何处理 html。

在这篇文章里将介绍 gulp 如何处理 css。

输出 css

我们在 src 目录里创建一个 css 目录,里面新建一个 index.css 文件,里面写上如下测试代码。

body {
  background: yellowgreen;
}
复制代码

src/index.html 引入 index.css。

...
<head>
  ...
  <link rel="stylesheet" href="./css/index.css">
</head>
...
复制代码

gulpfile.js 配置

function css() {
  return src(['src/css/**/*.css'])
    .pipe(changed('dist/css/**/'))
    .pipe(plumber())
    .pipe(dest('dist/css'))
}
function watcher() {
  ...
  watch('src/css/**/*.css', series(css)).on('unlink', function (path) {
    del('dist/css/**/*.css' + Path.basename(path))
  })
}

exports.default = series(clean, html, libJs, js, css, devServer, watcher)
exports.build = series(clean, html, libJs, js, css)
复制代码

运行 npm run build,可以发现 dist 目录有 css/index.css 目标文件。

压缩 css

gulp-clean-css 是一个用于压缩 css 的插件,接下来安装 gulp-clean-css。

安装

npm i -D gulp-clean-css
复制代码

gulpfile.js 配置

...

const cleanCss = require('gulp-clean-css')

...

function css() {
  return src(['src/css/**/*.css'])
    .pipe(changed('dist/css/**/'))
    .pipe(plumber())
    .pipe(cleanCss())
    .pipe(dest('dist/css'))
}

...
复制代码

我们打开 dist/css/index.css,可以看到里面的样式代码被压缩。

image.png

编译 scss

scss 是一种 css 预处理语言,现在都主流使用 scss 来写样式,下面介绍如何使用 gulp 插件编译 scss。

在 src 创建一个 scss 文件夹,里面新建一个 index.scss 文件,里面写上测试代码。

html {
  body {
    background: blanchedalmond;
  }
}
复制代码

index.html 里引入 scss 目录的 index.css,记得编译出来的文件是 css 文件。

<link rel="stylesheet" href="./scss/index.css">
复制代码

安装

npm i -D sass node-sass gulp-sass
复制代码

注意:这一块安装了 sass (dart sass)和 node-sass 两个编译器,在实际开发中,我们只用其中一个编译器就可以了,选择你自己喜欢的编译器,我建议选择 dart sass,因为 webpack 大佬也是这样推荐 (文章链接)。

image.png

不过尴尬的是 gulp-sass 插件推荐用 node-sass(文章链接),而且 node-sass 是默认的编译器…… ̄□ ̄||

image.png

在这里使用 dart sass 作为示例。

如果发现安装不了,建议用 cnpm 来安装这一块。

gulpfile.js

const sass = require('gulp-sass')
sass.compiler = require('sass')
//sass.compiler = require('node-sass') // 如果是选择 node-sass,这样写
...

function scss() {
  return src(['src/scss/**/*.scss'])
    .pipe(changed('dist/scss/**/'))
    .pipe(plumber())
    .pipe(sass())
    .pipe(cleanCss())
    .pipe(dest('dist/scss'))
}

...

function watcher() {
  ...
  watch('src/scss/**/*.scss', series(css)).on('unlink', function (path) {
    del('dist/scss/**/*.css' + Path.basename(path))
  })
}

exports.default = series(clean, html, libJs, js, css, scss, devServer, watcher)
exports.build = series(clean, html, libJs, js, css, scss)
复制代码

gulp-sass 的文档里有说到,如果使用 dart sass 编译器,则会存在一个问题,同步编译的速度是异步编译的速度的两倍,为了解决异步编译开销过大的问题,需要使用 fibers 包,从同步代码路径调用异步导入器(好吧,我是机翻  ̄□ ̄||,具体看下面原文)。

Note that when using Dart Sass, synchronous compilation is twice as fast as asynchronous compilation by default, due to the overhead of asynchronous callbacks. To avoid this overhead, you can use the fibers package to call asynchronous importers from the synchronous code path.

安装 fibers

npm i -D fibers
复制代码

同样地,如果 npm 安装不了,使用 cnpm 安装。

修改 gulpfile.js

const fiber = require('fibers') // 变量名命名没 s

...

function scss() {
  return src(['src/scss/**/*.scss'])
    .pipe(changed('dist/scss/**/'))
    .pipe(plumber())
    .pipe(sass({ fiber }))
    .pipe(cleanCss())
    .pipe(dest('dist/scss'))
}
复制代码

运行 npm run build,可以发现 dist/scss 多了一个 index.css 文件。

image.png

区分 css 开发源码和 css 库

和上一篇文章的 js 一样,我们有时候也会用到第三方的 css 库,因此需要区分 css 开发源码 和 css 库。

在 src 目录新建一个 libCss 目录,里面复制一个第三方样式 animate.min.css。

...

function libCss() {
  return src(['src/libCss/**/*.css'])
    .pipe(changed('dist/libCss/**/'))
    .pipe(plumber())
    .pipe(dest('dist/libCss'))
}

function watcher() {
  ...
  watch('src/libCss/**/*.css', series(css)).on('unlink', function (path) {
    del('dist/libCss/**/*.css' + Path.basename(path))
  })
}

exports.default = series(clean, html, libJs, js, css, scss, libCss, devServer, watcher)
exports.build = series(clean, html, libJs, js, css, scss, libCss)
复制代码

由于写法差不多,不再详细说明。

完整代码

目录

image.png

gulpfile.js

const { series, parallel, src, dest, watch } = require('gulp')

const Path = require('path')

const htmlmin = require('gulp-htmlmin')
const fileinclude = require('gulp-file-include')
const changed = require('gulp-changed')
const webserver = require('gulp-webserver')
const del = require('del')
const uglify = require('gulp-uglify')
const plumber = require('gulp-plumber')
const cleanCss = require('gulp-clean-css')
const sass = require('gulp-sass')
const fiber = require('fibers') // 变量名命名没 s

sass.compiler = require('sass')
//sass.compiler = require('node-sass')

function html() {
  return src(['src/**/*.html', '!src/include/**.html'])
    .pipe(changed('dist'))
    .pipe(plumber())
    .pipe(fileinclude({
      prefix: '@@', //引用符号
      basepath: './src/include', //引用文件路径
    }))
    .pipe(htmlmin({
      removeComments: true, //清除HTML注释
      collapseWhitespace: true, //压缩HTML
      collapseBooleanAttributes: true, //省略布尔属性的值 <input checked="true"/> ==> <input />
      removeEmptyAttributes: true, //删除所有空格作属性值 <input id="" /> ==> <input />
      removeScriptTypeAttributes: true, //删除<script>的type="text/javascript"
      removeStyleLinkTypeAttributes: true, //删除<style>和<link>的type="text/css"
      minifyJS: true, //压缩页面JS
      minifyCSS: true //压缩页面CSS
    }))
    .pipe(dest('dist'))
}

function js() {
  return src(['src/js/**/*.js'])
    .pipe(changed('dist/js/**/'))
    .pipe(plumber())
    .pipe(uglify())
    .pipe(dest('dist/js'))
}

function libJs() {
  return src(['src/lib/**/*.js'])
    .pipe(changed('dist/lib/**/'))
    .pipe(plumber())
    .pipe(dest('dist/lib'))
}

function css() {
  return src(['src/css/**/*.css'])
    .pipe(changed('dist/css/**/'))
    .pipe(plumber())
    .pipe(cleanCss())
    .pipe(dest('dist/css'))
}

function scss() {
  return src(['src/scss/**/*.scss'])
    .pipe(changed('dist/scss/**/'))
    .pipe(plumber())
    .pipe(sass({ fiber }))
    .pipe(cleanCss())
    .pipe(dest('dist/scss'))
}

function libCss() {
  return src(['src/libCss/**/*.css'])
    .pipe(changed('dist/libCss/**/'))
    .pipe(plumber())
    .pipe(dest('dist/libCss'))
}

function devServer() {
  return src('dist').pipe(webserver({
    port: 3000,
    livereload: true, // 是否实时加载
    // directoryListing: true, // 是否开启浏览目录
    // open: true, // 是否自动打开
    // proxies: [ // 代理,可以用来解决跨域问题
    //   {source: '/api', target: 'http://xxxx.com', options: {headers: {"Content-Type": 'application/x-www-form-urlencoded'}}}
    // ]
  }))
}

function watcher() {
  watch('src/**/*.html', series(html)).on('unlink', function (path) {
    del('dist/**/*.html' + Path.basename(path))
  })
  watch('src/js/**/*.js', series(js)).on('unlink', function (path) {
    del('dist/js/**/*.js' + Path.basename(path))
  })
  watch('src/lib/**/*.js', series(libJs)).on('unlink', function (path) {
    del('dist/lib/**/*.js' + Path.basename(path))
  })
  watch('src/css/**/*.css', series(css)).on('unlink', function (path) {
    del('dist/css/**/*.css' + Path.basename(path))
  })
  watch('src/scss/**/*.scss', series(css)).on('unlink', function (path) {
    del('dist/scss/**/*.css' + Path.basename(path))
  })
  watch('src/libCss/**/*.css', series(css)).on('unlink', function (path) {
    del('dist/libCss/**/*.css' + Path.basename(path))
  })
}

function clean() {
  return del('dist')
}

exports.default = series(clean, html, libJs, js, css, scss, libCss, devServer, watcher)
exports.build = series(clean, html, libJs, js, css, scss, libCss)
复制代码

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>首页</title>
  <link rel="stylesheet" href="./css/index.css">
  <link rel="stylesheet" href="./scss/index.css">
</head>
<body>
  @@include('./header.html', {"name": "hello")
  <div>首页内容</div>
  @@include('./footer.html')

  <script src="./js/index.js"></script>
</body>
</html>
复制代码

css/index.css

body {
  background: yellowgreen;
}
复制代码

scss/index.scss

html {
  body {
    background: blanchedalmond;
  }
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享