自动化构建和构建工具Gulp

自动化构建

什么是构建
  • 构建是将源代码转换成生产代码的过程
为什么构建
  • 一些代码需要编译(CSS,JS), 保证浏览器的兼容性
    将 Less 或 Sass 转换成 CSS
    将 ES6+ 的新语法转成 ES5
  • 有些代码需要压缩(CSS,JS,HTML,图片等)
    压缩之后的代码体积更小,加载更快,节省带宽
  • 有些代码需要做格式化校验,统一代码风格
  • 构建过程:源代码通过编译、压缩、格式化等等转化成生成代码
什么是自动化构建
  • 不管是代码压缩还是 less 转换,通过手动方式进行工作量巨大,自动化构建是指将手动构建任务,进行排列组合,然后通过命令(或工具)自动执行的过程
  • 实现自动化构建最简单的方式是 npm scripts (npm 脚本)
npm scripts
  • npm 在 package.json 文件里面,使用 scripts 字段定义脚本命令
{
  "scripts": {
    // 命令名称: 任务
    "foo": "node bar.js"
  }
}
# `scripts` 字段是一个对象。它的每一个属性,对应一段脚本。比如,`foo` 命令对应的脚本是`node bar.js`。

# 命令行下使用 npm run <命令>,就可以执行这段脚本。
$ npm run foo
# 等同于执行
$ node bar.js
  • npm 脚本就是 Shell 脚本,因为可以使用 Shell 通配符
"style": "lessc *.less"
"style": "lessc **/*.less"

* 表示任意文件名,** 表示任意一层子目录

  • 执行顺序
    如果是并行执行(即同时的平行执行),可以使用 & 符号
{
  "scripts": {
    "parallel": "node task1.js & node task2.js & node task3.js"
  }
}

如果是串行执行(前一个任务成功后,才执行下一个任务),可以使用 && 符号

{
  "scripts": {
    "series": "node task1.js && node task2.js && node task3.js"
  }
}

但是,& 符号在 Windows 操作系统下不起作用。此时,我们可以借助插件,在 Windows 下实现并行操作:npm-run-all

构建样式文件
  • 构建样式文件就是将开发环境下的 JavaScript 源代码,转成线上环境使用的代码。这里的构建任务可能有多个。

  • 在开发过程中,经常使用 ES6+ 新特性时,一些旧的浏览器,不支持 JS 的新语法。所以,在项目上线之前,就需要将新的语法特性解析成兼容性更好的 ES5 。最常用的编译工具是 Babel

  • Babel https://babeljs.io/

# 安装 babel核心,Babel客户端
npm i -g babel-core babel-cli

# 安装转码规则
npm i -g babel-preset-env

# 在项目根目录下,新建 .babelrc 文件(注意文件名前有一个点),并添加转换规则
{
    "presets": [
      "env"
    ],
}

# 通过 babel 编译单个 j s文件
babel input.js --out-file output.js
# 或者
babel input.js -o output.js
    
# 通过 babel 编译整个目录
babel js --out-dir scripts
# 或者
babel js -d scripts

# 在 package.json 中,添加 babel 解析命令
"scripts": {
    "script": "babel js -d scripts",
}

# 执行命令(自动编译)
npm run script

# 如果 Babel 是局部安装。则babel 的可执行路径是:./node_modules/.bin/babel命令需要做相应的调整
# babel js -d scripts    ===>   ./node_modules/.bin/babel js -d scripts
  • 添加压缩命令
# 在 package.json 中,添加 babel 解析和压缩命令
"scripts": {
    "script": "babel js -d scripts && minify scripts/main.js > scripts/script.min.js",
}
代码格式校验

使用 ESLint 来检测 JavaScript 代码

# 配置检测规则
{
    "env": {
        "browser": true,
        "commonjs": true,
        "es2021": true
    },
    "extends": "eslint:recommended",
    "parserOptions": {
        "ecmaVersion": 12
    },
    "rules": {
        "indent": [ "error", 2 ],       # 使用两个空格缩进
        "quotes": [ "error", "double" ] # 使用双引号包裹字符串
    }
}
StyleLint

StyleLint 是检测 CSS 代码格式的插件
官网:https://stylelint.io/

  • 在项目的根目录下,创建 .stylelintrc.json 文件,添加如下配置
{
  "extends": "stylelint-config-standard",
  "rules": {
    # 除了使用 stylelint-config-standard,我们还可以在 rules 字段中自定义校验规则
    "block-no-empty": true # 代码块不能为空
  }
}

自动化构建工具Gulp

自动化构建工具,可以帮我们又快又好的完成自动化构建任务。相比有 npm scripts,自动化构建工具,功能更为强大。更简单易学

  • Gulp 的构建是基于内存实现的,其构建速度比 Grunt 快,而且,Gulp 的生态也很完善,插件质量很高。目前最为流行

Gulp

Gulp 是基于 的自动化构建系统。

  • Gulp 的特点:
  • 任务化
    所有的构建操作,在 gulp 中都称之为任务
  • 基于流
    gulp 中所有的文件操作,都是基于 方式进行 ( Gulp有一个自己的内存,通过指定 API 将源文件流到内存中,完成相应的操作后再通过相应的 API 流出去)
Gulp 使用
  1. 使用 Gulp 之前,先在全局安装 gulp-cli
    命令:npm i -g gulp-cli
  2. 初始化项目
    npm init --yes
  3. 安装 Gulp 包
# 安装 gulp 包,作为开发时依赖项
npm i gulp -D
  1. 创建 gulpfile 文件
    gulpfile 文件是项目根目录下的 gulpfile.js在运行 gulp 命令时会被自动加载。在这个文件中,你经常会看到类似 src()dest()series()parallel() 函数之类的 Gulp API,除此之外,纯 JavaScript 代码或 Node.js 模块也会被使用。任何导出( exports )的函数都将注册到 Gulp 的任务(task)系统中

报错:The following tasks did not complete: task
Did you forget to signal async completion?
解释:在最新的 Gulp 中,取消了同步代码模式。约定每个任务都必须是一个异步任务
解决:再函数参数中,设定回调函数(回调函数是异步操作)

  1. 在 gulpfile.js 中注册 Gulp 任务

  2. 运行 Gulp 任务

# 运行 foo 任务
# 如需运行多个任务(task),可以执行 gulp <task> <othertask>
gulp foo
  1. 创建默认任务
# 默认任务的名称是 default
exports.default = cb => {
    console.log('default task is running')
    
    cb()
}

# 运行默认任务, gulp 后无需指定任务名称
gulp # 效果等同于 gulp default
组合任务
  • 按顺序执行,请使用 series() 方法
  • 并行执行,可以使用 parallel() 方法将它们组合起来
const gulp = require('gulp')
# 串行方式执行任务,先执行task1, 然后执行task2, 然后执行task3
exports.foo = gulp.series(task1, task2, task3)

# 并行方式执行任务,同时执行task1,task2,task3
exports.bar = gulp.parallel(task1, task2, task3)

# 执行命令
gulp foo # 串行执行
gulp bar # 并行执行
文件操作

gulp 暴露了 src()dest() 方法用于处理计算机上存放的文件。在代码构建过程中,需要将源文件,写入到目标目录。

# 通过 解构 的方式引入 gulp 中的函数
const { src, dest } = require('gulp')

exports.default = () => {
  // 文件操作
  // 将 src/styles 目录下的 main.css 文件,复制到 dist/styles 目录下
  return src('src/styles/main.less', { base: 'src' }).pipe(dest('dist'))
}

# 执行命令
gulp default
# 或直接执行
gulp

样式文件构建

  • 对样式文件进行转换、压缩、重命名。
  • 添加 CSS 属性前缀的操作,之前是通过程序员手动添加的。这类重复性操作,我们可以通过插件完成。
  • 在 Gulp 中 gulp-autoprefixer 插件,可以根据 caniuse.com 上提供的 CSS 兼容性数据,自动地给 CSS 属性加前缀,以保证 CSS 代码的兼容性问题。

脚本文件构建

  • 对 JS 代码进行 Babel 转换和压缩

页面模板构建

  • 对 html 文件的构建,主要指压缩 html 文件。其中 gulp-htmlmin 插件可以完成压缩任务
  • gulp-htmlmin 插件的解析器是:https://github.com/kangax/html-minifier
  • 我们可以将 style,script 和 html 任务组合起来。因为 style,script 和 html 之间没有明确的前后顺序,所以,可以进行并行执行,并行执行可以提升构建效率
# 引入 parallel 函数
const { src, dest, parallel } = require('gulp')

// 任务的并行执行
const build = parallel(style, script, html)

module.exports = {
  build
}

# 运行命令
gulp build

图片(字体)文件转换

  • 对图片文件的构建,主要是指图片的压缩。通过 gulp-imagemin 插件可以完成图片的压缩任务
报错处理:
gulp-imagemin: Couldn't load default plugin "gifsicle"
gulp-imagemin: Couldn't load default plugin "optipng"
原因:npm 安装依赖失败
解决:
1. 配置 hosts
2. 重新安装 npm i gulp-imagemin -D

文件清除

  • 有时候,我们需要删除一些构建的历史文件,然后再重新构建。删除文件操作,可以通过 del 插件完成

开发服务器

  • 通过web服务器插件,将 dist 下的代码,发布到浏览器查看效果。发布web服务的插件有很多。推荐功能强大的 browser-sync
# 安装 browser-sync 插件
npm i browser-sync -D

# 在 gulpfile.js 中添加开发服务器的内容
const browserSync = require('browser-sync')
const bs = browserSync.create()

// 声明 web 服务构建任务
const serve = () => {
  bs.init({
    server: {
      baseDir: './dist' // 指定服务启动的目录
      routes: {
        '/node_modules': 'node_modules' // 引入 Bootstrap 是设置路径映射
      }
    }
  })
}

module.exports = {
  clean,
  build,
  serve
}

# 运行命令,然后在浏览器查看效果
gulp serve
  • 服务发布成功后,之前学习的内容,也可以拿过来使用,例如:Bootstrap
  1. 下载插件
# 因为 Bootstrap 和 jQuery 上线之后还要使用,所以,采用 -S 参数(上线依赖)
npm i bootstrap@3.4.1 jquery -S
  1. 引入文件
    Bootstrap 和 jQuery 下载后,文件位于当前目录的 node_modules 下
# 在 HTML 中引入
<link rel="stylesheet" href="/node_modules/bootstrap/dist/css/bootstrap.min.css">
......
<script src="/node_modules/jquery/dist/jquery.min.js"></script>
<script src="/node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
  • 引入路径,需要在 browser-sync 中,通过 routes 参数映射后,才能正确引入
  1. 使用 Bootstrap

监视变化(热更新)

  • 监视 src 下文件变化的页面更新,代码一旦更新,浏览器上的页面效果也随之更新。

  • 此时,我们需要监视两个目录的变化,一个是 dist 目录,一个是 src 目录。

  • 监视 dist 目录下代码的变化

    # 通过 browser-sync 中的 files 字段
    files: 'dist/**'
    
  • 监视 src 目录下代码的变化

    # 通过 gulp 中的 watch 函数
    watch(被监视的文件,对应的任务)
    

最终的代码如下:

# 在 gulpfile.js 中添加监视文件变化的代码
const serve = () => {
  // watch(被监视的文件,对应的任务)
  watch('src/index.html', html)
  watch('src/styles/*.less', style)
  watch('src/js/*.js', script)
  watch('src/images/**', image)

  // 初始化服务
  bs.init({
    notify: false,      // 禁用浏览器右上角的 browserSync connected 提示框
    files: 'dist/**',   // 监视 dist 下 文件的变化,然后在浏览器上实时更新
    server: {
      baseDir: './dist', // 指定服务启动的目录
      routes: {
        '/node_modules': 'node_modules'
      }
    }
  })
}

// 组合任务
const build = parallel(style, script, html, image)
const dev = series(clean, build, serve)

// 导出任务
module.exports = {
  build,
  dev,
  serve
}

# 运行命令,更新代码文件,查看页面变化
gulp dev

此时,不管是 dist 目录下,还是 src 目录下。只要代码发生变化,我们就可以在浏览器上实时看到效果。

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

推荐阅读更多精彩内容