一、Node.js 入门
1. 什么是 Node.js?
2. 什么是前端工程化?
3. Node.js 为何能执行 JS?
4. Node.js 安装
5. 使用 Node.js
总结
6. fs 模块 - 读写文件
/**
* 目标:基于 fs 模块 读写文件内容
* 1. 加载 fs 模块对象
* 2. 写入文件内容
* 3. 读取文件内容
*/
// 1. 加载 fs 模块对象
const fs = require('fs')
// 2. 写入文件内容
fs.writeFile('./text.txt', 'Hello,node.js', err => {
if(err) console.log(err)
else console.log('写入成功')
})
// 3. 读取文件内容
fs.readFile('./text.txt', (err, data) => {
if(err) console.log(err)
// data 是 buffer 16 进制数据流对象
// .toString() 转换成字符串
else console.log(data.toString())
})
7. path 模块 - 路径处理
8.path 模块 - 路径处理
/**
* 目标:在Node.js环境的代码中,应使用绝对路径
* 原因:代码的相对路径是以终端所在文件夹为起点,而不是Vscode资源管理器
* 容易造成目标文件找不到的错误
*/
const fs = require('fs')
// 1.引入path模块对象
const path = require('path')
// 2.调用path.join()配合__dirname组成目标文件的绝对路径
console.log(__dirname)
fs.readFile(path.join(__dirname, '../text.txt'), (err, data) => {
if (err) console.log(err)
else console.log(data.toString())
})
9. 案例 - 压缩前端 html
// 1.1 读取源 html 文件内容
const fs = require('fs')
const path = require('path')
fs.readFile(path.join(__dirname, 'public/index.html'), (err, data) => {
if (err) console.log(err)
else {
const htmlStr = data.toString()
// 1.2 正则替换字符串
const resultStr = htmlStr.replace(/[\r\n]/g, '')
console.log(resultStr)
// 1.3 写入到新的 html 文件中
// writeFile方法没有文件可以自动创建,但是不能自动创建文件夹(自己手动创建)
fs.writeFile(path.join(__dirname, 'dist/index.html'), resultStr, err => {
if (err) console.log(err)
else console.log('写入成功')
})
}
})
10.URL 中的端口号
协议+域名+端口号+资源路径
10.常见的服务程序
总结
11. http 模块-创建 Web 服务
/**
* 目标:基于 http 模块创建 Web 服务程序
* 1.1 加载 http 模块,创建 Web 服务对象
* 1.2 监听 request 请求事件,设置响应头和响应体
* 1.3 配置端口号并启动 Web 服务
* 1.4 浏览器请求(http://localhost:3000)测试
*/
// 1.1 加载 http 模块,创建 Web 服务对象
const http = require('http')
const server = http.createServer()
// 1.2 监听 request 请求事件,设置响应头和响应体
server.on('request', (req, res) => {
// 设置响应头-内容类型-普通文本以及中文编码格式
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
// 设置响应体内容,结束本次请求与响应
res.end('欢迎使用 Node.js 和 http 模块创建的 Web 服务')
})
// 1.3 配置端口号并启动 Web 服务
server.listen(3000, () => {
console.log('Web 服务启动成功了')
})
运行结果:
ctrl+c 结束进程
cls清空
案例:浏览时钟
需求:基于 Web 服务,开发提供网页资源 的功能
/**
* 目标:基于 Web 服务,开发提供网页资源的功能
* 步骤:
* 1. 基于 http 模块,创建 Web 服务
* 2. 使用 req.url 获取请求资源路径,并读取 index.html 里字符串内容返回给请求方
* 3. 其他路径,暂时返回不存在提示
* 4. 运行 Web 服务,用浏览器发起请求
*/
const fs = require('fs')
const path = require('path')
// 1. 基于 http 模块,创建 Web 服务
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
// 2. 使用 req.url 获取请求资源路径,并读取 index.html 里字符串内容返回给请求方
if (req.url === '/index.html') {
fs.readFile(path.join(__dirname, 'dist/index.html'), (err, data) => {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end(data.toString())
})
} else {
// 3. 其他路径,暂时返回不存在提示
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end('你要访问的资源路径不存在')
}
})
server.listen(8080, () => {
console.log('Web 服务启动成功了')
})
二、Node.js 模块化
1.什么是模块化?
2.CommonJS 标准
utils.js
/**
* 目标:基于 CommonJS 标准语法,封装属性和方法并导出
*/
const baseURL = 'http://hmajax.itheima.net'
const getArraySum = arr => arr.reduce((sum, item) => sum += item, 0)
// 导出
module.exports = {
url: baseURL,
arraySum: getArraySum
}
index.js
/**
* 目标:基于 CommonJS 标准语法,导入工具属性和方法使用
*/
// 导入
const obj = require('./utils.js')
console.log(obj)
const result = obj.arraySum([5,1,2,3])
console.log(result)
总结
3.ECMAScript 标准 - 默认导出和导入
需求:封装并导出基地址和求数组元素和的函数
默认标准使用:
1.导出:export default {}
2.导入:import 变量名 from '模块名或路径'
注意:Node.js 默认支持 CommonJS 标准语法
如需使用 ECMAScript 标准语法,在运行模块所在文件夹新建 package.json 文件,并设置 { "type" : "module" }
练习:
总结
4. ECMAScript 标准 - 命名导出和导入
utils.js
/**
* 目标:基于 ECMAScript 标准语法,封装属性和方法并"命名"导出
*/
export const baseURL = 'http://hmajax.itheima.net'
export const getArraySum = arr => arr.reduce((sum, item) => sum += item, 0)
index.js
/**
* 目标:基于ECMAScript 标准语法,'命名'导入
* 工具属性和方法使用
*/
// 命名导入
import {baseURL, getArraySum} from './utils.js'
console.log(baseURL)
console.log(getArraySum)
const result = getArraySum([10, 20, 33])
console.log(result)
package.json
{
"type": "module"
}
总结
5.包的概念
- 包:将模块,代码,其他资料聚合成一个文件夹
- 包分类:
✓ 项目包:主要用于编写项目和业务逻辑
✓ 软件包:封装工具和方法进行使用 - 要求:根目录中,必须有 package.json 文件(记录包的清单信息)
- 注意:导入软件包时,引入的默认是 index.js 模块文件 / main 属性指定的模块文件
- 需求:封装数组求和函数的模块,判断用户名和密码长度函数的模块,形成成一个软件包
总结
6.npm - 软件包管理器
server.js
/**
* 目标:使用npm 下载 dayjs 软件包,来格式化日期时间
* 1. 初始化清单文件 :npm init -y(得到 package.json 文件,有则略过此命令)
* 2. 下载软件包 :npm i 软件包名称
* 3. 使用软件包
*/
// 3. 使用软件包
const dayjs = require('dayjs')
const nowDateStr = dayjs().format('YYYY-MM-DD')
console.log(nowDateStr)
总结
7.npm - 安装所有依赖
问题:项目中不包含 node_modules,能否正常运行?
答案:不能,缺少依赖的本地软件包
原因:因为,自己用 npm 下载依赖比磁盘传递拷贝要快得多
解决:项目终端输入命令:npm i
下载 package.json 中记录的所有软件包
总结
8.npm - 全局软件包 nodemon
软件包区别:
➢ 本地软件包:当前项目 内使用,封装属性和方法 ,存在于 node_modules
➢ 全局软件包:本机 所有项目使用,封装命令和工具 ,存在于系统设置的位置
nodemon 作用:替代 node 命令,检测代码更改,自动重启程序
使用:
1.安装:npm i nodemon -g(-g 代表安装到全局环境中)
2.运行:nodemon 待执行的目标 js 文件
需求:启动准备好的项目,修改代码保存后,观察自动重启应用程序
总结
9.Node.js 总结
三、Webpack
1.什么是 Webpack?
2.使用 Webpack
3.修改 Webpack 打包入口和出口
Webpack 配置(https://webpack.docschina.org/concepts/#entry):影响 Webpack 打包过程和结果
步骤:
- 项目根目录,新建 webpack.config.js 配置文件
- 导出配置对象,配置入口,出口文件的路径
- 重新打包观察
注意:只有和入口产生直接/间接的引入关系,才会被打包
webpack.config.js
js
const path = require('path');
module.exports = {
// 入口
entry: path.resolve(__dirname, 'src/login/index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: './logon/index.js',
clean: true //生成打包内容之前,清空输出目录
},
};
4.案例:用户登录 - 长度判断
需求:点击登录按钮,判断手机号和验证码长度
步骤:
1.准备用户登录页面
2.编写核心 JS 逻辑代码
3.打包并手动复制网页到 dist 下,引入打包后的 js,运行
核心:Webpack 打包后的代码,作用在前端网页中使用
5.自动生成 html 文件
插件 html-webpack-plugin: 在 Webpack 打包时生成 html 文件
步骤:
1.下载 html-webpack-plugin 本地软件包
2.配置 webpack.config.js 让 Webpack 拥有插件功能
3.重新打包 观察效果
6.打包 css 代码
加载器 css-loader:解析 css 代码
加载器 style-loader:把解析后的 css 代码插入到 DOM
步骤:
1.准备 css 文件代码 引入到 src/login/index.js 中(压缩转译处理等)
2.下载 css-loader 和 style-loader 本地软件包
3.配置 webpack.config.js 让 Webpack 拥有该加载器功能
- 打包后观察效果
注意:Webpack 默认只识别 js 代码
7.优化-提取 css 代码
插件 mini-css-extract-plugin:提取 css 代码
步骤:
1.下载 mini-css-extract-plugin 本地软件包
2.配置 webpack.config.js 让 Webpack 拥有该插件功能
3.打包后观察效果
注意:不能和 style-loader 一起使用
好处:css 文件可以被浏览器缓存,减少 js 文件体积
8.优化-压缩过程
问题:css 代码提取后没有压缩
解决:使用 css-minimizer-webpack-plugin 插件
步骤:
1.下载 css-minimizer-webpack-plugin 本地软件包
2.配置 webpack.config.js 让 webpack 拥有该功能
- 打包重新观察
9.打包 less 代码
加载器 less-loader:把 less 代码编译为 css 代码
步骤:
1.新建 less 代码(设置背景图)并引入到 src/login/index.js 中
2.下载 less 和 less-loader 本地软件包
3.配置 webpack.config.js 让 Webpack 拥有功能
4.打包后观察效果
注意:less-loader 需要配合 less 软件包使用
10.打包图片
11、搭建开发环境
问题:之前改代码,需重新打包才能运行查看,效率很低
开发环境:配置 webpack-dev-server 快速开发应用程序
作用:启动 Web 服务,自动 检测代码变化,热更新到网页
注意:dist 目录和打包内容是在内存里(更新快)
步骤:
- 下载 webpack-dev-server 软件包到当前项目
- 设置模式为开发模式 ,并配置自定义命令
- 使用 npm run dev 来启动开发服务器,试试热更新效果
注意1:webpack-dev-server 借助 http 模块创建 8080 默认 Web 服务
注意2:默认以 public 文件夹作为服务器根目录
注意3:webpack-dev-server 根据配置,打包相关代码在内存当中,以 output.path 的值作为服务器根目录(所以可以直接直接拼接访问dist目录下内容)
12、打包模式
打包模式:告知 Webpack 使用相应模式的内置优化
分类:
设置:
方式1:在 webpack.config.js 配置文件设置 mode 选项
方式2:在 package.json 命令行设置 mode 参数
注意:命令行设置的优先级高于配置文件中的,推荐用命令行设置
将css文件放入login中
webpack.config.js
js
// 插件(给webpack提供更多功能)
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, 'public/login.html'), //模板文件
filename: path.resolve(__dirname, 'dist/login/index.html') //输出文件
}),
new MiniCssExtractPlugin({
filename: './login/index.css' //放入login中
}) //生成css文件
],
13、打包模式的应用
需求:在开发模式下用 style-loader 内嵌更快,在生产模式下提取 css 代码
方案1:webpack.config.js 配置导出函数,但是局限性大(只接受 2 种模式)
方案2:借助 cross-env (跨平台通用)包命令,设置参数区分环境
步骤:
1.下载 cross-env 软件包到当前项目
2.配置自定义命令,传入参数名和值(会绑定到 process.env 对象下)
3.在 webpack.config.js 区分不同环境使用不同配置
4.重新打包观察两种配置区别
方案3:配置不同的 webpack.config.js (适用多种模式差异性较大情况)
14、前端-注入环境变量
需求:前端 项目中,开发模式下打印语句生效,生产模式下打印语句失效
问题:cross-env 设置的只在 Node.js 环境生效,前端代码无法访问 process.env.NODE_ENV
解决:使用 Webpack 内置的 DefinePlugin 插件
作用:在编译时,将前端代码中匹配的变量名,替换为值或表达式
15、开发环境调错 - source map
问题:代码被压缩和混淆,无法正确定位源代码位置(行数和列数)
source map:可以准确追踪 error 和 warning 在原始代码的位置
设置:webpack.config.js 配置 devtool 选项
inline-source-map 选项:把源码的位置信息一起打包在 js 文件内
注意:source map 仅适用于开发环境,不要在生产环境使用(防止被轻易查看源码位置)
16、解析别名 alias
解析别名:配置模块如何解析,创建 import 引入路径的别名,来确保模块引入变得更简单
例如:原来路径如图,比较长而且相对路径不安全
解决:在 webpack.config.js 中配置解析别名 @ 来代表 src 绝对路径
17、优化-CDN使用
CDN定义:内容分发网络,指的是一组分布在各个地区的服务器
作用:把静态资源文件/第三方库放在 CDN 网络中各个服务器中,供用户就近请求获取
好处:减轻自己服务器请求压力,就近请求物理延迟低,配套缓存策略
需求:开发模式 使用本地 第三方库,生产模式 下使用 CDN 加载 引入
需求:开发模式使用本地第三方库,生产模式下使用 CDN 加载引入
步骤:
- 在 html 中引入第三方库的 CDN 地址 并用模板语法判断
- 配置 webpack.config.js 中 externals 外部扩展选项(防止某些 import 的包被打包)
- 两种模式下打包观察效果
18、多页面打包
单页面:单个 html 文件,切换 DOM 的方式实现不同业务逻辑展示,后续 Vue/React 会学到
多页面:多个 html 文件,切换页面实现不同业务逻辑展示
需求:把黑马头条-数据管理平台-内容页面一起引入打包使用
步骤:
1.准备源码 (html,css,js)放入相应位置,并改用模块化语法导出
2.下载 form-serialize 包并导入 到核心代码中使用
3.配置 webpack.config.js 多入口 和多页面 的设置
4.重新打包观察效果
19、案例-发布文章页面打包
需求:把发布文章页面一起打包
步骤:
- 准备发布文章页面源代码,改写成模块化的导出和导入方式
- 修改 webpack.config.js 的配置,增加一个入口和出口
- 打包观察效果
20、优化-分割公共代码
需求:把 2 个以上页面引用的公共代码提取
步骤:
- 配置 webpack.config.js 的 splitChunks 分割功能
- 打包观察效果
除了CDN外还有http://unpkg.comhttp://unpkg.com