原文zh.annas-archive.org/md5/2789AE2FE8CABD493B142B2A68E84610译者飞龙协议CC BY-NC-SA 4.0第十四章最终自动化和流程优化在这最后一章中我们将讨论在创建 CSS 代码过程中重复流程的最终自动化。有很多流程可以自动化但是意识到它是否可以做到以及使用的工具的知识是必不可少的。在本章中我们将专注于工具以及如何在 Gulp 任务运行器中实现自动化。在本章中我们将涵盖以下主题视网膜和移动设备上的图像如何识别未使用的 CSS如何压缩代码如何从页面列表中制作截图以便快速概览如何使用 Jade 模板的基础知识并将其编译到 Gulp 中Gulp在本书的开头我介绍了 Gulp 作为 SASS 的入门。但是仅仅使用 Gulp 来编译 SASS 可能是浪费时间的。在本章中我们将向 Gulp 添加更多任务这些任务可以作为前端开发人员使用并将帮助你优化你的代码。Jade 作为你的模板引擎在大型项目的情况下编写 HTML 文件可能会有问题。页面的可重复元素的维护比如主导航页脚边栏在需要处理 10 个文件时可能会成为一个问题。每次你想要更改页脚中的内容你都需要更新 10 个文件。当一个项目有 50 个模板时情况会变得更加复杂。你可以开始使用 PHP 或任何包含重复代码部分的文件的语言或者使用其中一个模板语言。有多种模板系统。以下是一些知名和时髦的模板系统手柄HAMLJadeSlim让我们专注于 Jade。为什么因为有以下功能混合支持主模板文件的部分化缩进的语法类似于 SASS安装和使用 JadeJade 是通过 node 包管理器安装的。你可以用以下命令安装它npm install jade --global如果你想编译一些文件只需要调用 HTML 文件如下jade filename.html更多信息我建议你查看 Jade 模板系统的官方文档jade-lang.com/。Jade 的基础知识理论介绍很重要但让我们试着将代码的这部分描述成 Jadenav ul lia href#Home/a/li lia href#About/a/li lia href#Contact/a/li /ul /nav在 Jade 中它会是这样的nav ul lia(href#)Home lia(href#)About lia(href#)Contact你可以看到你不需要考虑标准的 HTML 问题“我的标签关闭了吗”缩进会跟踪标签的开启和关闭。你想要附加到标签中的每个文本都会出现在标签描述名称和属性后的空格后。让我们看一下代码的这部分a(href#)Home这部分代码将被编译成a href#Home/a如你所见在 Jade 中属性href出现在元素名称a之后用括号括起来。让我们看一下我们将要翻译成 Jade 的 HTML 代码的下一部分head meta charsetutf-8 titlePage title/title link relstylesheethrefcss/main.cssmediascreentitleno titlecharsetutf-8 /head这部分代码将在所有页面上重复出现因为它包含了我们 HTML 的head标签。在 Jade 中它会是这样的headmeta(charsetutf-8)title Page titlelink(relstylesheet,hrefcss/main.css,mediascreen,titleno title,charsetutf-8)在这里你可以看到如何向 HTML 元素添加更多属性。在link元素中括号中的每个属性都用逗号分隔。代码的下一部分与带有类和 ID 的 DOM 元素有关main idmain article classmain--article a href# img srcimg/error_log.pngalt/ span classcomments/span /a h3Lorem ipsum dolor sit amet,consectetur adipisicing elit/h3 p sed do eiusmod tempor incididunt ut labore et dolore /p a href#classreadmoreRead more/a /article /main在 Jade 中代码看起来是这样的main#main article.main--articlea(href#)img(srcimg/error_log.png,altError log).comments h3 Lorem ipsum dolor sit amet p sed do eiusmod tempor incididunt ut labore et dolorea(href#).readmore Read more你可以看到你不需要描述这部分main idmain这是写成这样的main(idmain)在 Jade 中有一个简短的形式main#main类似的情况也适用于类article classmain--article你也可以使用一个简短的形式article.main--article这种简短的方法使 Jade 易于理解因为它基于 CSS 中使用的选择器。Jade 中的混合Jade 中的混合很有用特别是当网页上有一些可重复的元素时。例如可能是一些带有href的小元素amixinlink(href,name)a(href href)name现在我们需要做的就是将它添加到你的模板中link(url,Your link)在你编译的文件中你会看到a hrefurlYour link/a在 Jade 中包含和扩展功能如前所述我们可以将代码的部分保存在单独的文件中。这样做的最简单方法是使用include方法。假设我们已经在文件navigation.jade中定义了主要的nav并且我们希望在我们的模板中添加其内容。代码如下文件名是navigation.jadenav ul lia(href#)Home lia(href#)About lia(href#)Contact文件名是template.jadedoctype html html headmeta(charsetutf-8)title Page titlelink(relstylesheet,hrefcss/main.css,mediascreen,titleno title,charsetutf-8)body include _navigation.jade当您编译template.jade时您将得到!DOCTYPE html html head meta charsetutf-8 titlePage title/title link relstylesheethrefcss/main.cssmediascreentitleno titlecharsetutf-8 /head body nav ul lia href#Home/a/li lia href#About/a/li lia href#Contact/a/li /ul /nav /body /html这是一个很好的时机来使用可以扩展的主布局。这可以通过代码操作来完成。第一次操作必须在主模板中进行 - 定义一个将在我们的 HTML 文件中交换的块。第二次需要在将代表最终 HTML 文件的文件中完成 - 指定将扩展的主模板。代码如下文件名是master.jadedoctype html html headmeta(charsetutf-8)title Page titlelink(relstylesheet,hrefcss/main.css,mediascreen,titleno title,charsetutf-8)body include _navigation.jade block content文件名是index.jadeextends master block content h1 Content编译后的文档!DOCTYPE html html head meta charsetutf-8 titlePage title/title link relstylesheethrefcss/main.cssmediascreentitleno titlecharsetutf-8 /head body nav ul lia href#Home/a/li lia href#About/a/li lia href#Contact/a/li /ul /nav h1Content/h1 /body /html在 gulp.js 中使用 Jade要在gulpfile.js中创建或添加 Jade 任务您需要使用npm安装特定的包gulp-jade。要这样做请使用以下命令npm install --save gulp-jade然后您需要在gulpfile.js中定义一个新任务并为模板添加一个监视器该模板将存储在src/jade目录中。以下是来自本书第一章的扩展gulpfile.js的清单var gulp require(gulp),sass require(gulp-sass),jade require(gulp-jade);gulp.task(sass, function (){return gulp.src(src/css/main.sass).pipe(sass().on(error,sass.logError)).pipe(gulp.dest(dist/css/main.css));});gulp.task(jade, function(){gulp.src(src/jade/*.jade).pipe(jade()).pipe(gulp.dest(dist/));});gulp.task(default, function (){gulp.watch(src/sass/*.sass,[sass]);gulp.watch(src/jade/*.jade,[jade]);});它会表现如何每当您更改src/jade文件夹中的任何文件时编译后的文件将会出现在dist文件夹中。当然如果您愿意这种结构可以更改这只是使用示例。随意更改它UnCSS有多少次你面对过这样的情况HTML 中没有使用某些类/选择器但在 CSS 代码中有描述每当您的项目更改或重新设计时这种情况都会发生。例如您的任务是删除某些部分并在 HTML 代码中添加几行。因此您将添加一些 CSS 代码然后删除其中的一些。但您确定 CSS 代码不包含未使用的 CSS 代码部分吗UnCSS 将帮助您完成此任务。要安装它您需要执行此命令npm install -g uncss让我们来看看在npm命令中使用的标志标志描述-g全局安装--save本地安装这些包将出现在package.json的dependencies部分。这些包是在生产中运行应用程序所需的。--save-dev本地安装这些包将出现在package.json的devDependencies部分。这些包是用于开发和测试过程的。在 Gulp 中集成 UnCSS首先我们需要通过npm安装gulp-uncssnpm install --save gulp-uncss现在我们需要在gulpfile.js中添加新的任务。我们需要在项目中创建一个测试阶段该阶段将存储在test目录中。您需要这些新任务来基于uncss进行处理gulp.task(clean-css-test, function (){return gulp.src(test/css/main.css,{read:false}) .pipe(rimraf({force:true}));});gulp.task(jade-test, function(){return gulp.src(src/jade/templates/*.jade).pipe(jade()).on(error,gutil.log).pipe(gulp.dest(test/));});gulp.task(sass-test,[clean-css-test], function (){return gulp.src(src/sass/main.sass).pipe(sass().on(error,sass.logError)).pipe(gulp.dest(test/css/));});gulp.task(uncss,[jade-test, sass-test], function (){return gulp.src(test/css/main.css) .pipe(uncss({html:[test/**/*.html]})).pipe(gulp.dest(./test/uncss));});要运行uncss任务您需要使用以下命令gulp uncss此命令将执行以下任务将 Jade 文件编译到test文件夹中从test文件夹中删除旧的 CSS 文件将 SASS 文件编译到test文件夹中运行uncss任务并将文档保存为test/uncss文件夹中仅使用的 CSS 部分现在我们需要实时测试。我们将准备一个简短的测试环境。以下是文件的结构├── jade │ ├── master_templates │ │ └── main.jade │ ├── partials │ │ ├── footer.jade │ │ └── navigation.jade │ └── templates │ ├── about.jade │ ├── contact.jade │ └── index.jade └── sass └── main.sass代码如下文件名是main.jadedoctype html html headmeta(charsetutf-8)title Page titlelink(relstylesheet,hrefcss/main.css,mediascreen,titleno title,charsetutf-8)body include ../partials/navigation block content include ../partials/footer文件名是navigation.jadenav ul lia(href#)Home lia(href#)About lia(href#)Contact文件名是footer.jadefooter p Copyright fedojo.com文件名是index.jadeextends ../master_templates/main block content .main p Test of INDEX page文件名是about.jadeextends ../master_templates/main block content .main h1 Test of ABOUT page文件名是contact.jadeextends ../master_templates/main block content .main h1 Test of CONTACT page文件名是main.sassbodybackground:#fff pcolor:#000 .headerbackground:#000color:#fff .footerbackground:#000color:#fff headerbackground:#000color:#fff footerbackground:#000color:#fff现在让我们检查这个过程对我们是否有利。这是从 SASS 编译的文件body{background:#fff;}p{color:#000;}.header{background:#000;color:#fff;}.footer{background:#000;color:#fff;}header{background:#000;color:#fff;}footer{background:#000;color:#fff;}此文件由uncss检查它查看了所有模板index.htmlabout.html和contact.htmlbody{background:#fff;}p{color:#000;}footer{background:#000;color:#fff;}我们的新命令是用 Gulp 构建的删除了所有不必要的 CSS 声明。压缩 CSS缩小文件的过程主要应该用于生产代码。在开发过程中对缩小的文件进行操作会很困难因此我们只需要为生产代码进行缩小。可以通过添加适当的标志--compressed来启用 SASS 或 Compass 编译中的缩小。我们还将使用一个外部工具在uncss过程之后对代码进行缩小。现在我们需要安装gulp-clean-cssnpm install --save gulp-clean-css现在缩小uncss过程的结果。我们将创建一个prod目录其中存储项目的最终版本。现在让我们导入gulp-clean-csscleanCSS require(gulp-clean-css)让我们在gulpfile.js中创建所需的部分gulp.task(clean-css-production, function (){return gulp.src(prod/css/main.css,{read:false}) .pipe(rimraf({force:true}));});gulp.task(sass-production,[clean-css-production], function (){return gulp.src(src/sass/main.sass) .pipe(sass().on(error, sass.logError)) .pipe(uncss({html:[prod/**/*.html]})).pipe(cleanCSS()).pipe(gulp.dest(prod/css/));});gulp.task(jade-production, function(){return gulp.src(src/jade/templates/*.jade).pipe(jade()).pipe(gulp.dest(prod/));});gulp.task(production,[jade-production,sass-production]);最终的自动化工具现在我们需要将之前创建的所有任务汇总到一个文件中。gulp项目的核心是两个文件package.json它汇总了所有项目依赖以及gulpfile你可以在其中存储所有任务。以下是任务文件名是package.json{name:automatizer,version:1.0.0,description:CSS automatizer,main:gulpfile.js,author:Piotr Sikora,license:ISC,dependencies:{gulp:latest,gulp-clean-css:latest,gulp-jade:latest,gulp-rimraf:latest,gulp-sass:latest,gulp-uncss:latest,gulp-util:latest,rimraf:latest}}文件名是gulpfile.jsonvar gulp require(gulp),sass require(gulp-sass),jade require(gulp-jade),gutil require(gulp-util),uncss require(gulp-uncss),rimraf require(gulp-rimraf),cleanCSS require(gulp-clean-css);gulp.task(clean-css-dist, function (){return gulp.src(dist/css/main.css,{read:false}) .pipe(rimraf({force:true}));});gulp.task(clean-css-test, function (){return gulp.src(test/css/main.css,{read:false}) .pipe(rimraf({force:true}));});gulp.task(sass,[clean-css-dist], function (){return gulp.src(src/sass/main.sass).pipe(sass().on(error,sass.logError)).pipe(gulp.dest(dist/css/));});gulp.task(jade, function(){return gulp.src(src/jade/templates/*.jade).pipe(jade()).pipe(gulp.dest(dist/));});gulp.task(jade-test, function(){return gulp.src(src/jade/templates/*.jade).pipe(jade()).on(error,gutil.log).pipe(gulp.dest(test/));});gulp.task(sass-test,[clean-css-test], function (){return gulp.src(src/sass/main.sass).pipe(sass().on(error,sass.logError)).pipe(gulp.dest(test/css/));});gulp.task(uncss,[jade-test, sass-test], function (){return gulp.src(test/css/main.css) .pipe(uncss({html:[test/**/*.html]})).pipe(gulp.dest(test/uncss));});gulp.task(clean-css-production, function (){return gulp.src(prod/css/main.css,{read:false}) .pipe(rimraf({force:true}));});gulp.task(sass-production,[clean-css-production], function (){return gulp.src(src/sass/main.sass) .pipe(sass().on(error, sass.logError)) .pipe(uncss({html:[prod/**/*.html]})).pipe(cleanCSS()).pipe(gulp.dest(prod/css/));});gulp.task(jade-production, function(){return gulp.src(src/jade/templates/*.jade).pipe(jade()).pipe(gulp.dest(prod/));});gulp.task(production,[jade-production,sass-production]);gulp.task(default, function (){gulp.watch(src/sass/*.sass,[sass]);gulp.watch(src/jade/*.jade,[jade]);});总结在本章中我们讨论了 Jade 模板系统的基础知识。我们看到了如何将其添加到前端开发人员的工作流程中。基于模板系统你现在可以将 UnCSS 包含到你的流程中并从 CSS 文件中删除不必要的代码。然后我们对最终结果进行了缩小并创建了生产代码。你可以将这个自动化工具视为项目的起点并根据自己的项目进行调整。你也可以添加新功能并不断完善它。