P3M1:工程化基础、自动化工具

1,016 阅读9分钟

T1:前端工程化概述、Node.js 基础

前端工程化 #2

面向前端工程开发的工具集,方便对代码压缩、特性兼容、同一格式化、预编译文件等问题的解决。

  • 脚手架工具
    • 专用:vue-cli、create-reacet-app、angular-cli、gatsby-cli
    • 通用:Yeoman、Plop
  • 自动化构建:npm scripts & script hooks、Grunt、Gulp、FIS
  • 模块化打包:Webpack、Rollup、Parcel
  • 标准化规范:ESLint、StyleLint、Prettier
  • 自动化测试:Mocha、Jest、Enzyme、Cypress、Nightmare、Puppeteer
  • 自动化部署:Git Hook、Lint-staged、CI/CD

Node.js 基础

Node.js 是一个基于 V8 引擎的 JavaScript 运行时。

类同浏览器,Node.js 为 JavaScript 提供了一个运行环境,建立在 node.js 上

Node.js APIs #5

浏览器里的 JavaScript 包括了 ECAMScript 和 Web APIs,Web APIs 则包括 DOM 和 BOM;

Node.js 下的 JavaScript 包括了 ECMAScript 和 Node APIs,Node APIs 则包括 fs、path、OS、HTTP等

Node.js 的运行 #7

在命令行中运行

  • 脚本模式

    在文件目录下,输入 node 和文件名,即执行该 js 文件。

  • 交互模式

    输入 node 回车进入

    此模式下,类似于浏览器 console,可以直接输入代码执行

    输入 .exit 退出

全局对象 #8

浏览器中的 JavaScript 的全局对象是 window,Node.js 中是 global

在交互模式下,声明的变量和函数都属于 global;在脚本模式下,声明的变量和函数都属于 global

全局函数 #9

全局函数包括了 JavaScript 自身提供的方法和全局对象 global 下的方法。

global 下有 setTimeout、clearTimeout、setInterval、clearInterval,与浏览器端的 window 下用法相同。也有新增加的方法:

  • setImmediate 立即执行定时器

    插入到事件队列的最前执行

    与 process.netxTick 的区别:

    process.nextTick 函数将在主程序的末尾执行,在事件列队之前。

  • clearImmediate 立即清除定时器

Node.js 内置模块

Node.js 有内置模块、自定义模块和第三方模块。

内置模块即 Node.js APIs,安装 Node.js 即可用。第三方模块需要在使用前自行选用安装。

console #11

process #12~13

process 是 global 的变量,因此它是全局的。使用 require() 引入不是必须的。

  • arch 当前操作系统架构

  • platform 当前系统平台信息

  • cwd() 当前文件所在目录,cwd

    __dirname 指向的值相同

    __filename 则是当前文件的完整路径,包含了文件名

  • env 环境变量

    自定义的环境变量在 env 下新定义变量即可

  • pid 进程编号

  • kill(pid) 结束该进程

path #14

path 必须由 require() 引入。const path = require('path');

获取当前文件所在目录

  • extname(url) 路径指向文件的扩展名

  • dirname(url) 路径指向文件的目录部分

  • basename(url) 路径指向文件的文件名(包括扩展名)

  • join() 拼接路径,并且自动补 /

    e.g.1 实现返回上一层:let fa = path.join(__dirname,'..');

    e.g.2 获得同一目录下的其他文件的完整路径:let another = path.join(__dirname,'another.js');

fs #15~17

File System 能够实现对文件操作和管理。

对文件的操作
  • 清空写入 fs.writeFile(fileName, content, callback)

    参数:

    • fileName
    • content:文件内容
    • callback:回调,写入完成后调用
      • err:错误

    e.g. fs.writeFile(__dirname+'/1.txt', 'Hello,node.js!', (err)=>{if (err) throw err;})

  • 读取 fs.readFile(url, callback);

    参数:

    • url

    • callback

      • err

      • data:读取到的文件二进制数据,默认以十六进制输出。

        【常用】调用 toString 转换为字符串

  • 删除 fs.unlink(url, callback);

  • 追加写入 fs.appendFile(url, content, callback);

对目录操作
  • 创建目录 fs.mkdir(url, callback)

  • 删除目录 fs.rmdir(url, callback);

    只能删除空目录

  • 重命名目录 fs.rename();

  • 读取目录 fs.readdir()

查看文件信息
  • fs.stat()
    • isDirectory()
    • isFile()
fs 中的同步和异步

除了上面讲的方法,另外还有加 Sync 后缀的方法,表示同步执行

一般情况下,多使用异步。强调先后顺序的命令使用同步方法,比如

【案例】文件的复制和压缩 #18
文件流 #19

读取流通过管道到写入流

  • 创建一个读取流 createReadStream()

    创建的实例可以调用 pipe() 联通写入流,写入流作为实参。

  • 创建一个写入流 createWriteStream()

HTTP #20

HTTP 可以发布 Web 服务。

使用前需要使用 require 引入。

  • 创建一个服务 http.createserver(func)

    参数:一个函数

    • req:request 请求

      • setHeader
      • end
    • res:response 响应

  • 发布服务 server.listen()

自定义模块

Node.js 中每个单独的 .js 文件,就是一个模块。模块内是定义的属性和方法。

每个模块中都有一个 module 变量,其代表当前模块。

module 的 exports 属性是对外的接口,其值为一个对象。module.exports 对象内的的属性或方法是被导出的,能被外部调用,未导出的内容是模块私有,不能被外部访问

使用时,通过 require 引入。

模块的组织和加载逻辑

模块文件的组织有两种,单个的文件模块和多个文件组成的目录模块

模块的引入形式也有两种,以路径开头和不以路径开头。

image-20210514181406495

第三方模块(npm)

第三方模块由 npm 维护,主要介绍 npm 的使用。

npm 换源

npm config set registry https://registry.npm.taobao.org

全局安装

npm i packageName -g

注:-g = -global

全局安装后,可以直接以 packageName 调用包

局部安装(仅供某个项目使用)

  1. 在项目文件夹下初始化项目:npm init

    问答交互式配置 npm 项目,生成 package.json。也可以加 --yes-y 以默认值作配置

  2. 初始化完成后,可以进行安装,需要加命令行参数:

    • --save / -S:模块包会放在 dependencies 下。开发和运行都需要的模块,例如 jQuery

    • --save-dev / -D:模块包会放在 devDependencies 下。只在开发环境下依赖的模块工具,开发完成后上线运行不再需要,例如压缩模块。

  3. 安装后,需要选中包的具体路径位置调用,默认在项目文件夹下的 .\node_modules\.bin\packageName

T2:脚手架工具:Yeoman

脚手架工具辅助开发,帮助快速创建项目基础、提供项目规范和约定,实现代码复用。

通用脚手架:yeoman

专用脚手架:vue-cli、create-react-app、angular-cli(它们又不止于脚手架)

Yeoman

命令行工具 yo

通过 yo 管理和调用生成器来生成不同的项目

  1. 官网 搜寻需要的 generator
  2. 安装生成器:npm i -g generatorName
  3. 创建项目:在目标项目文件夹下 yo generatorName
  4. 运行项目:项目文件夹下 npm run start

T3:自动化构建

构建:将源代码转换成生产代码。

构建的需要有以下几种:

  • 代码需要编译或处理兼容( LESS → CSS,ES6+ → ES5)
  • 代码需要压缩( CSS,JS,HTML,图片等 ),节省带宽,提高加载速度
  • 代码需要做格式化校验,统一代码风格。

通过不同功能的 npm 模块来实现我们想要的构建。

自动化构建的实现:npm scripts

npm 允许在 package.json 文件里面,使用 scripts 字段定义脚本命令。例如:

{
    "scripts": {
        "foo": "node bar.js"
    }
}

scripts 字段是一个对象。它的每一个属性,对应一段命令脚本。可以直接以 npm 调用 scripts 的属性,即等同于在命令行中执行了对应的命令。例如:npm run foo .

执行方式

一段 npm scripts 当中可能需要执行多个任务,需要明确它们的执行顺序。

  • 并行执行 parallel

    任务1**&** 任务2

  • 串行执行 series

    任务1 && 任务2

Windows 下无效,需要 npm-run-all 插件

插件添加了 -p -s 命令行参数,分别对应并行和串行模式,在 run 时使用。

构建案例和相关包的使用

构建样式文件

  1. less 转 css(less 插件)

    lessc

  2. css 格式检测(StyleLint 插件)
    • 配置:

      在项目文件夹下,先初始化:eslint --init 可以通过问答交互自动生成配置文件 .eslintrc.json

      配置文件下的 rules 可以修改为需要规范的样式,比如缩进、单双引号

    • 使用:

      • 单个文件:eslint path/filename.js
      • 整个目录:eslint path/dirname

      会根据 rules 提示警告或错误

  3. 压缩 css(minify 插件)

构建脚本文件

  1. ES6+ 转 ES5(Babel 插件)
    • 安装:

      Babel 有多种转码规则,本例需要的、也是最常用的:babel-preset-env

      使用前需安装转码规则:npm i babel-preset-env -D

    • 配置:在项目根目录对 Babel 进行配置 .babelrc

    • 使用:

      • 单个文件

        babel input.js -o output.js

        -o = --out-file

      • 整个文件夹

        babel src -d dist

        -d = --out-dir

  2. js 格式检测(ESLint 插件)
    • 安装:

      需要安装标准:npm i -g stylelint-config-standard

    • 配置:在项目根目录手动创建配置文件 .stylelintrc.json

    • 使用:

      • 单个文件:stylelint path/filename.css
      • 整个项目:stylelint **/*.css
  3. 压缩 js(minify 插件)同上

T4:自动化构建工具:Gulp

借助工具可以实现更进一步的自动化构建,比如:Grunt、Gulp、FIS,其中以 Gulp 最为流行。

Gulp 的安装、使用

  1. 全局安装 gulp 客户端 npm install -g gulp-cli

  2. 初始化项目 npm init --yes

  3. 安装 gulp 包 npm install gulp -D

  4. 项目根目录新建 gulpfile.js 文件

  5. gulpfile.js 中,创建 gulp 任务

    1. 任务变量声明

      • 新:定义函数常量

        所有的任务都是异步的,因此需要在参数中传入回调函数

      • 旧语法:gulp.task( 'taskName', func() )

    2. 任务导出:module.exports

      exports 的 default 属性可以直接以 gulp 命令调用

  6. 执行 gulp 任务 gulp taskName

Gulp 中的组合任务 #2

与 npm scripts 相似,Gulp 也有区分串行和并行的方法

  • 串行:series(t1,t2,t3)
  • 并行:parallel(t1,t2,t3)

二者可以相互、多层嵌套来实现更复杂的执行顺序

文件操作 #3

Gulp 中的文件操作是基于

  • 读取流/源:src()

    参数:

    1. 源文件*,URL字符串
    2. 配置,对象
      • base:保留该位置下的目录结构,url字符串
  • 写入流/目标:dest()

  • 管道:pipe()

e.g.

const { src, dest } = require('gulp');
exports.default = () => {
  return src('src/styles/main.less', { base: 'src' }).pipe(dest('dist'))
}

【案例】使用 Gulp 和相关插件实现的自动化构建

构建 CSS 样式文件 #4

使用服务 gulp 的三个插件:gulp-less、gulp-clean-css、gulp-rename,来一步完成 less 文件转 css 文件,并压缩、重命名。

  1. gulpfile.js 添加插件的依赖
  2. 新建任务,在源和目的之间,利用管道 pipe() 调用插件。每次调用都需要一个管道,可以连续调用。
  3. 导出任务
CSS hack 插件:autoprefixer #5

使用 gulp-autoprefixer 插件来完成 CSS 针对不同浏览器的前缀,它的数据来源于 caniuse.com

它的处理顺序应放在转换之后、压缩之前。

构建 JS 脚本文件 #6

使用插件 gulp-babel、gulp-uglify、gulp-rename 来实现对 js 文件降低版本、压缩、重命名。

gulp-babel 的调用时,是将转换规则写在配置对象中作为参数传入:

  • 旧版本:{ presets: ['@babel/env'] }
  • 新版本:{ presets: [babel/presets/env] }

构建 HTML 页面文件 #7

压缩:gulp-htmlmin

gulp-htmlmin 的参数为一个配置对象,例如:{ collapse: true, minifyCSS: true, minifyJS: true} 压缩 HTML 空白和行内样式、脚本。

构建图片文件 #8

gulp-imagemin

文件清除 #9

需求:构建前清除多余文件

del

【综合】

将上述的各项构建操作综合为一个任务:

series(clean, parallel(style, script, html, img))

先清空目标文件夹,然后并行执行 HTML、CSS、JS、图片文件的构建。

开发服务器 #10

browser-sync

LIVE: