前端工程化概述和node.js基础

1,114 阅读9分钟

前端工程化概述

  • 工程的概念 工程就是项目。工程的整个生命周期可分为以下几个部分: image.png
  • 工程化 工程化就是完成项目过程中,用到的各种工具和技术。
  • 前端工程化 前端工程化就是通过各种工具和技术,提升前端开发效率的过程。 前端工程化的内容:各种工具和技术。 image.png

前端工程化的内容

技术是为解决问题而存在的。

  • 前端代码压缩是为了节约带宽,网页加载更快;
  • 想要用ES6+和CSS3需要解决兼容性问题,兼容性问题可以在caniuse.com上查找到;

image.png

  • 代码规范是为了解决代码风格无法统一的问题; 等等。 image.png 工程化≠某个工具,工具和技术只是工程化落地的手段。不过我们还是需要学习相关的工具和技术,先从前端工程化的基础node.js学起。

node.js基础

node.js官网:nodejs.org “Node.js®是基于Chrome的V8 JavaScript引擎构建的JavaScript运行时。”,运行时的英文是runtime,运行环境。 image.png

image.png node.js不是新的编程语言,也不是JavaScript框架,而是JavaScript的一个运行环境。

node.js功能

和浏览器中的JavaScript主要负责前端功能不同,node.js中的JavaScript主要负责后端功能。
浏览器端的JavaScript:

  • 响应浏览器事件
  • 数据验证
  • DOM操作
  • 不能做文件操作 Node端的JavaScript:
  • Node.js适合开发服务器端的应用层(BFF)
  • 为网站、APP、小程序等提供数据服务
  • Node.js适合用于开发前端方向的各种工具
  • 各种前端工程化的工具
  • Node.js可以用来做桌面应用开发,各种跨平台的桌面应用,比如vscode,typora,insomnia等 Node.js给JavaScript插上了全栈编程的翅膀。

node.js API

node.js API是在ES的语法基础上实现了和操作系统的交互。 image.png

node.js安装

  1. 在官网下载Node.js安装包
    一般选择首页推荐的LTS版本就行了,这里我们手动选择download, image.png 找到历史版本, image.png 找到12.19.0版本,download image.png
  2. 双击安装包,一路next安装
  3. 命令行输入node -v验证安装是否成功

image.png

node.js使用

Node.js下运行JavaScript

  • 脚本模式
    命令行输入node .\hello.js
    表示运行当前目录的hello.js文件
  • 交互模式
    命令行输入node回车进入交互模式,在交互模式下
    • 使用tab键自动补全
    • 探索JavaScript对象(例如:Math.然后按两次tab键)
    • 点命令(例如:输入.help然后回车)

node.js下的全局对象是global

在交互模式下,声明的变量和函数都属于global。例如var a = 1; global.a可以获取到a的值。 image.png 在脚本模式下,声明的变量和函数都不属于global。
无论哪个模式,属于DOM和BOM的部分是无法访问到的。比如window、ducument。 image.png

node.js下的定时器执行顺序

  • JavaScript语言提供的全局函数,在Node.js下依然可用
    • parseInt/parseFloat/isNaN/isFinite/eval..
    • 一次性定时器(setTimeout/clearTimeout)
    • 周期性定时器(setInterval/clearlnterval)
  • Node.js环境也提供了一些全局函数
    • 立即执行定时器(setImmediate/clearImmediate)
    • 进程立即执行定时器(process.nextTick) 执行顺序是:主进程→nextTick→事件队列(setImmediate)→事件队列(setTimeout,setInterval) image.png

node.js模块

  • 内置模块:在nodejs.cn/api/ 有中文说明文档,也可以进入nodejs.org/en/docs/ 官网文档中查看
  • 自定义模块
  • 第三方模块:社区维护的,需要单独下载才能使用,比如Less,Babel,Express...在集中管理平台www.npmjs.com/ 都有说明。

内置模块console

在中文文档和官方文档中都可找到相关用法: image.png 我们只列举常用的几个。

// 不同类型的数据,输出后颜色不同
console.log('1');
console.log(1);

var obj = { name: 'Tom', age: 19 }
console.log(obj)
console.table(obj) // 以表格方式展示数据

console.time('for');//开始计时
for (var i = 1; i <= 100000; i++) {
}
console.timeEnd('for');//结束计时

console.time('while');
var i = 1;
while (i <= 100000) {
  i++;
}
console.timeEnd('while');

内置模块process

process 对象是一个全局变量,提供了有关当前 Node.js 进程的信息并对其进行控制。作为全局变量,它始终可供 Node.js 应用程序使用,无需使用 require()。 它也可以使用 require() 显式地访问:

// process 是全局变量,可以不写 require 引入
const process = require('process');

// 获取操作系统架构  x64
console.log(process.arch)

// 当前系统平台信息  win32
console.log(process.platform)

// 获取当前文件所在的目录
console.log(process.cwd())

// 环境变量
console.log(process.env)
// 自定义环境变量
process.env.NODE_ENV = 'develop'// 标识是线上环境还是开发环境
console.log(process.env)

// 获取进程的编号
console.log(process.pid)

// 杀死进程  
process.kill(进程编号)

内置模块path

path 模块负责文件路径的,使用之前必须使用require关键字引入。

  • ./ 表示当前目录
  • ../ 表示上一级目录
  • __dirname 返回当前文件所在的目录
  • __filename 返回当前文件的完整路径(目录+文件)
// path使用之前必须使用require关键字引入
const path = require('path');

// __dirname 获取当前文件所在的目录
console.log(__dirname);

// __filename 获取当前文件的完整路径
console.log(__filename);

// path.join()用于拼接多个路径部分,并转化为正常格式
const temp = path.join(__dirname, '..', 'lyrics', './友谊之光.lrc');
console.log(temp);

console.log('获取路径中的文件名');
console.log(path.basename(temp));

console.log('获取一个路径中的目录部分');
console.log(path.dirname(temp));

console.log('获取一个路径中最后的扩展名');
console.log(path.extname(temp));

内置模块fs

fs (file system)模块主要负责文件基本操作。使用之前必须使用require关键字引入。

  1. 文件基本操作
// 使用 fs 之前先引入
const fs = require('fs')

// 写文件 (清空写入:写入之前会先将文件清空)
// fs.writeFile('文件路径','写入内容',回调函数)
fs.writeFile('./1.txt', '曾经有一首歌,她感动了我', (err) => {
    if (err) throw err
    console.log('写入成功')
})

// 读文件
// fs.readFile('文件路径', 回调函数)
fs.readFile('./1.txt', (err, data) => {
    if (err) throw err
    // data 是二进制数据,默认输出时,以十六进制的方式展示
    // 想要看到正常的效果,需要通过 toString() 转换
    console.log(data.toString())
})

// 删除文件
// fs.unlink('文件路径', 回调函数)
fs.unlink(__dirname+'/1.txt', (err) => {
    if (err) throw err
    console.log('删除成功')
})

// 追加写入(多次执行,文件中会有多条数据)
// fs.appendFile('文件路径','写入内容',回调函数)
fs.appendFile(__dirname+'/2.txt', '曾经有一首歌,她是这样唱的\n', (err) => {
    if (err) throw err
    console.log('追加写入成功') 
})
  1. 目录基本操作
const fs = require('fs')

// 创建目录
fs.mkdir('./d1', (err) => {
  if (err) throw err
  console.log('创建成功')
})

// 删除目录,只能删除空目录
fs.rmdir('./d1', (err) => {
  if (err) throw err
  console.log('删除成功')
})

// 重命名目录
// fs.rename(旧名称, 新名称, 回调函数)
fs.rename(__dirname+'/d1', __dirname+'/d2', (err) => {
  if (err) throw err
  console.log('重命名成功')
})

// 读取目录的内容
fs.readdir(__dirname, (err, data) => {
  if (err) throw err
  // console.log(data) // data 是数组
  data.map((d) => {
    console.log(d)
  })
})

// 判断文件是否存在
if (!fs.existsSync('./d2')) {
  fs.mkdirSync('./d2')
}
  1. fs.stat 查看状态
// 查看文件信息
fs.stat(__dirname+"/a.txt", (err, stat) => {
  if (err) throw err
  if (stat.isDirectory()) {
    // 判断当前文件是否是目录
    console.log('目录:', d)
  } else if (stat.isFile()) {
    // 判断当前文件是否是普通文件
    console.log('文件:', d)
  }
})
  1. 同步函数(synchronization)
  • 同步函数:在主程序中,自上而下运行
  • 异步函数:通过回调函数在事件队列中运行 image.png
const fs = require('fs')

// 先判断文件是否存在
// 然后,如果文件存在的化,再执行删除
if (fs.existsSync(__dirname+"/1.txt")) {
    fs.unlinkSync(__dirname+"/1.txt")
} else {
    console.log('文件不存在')
}
  1. 文件流 文件流相比文件缓冲方式操作文件优点:
  • 内存效率提高: 无需加载大量数据,流把大数据切成小块,占用内存更少
  • 时间效率提高: 接获数据后立即开始处理,无需等到内存缓冲填满
const fs = require('fs')

// 1. 创建读取流
var readStream = fs.createReadStream('./file2.txt')

// 2. 创建写入流
var writeStream = fs.createWriteStream('./file_stream.txt')

// 3. 把读取流通过管道传给写入流
readStream.pipe(writeStream)

内置模块http

http可以发布web服务,需要通过require()引用。

image.png

const http = require('http')

// 1. 创建服务器
/**
 * req = request 请求
 * res = response 响应
 */
const server = http.createServer((req, res) => {
    res.statusCode = 200
    res.setHeader('Content-Type', 'text/plain; charset=utf-8')
    res.end('你好:Node.js')
})

// 2. 发布 web 服务
const port = 3000
const host = 'localhost'
// 在浏览器中访问 http://localhost:3000 然后能看到效果
server.listen(port, host, () => {
    console.log(`服务器运行在 http://${host}:${port}`)
})

自定义模块

  • Node.js中每个单独的文件,就是一个模块
  • 每个模块中都有一个module变量,其代表当前模块
  • module的exports属性是对外的接口。
  • 使用时使用require()引用 只有导出(module.exports)的属性或方法才能被外部调用,未导出的模块是内部私有的,不能被外部访问。
    创建自定义模块:
// circle.js 我们声明一个模块 circle,模块中有两个方法,分别求圆的面积和周长。
const PI = 3.14

// 圆的周长
const perimeter = (r) => {
	return 2 * PI * r
}

// 圆的面积
function area (r) {
    return PI * Math.pow(r, 2)
}

// 模块内容导出后,才能被外部调用
module.exports = {
    perimeter,
    area
}

外部使用模块:

// 在 app.js 中引入模块
// 引入模块时,需要写引入路径,否则 require('circle') 会报错
const circle = require('./circle')

// 调用模块中的属性或方法
const r = 10
const p = circle.perimeter(r)
const a = circle.area(r)

console.log(`直径为 ${r} 的圆的周长是:` + p)
console.log(`直径为 ${r} 的圆的面积是:` + a)

模块的加载逻辑

这里我们可以根据文件的组织方式,将模块分成文件模块目录模块。 不同类型的模块,引入方式不同,其加载逻辑也不相同,一共有四种情况:

  1. 以路径开头的文件模块
  2. 不以路径开头的文件模块
  3. 以路径开头的目录模块
  4. 不以路径开头的目录模块 这里,我们将以上四种情况的加载逻辑整理成下表: image.png

第三方模块

第三方模块是由社区维护的模块,想要使用第三方模块需要单独安装。前端工程化的大部分工具都是第三方工具。
第三方工具集中管理网站:www.npmjs.com/
以bootstrap为例: image.png 我们可以在上面看到关于bootstrap的各种信息。

npm概述

我们知道了第三方模块,以及它们的集中管理平台,我们要如何安装呢?这时候就需要用到npm了。
npm(Node Package Manager)是Node.js的包管理工具,跟随Node.js一起安装的,同时也是一个命令。
在命令行中输入npm相应命令就可以进行包及其依赖的安装操作。
npm 命令下载包的资源地址,称为 npm 的镜像源。
默认 npm 的镜像源是国外的(npmjs.com),下载速度慢,为了提高下载速度,可以将 npm 的镜像源设置为国内的地址(例如:淘宝镜像源)
设置命令为:

// 修改npm的镜像源
npm config set registry https://registry.npm.taobao.org

// 验证是否更改成功(查看镜像源):
npm config get registry

使用npm安装包

npm安装包分为全局安装和项目安装。

  • 全局安装: npm install 包名称 --global(或 简写为 npm i 包名称 -g
    全局卸载:npm uninstall 包名称 --global(或 简写为 npm uninstall 包名称 -g

  • 项目安装,分为四步:

    1. 创建项目目录(mkdir project)

    2. 进入项目目录(cd project)

    3. 初始化项目(npm init)

    4. 在项目中安装包: 项目中安装的包,默认存在 当前项目/node_modules 目录下

      安装包时,涉及到两个重要的参数:

      • npm install --save

        • 安装好后,包的信息会写入 package.json 的 dependencies 中;
        • dependencies 中的包,在开发和生产环境都使用,例如:jQuery。
      • npm install --save-dev

        • 安装好后,包的信息会写入 package.json 的 devDependencies 中
        • devDependencies 中的包只用于开发环境,生产环境不需要。例如 minify,项目上线后,就不需要压缩文件了。
    配置项命令描述
    devDependencies--save-dev 简写 -D开发环境,管理的依赖包仅在开发阶段有效
    dependencies--save 简写 -S生产环境,管理的依赖包在项目上线后依然有效
# --save(-S) 安装好后写入 package.json 的 dependencies 中;
# dependencies 依赖的包不仅开发环境能使用,生产环境也能使用,例如 jQuery 开发和线上环境都需要
npm install jquery --save
# 
npm i jquery -S
   
# --save-dev(-D) 安装好后写入 package.json 的 devDependencies 中;
# devDependencies是只会在开发环境下依赖的模块,例如 minify 只需要开发环境使用,上线后就不需要了
npm install minify --save-dev
# 
npm i minify -D

包在命令行中的使用方法:
如果包安装在当前项目中(局部安装),则命令的执行路径是当前项目下的 .\node_modules\.bin 目录下。
如果包是全局安装,则命令执行的路径也是全局的