前端工程化概述,Node.js基础

前端工程化简介

工程就是一个项目(比如一个网站或者app)

一个工程的生命周期

一个工程的生命周期

工程化就是项目完成过程中,用到的各种工具和技术

前端工程化

  • 前端工程化就是通过各种工具和技术,提高前端开发效率的过程
    • 前端工程化的内容:各种工具和技术
    • 前端工程化的作用:通过使用工具,提高开发效率

前端工程化的内容

兼容性查阅

www.caniuse.com

比如查看ES6标准兼容性:


ES6支持浏览器

前端工程化解决的问题

  • 项目上线前,压缩代码
  • 对ES6+或者CSS3新特性转换
  • 对less等css的预编译语言进行编译处理
    ...


前端工程化包含的内容

工程化≠某个工具

node.js

  • 基于chrome的V8引擎的JavaScript运行环境
  • 不是新语言,也不是JavaScript的新框架

node.js能做什么?

负责后端的功能

  • 为网站,app,小程序提供数据服务

开发前端方向的工具

  • 各种前端工程化的工具
    用作桌面应用开发

  • 各种跨平台的应用


node.js APIs


web和Node的交集和区别

安装node.js

www.nodejs.org

  • 下载安装一路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)
      在主进程结束后立即执行

node.js模块

  • 内置模块(官方提供的,跟随node.js一起安装)

http://nodejs.cn/api/

  • 自定义模块(工程师自己写的)
  • 第三方模块(社区维护的,需要单独下载才能使用)

https://www.npmjs.com/


内置模块,也叫核心模块

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引入
    官方文档:

http://nodejs.cn/api/fs.html

文件操作:

写文件
// 文件的写操作
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引入
  • 官方文档

http://nodejs.cn/api/http.html

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模块
  • 想要使用需要单独安装

https://www.npmjs.com/

npm(node.js包管理工具)

  • 测试npm
npm --version

npm可以安装包和包的依赖

非常方便的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

总结:

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

推荐阅读更多精彩内容