前端工程化简介
工程就是一个项目(比如一个网站或者app)
一个工程的生命周期
工程化就是项目完成过程中,用到的各种工具和技术
前端工程化
- 前端工程化就是通过各种工具和技术,提高前端开发效率的过程
- 前端工程化的内容:各种工具和技术
- 前端工程化的作用:通过使用工具,提高开发效率
前端工程化的内容
兼容性查阅
比如查看ES6标准兼容性:
前端工程化解决的问题
- 项目上线前,压缩代码
- 对ES6+或者CSS3新特性转换
-
对less等css的预编译语言进行编译处理
...
工程化≠某个工具
node.js
- 基于chrome的V8引擎的JavaScript运行环境
- 不是新语言,也不是JavaScript的新框架
node.js能做什么?
负责后端的功能
- 为网站,app,小程序提供数据服务
开发前端方向的工具
各种前端工程化的工具
用作桌面应用开发-
各种跨平台的应用
node.js APIs
安装node.js
- 下载安装一路next
- 安装LTS版node,便于后期维护更新
- 检查是否安装成功:cmd命令行node -v
使用node.js
运行JavaScript有两种方式
- 脚本模式
node path/filename.js(回车)
-
交互模式
- 使用tab键自动补全
- 探索JavaScript对象(例如:Math.然后按两次tab键,就可以看到Math下所有的对象)
- 点命令(例如:输入.help然后回车)
快捷键Ctrl+`可以打开编辑器里面的命令行
全局对象
- node.js下的全局对象是global
- 在交互模式下,声明的变量和函数都属于global
- 例如:var a = 1; global.a可以访问到
- 在脚本模式下,声明的变量和函数都不属于global
- Node.js 不能访问浏览器端的全局对象 window
全局函数
- JavaScript语言本身提供的全局函数,node.js依然可用
- parseInt/parseFloat/isNaN/isFinite/eval...
- 一次性定时器(setTimeout/clearTimeout)
- 周期性定时器(setInterval/clearInterval)
- Node.js环境也提供了一些全局函数
- 立即执行定时器(setImmediate/clearImmediate)
在实践队列开始之前,立即执行 - 进程立即执行定时器(process.nextTick)
在主进程结束后立即执行
- 立即执行定时器(setImmediate/clearImmediate)
node.js模块
- 内置模块(官方提供的,跟随node.js一起安装)
- 自定义模块(工程师自己写的)
- 第三方模块(社区维护的,需要单独下载才能使用)
内置模块,也叫核心模块
console
console.log("1")
console.log(1)
var obj = {
name: 'Tom',
age: 18
}
console.log(obj)
console.table(obj)
// 计时函数
console.time('for') // 计时开始
for (let i = 0; i < 1000000; i++) {
}
console.timeEnd('for') // 计时结束
console.time('while')
var i = 0
while (i < 1000000) {
i++;
}
console.timeEnd('while')
process(进程)
- 作为全局变量,它始终可供 Node.js 应用程序使用,无需使用 require()。 它也可以使用 require() 显式地访问:
const process = require('process');
// process 是全局变量,使用时,无需引入
// const process = require('process')
// console.log(process)
// 输出 node 版本
console.log(process.version)
// 输出操作系统架构
console.log(process.arch)
// 输出操作系统平台
console.log(process.platform)
// 输出当前工作目录 cwd = current working directory
console.log(process.cwd())
// 环境变量
console.log(process.env)
// 自定义环境变量
process.env.NODE_ENV = 'develop'
console.log(process.env)
// 获取进程的编号
console.log(process.pid)
// 杀死进程 process.kill(进程编号)
path
- 与process不同,需要引入path模块,使用require
const path = require('path');
// 引入 path 模块
const path = require('path')
// 获取当前文件所在的路径
console.log(process.cwd())
// dir = directory 目录
console.log(__dirname) // 获取当前文件所在的路径
// D:\cliu\Desktop\node\03.core_module\path.js
console.log(__filename) // 获取当前文件的完整路径
// 获取文件的扩展名 ext = extension
console.log(path.extname(__filename))
// 获取路径中的目录部分
console.log(path.dirname(__filename))
// 获取路径中的文件名
console.log(path.basename(__filename))
// 当前目前的上一级
const t = path.join(__dirname, '..')
console.log(t)
// 将多个路径合并起来
const a = path.join('D:/', 'a', 'b', 'c.png')
console.log(a)
fs
- fs提供了文件操作的API
- 文件操作
- 目录操作
- 使用之前,需要require引入
官方文档:
文件操作:
写文件
// 文件的写操作
const fs = require('fs')
// 清空写入,写之前会把之前的内容清空
// fs.writeFile('文件路径', '写入内容', 回调函数),没有文件自动创建
fs.writeFile('./1.txt', '曾经有一首歌,她感动了我', (err) => {
if (err) throw err
console.log('写入成功')
})
读文件
const fs = require('fs')
const path = require('path')
// 读文件
// 指定目标文件所在的路径
// var filename = __dirname + '/1.txt'
var filename = path.join(__dirname, '1.txt')
// 语法:fs.readFile('文件路径', 回调函数)
fs.readFile(filename, (err, data) => {
if (err) throw err
// data 是二进制数据,默认输出时,以十六进制的方式展示
console.log(data.toString())
})
删除文件(unlink)
const fs = require('fs')
// 语法: fs.unlink('文件路径', 回调函数)
fs.unlink(__dirname+'/1.txt', (err) => {
if (err) throw err
console.log('删除成功')
})
追加写入(append)
下列代码逻辑有误,后期待纠正
const fs = require('fs')
// 追加写入
// 语法: fs.appendWrite('文件路径','写入内容', 回调函数)
// fs.appendFile(__dirname+'/2.txt', '曾经有一首歌,她是这样唱的\n', (err) => {
// if (err) throw err
// console.log('追加写入成功')
// })
// 有数组a
var a = ['白石定规', '魔女之旅', '伊蕾娜']
/**
* 通过 appendFile 实现如下写入
* 数据1
* 数据2
* 数据3
*/
for(var i = 0; i < a.length; i++){
fs.appendFile(__dirname+'/2.txt', a[i]+"\n", (err) => {
if (err) throw err
console.log('数据'+i+'追加写入成功')
})
}
目录操作
创建新目录
const fs = require('fs')
// 创建目录
// 语法:fs.mkdir('目录路径', 回调函数)
fs.mkdir('./d1', (err) => {
if (err) throw err
console.log('创建成功')
})
删除目录
const fs = require('fs')
// 删除目录
// 语法: fs.rmdir('目录路径', 回调函数)
fs.rmdir('./d1', (err) => {
if (err) throw err
console.log('删除成功')
})
// 声明: rmdir 只能删除空目录
// 1. 先删除目录下的普通文件(清空目录)
// 2. 通过 rmdir 删除空目录
重命名目录
const fs = require('fs')
// 重命名目录
// 语法: fs.rename(旧名称, 新名称, 回调函数)
fs.rename(__dirname+'/d1', __dirname+'/d2', (err) => {
if (err) throw err
console.log('重命名成功')
})
读目录
const fs = require('fs')
// 读目录
// 语法:fs.readdir('目录路径', 回调函数)
fs.readdir(__dirname, (err, data) => {
if (err) throw err
// console.log(data)
data.map((d) => {
// console.log(d)
fs.stat(__dirname+"/"+d, (err, stat) => {
if (err) throw err
if (stat.isDirectory()) {
// 判断当前文件是否是目录
console.log('目录:', d)
} else if (stat.isFile()) {
// 判断当前文件是否是普通文件
console.log('文件:', d)
}
})
})
})
fs同步函数
- 同步函数
- 在主程序中自上而下运行
- 例如:火车站排队买票
- 异步函数
- 通过回调函数在事件队列中运行
- 例如:委托人买票,买好通知
const fs = require('fs')
// 先判断文件是否存在
// 然后,如果文件存在的化,再执行删除
if (fs.existsSync(__dirname+"/1.txt")) {
fs.unlinkSync(__dirname+"/1.txt")
} else {
console.log('文件不存在')
}
fs:实现文件的复制和压缩
要求:
const fs = require('fs')
const path = require('path')
// 把 src/style.css 复制到 dist/ 目录下
const dist = path.join(__dirname, 'dist')
fs.readFile('./src/style.css', (err, data) => {
if (err) {
throw err
} else {
console.log(data.toString())
// 确保 dist 目录存在
if (!fs.existsSync(dist)) {
fs.mkdirSync(dist)
}
// 对文件进行压缩: 将无用的注释或空格去掉
// /* 注释的内容 */
var mydata = data.toString().replace(/\s+/g, '').replace(/\/\*{1,2}[\s\S]*\*\//g, '')
// 将读到的内容,写入目标文件
fs.writeFile(dist+'/style.min.css', mydata, (err) => {
if (err) throw err
console.log('成功')
})
}
})
文件流
- 内存效率会提高
- 无需加载大量数据
- 流把大数据切成小块,占用内存更少
- 时间效率高
- 接获数据后立即开始处理
- 无需等到内存缓冲填满
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引入
- 官方文档
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中每一个单独的js文件,就是一个模块
- 每一个模块中都有一个module变量,代表当前模块
- module的exports属性是对外的接口
- 只有导出的(module.exports)的属性或方法才能被外部调用
- 未导出的内容是模块私有,不能被外部访问
-
使用时,通过require引入
引入文件模块
const circle = require('./circle')
模块的加载逻辑
-
按照组织方式划分模块
- 目录模块的加载逻辑
package.json是目录模块的描述文件
如果没有package.json,默认文件就是index.js,都没有就报错
第三方模块
- 社区维护的Node.js模块
- 想要使用需要单独安装
npm(node.js包管理工具)
- 测试npm
npm --version
npm可以安装包和包的依赖
-
为了提高npm上的包的下载速度,使用淘宝镜像,命令:
使用npm安装包
npm install <pack-name>
全局安装
npm install <package-name> --global
npm i <package-name> -g
- 明确需求
- 找到合适的包
- 通过npm安装包
- 使用包
局部安装
- 创建项目目录(mkdir project)
- 进入项目目录(cd project)
- 初始化项目(npm init)
- 在项目中安装包
npm install <package-name> --save
npm i <package-name> -S
初始化项目
npm init
会进行一系列npm初始化提问,之后出现json文件将你的内容进行整理,局部安装的npm包在.\node_modules.bin\npm包,指令也是在这个地址之下使用
--save 和 --save-dev
-- save对应dependencies
-- dev 对应devDenpendencies