require()引入
核心模块
require('http');//引入http模块
引入的模块会先从当前目录node_modules找,没有继续往上一级目录找,直到根目录,没有则报错
文件模块
一个模块就是一个js文件
引入的是路径必须以 ./ 或 ../ 开头
引入后返回一个对象,返回的就是引入模块的返回值
var md = require('./02-module.js');// 引入本地模块 .js可以省略
每一个js文件模块都有一个文件作用域,无法返回引入模块的变量
exports 暴露给外部的变量
exports.变量名 = '';// 另一个文件即可访问该变量
引入自定义模块
1、node_modules下文件夹名字为模块名字, require引入文件夹名字
2、nodejs会自动找到文件夹下的index.js文件。如果不是index会报错
3、修改模块文件夹下package.json 的main参数可以设置引入时的index为其他名字
模块的参数
console.log(arguments.callee + ''); 当前函数 + '' 隐式调用toString
/*
函数最开始添加此代码
function (exports, require, module, __filename, __dirname) {
console.log(arguments.callee + '');
函数结尾添加此代码
}
实际上模块中运行的代码都包装在一个函数中,并在执行时传递5个实参
require
函数,用来引入外部的模块
exports
将对象或变量暴露到外部
module
module代表这个函数的本身
exports就是module的属性
既可以使用module.exports 导出,也可以使用exports导出
module.exports == exports;// true
__filename
e:\PHPnow-1.5.6\htdocs\OneDrive\Web\资料\practice\09Node.js\01-createHttp.js
当前文件所在路径
__dirname
e:\PHPnow-1.5.6\htdocs\OneDrive\Web\资料\practice\09Node.js
当前文件夹所在路径
*/
exports
exports是module.exports的引用,module.exports是真实存在的,最终返回的是module.exports
可以用
exports.name = 'xx';
// 不可用
exports = { /* 代码 */ }
赋值对象会改变引用地址,实际的 module.exports 对象内的值并没有被修改
// 可用
module.exports.name = 'xx';
// 可用
module.exports = {/* 代码 */}
module = { exports: {} };
exports = module.exports;
exports.age = 22;
console.log(exports, module.exports);
module.exports = {};
console.log(exports, module.exports);
package.json
dependencies:{} 依赖,此包依赖另外的哪些包 类型jq插件依赖jq
description : '' 描述
devDependencis : {} 开发环境依赖,生成环境不依赖
homepage : 'http...' 主页
license : '' 权限
main:''主文件
maintainers : {} 主要贡献者
contributors : 维护者
bugs :提交bug地址
name : '' 包的名字
version : 版本
keywords 关键字
repositories :仓库
os : 系统
"scripts": {
"start": "node ./bin/www", // 用 npm start 启动www.js 只有键为start可以省略 run
"dev":"nodemon ./bin/www" // 用npm run dev 启动 www.js
}
dos指令
dir: 显示当前目录中的内容
cd: 切换目录
盘符冒号: 切换盘符
cls: 清屏
mkdir : 创建目录
rmdir: 删除目录
. 代表当前目录 .. 代表上级目录
npm指令
npm -v //查看版本
npm -version //查看npm模块所有版本
npm //帮助说明
npm search 包名 //搜索模块
npm install 包名 //在当前目录安装模块
简写 npm i 包名
npm install 包名 -g //在全局模式安装包
npm install 包名 --save //安装包并添加到依赖中 cnpm必须要加—save
npm install 包名 -S //安装包并添加到依赖中
npm install //下载package依赖的包
npm remove 包名 //删除一个模块
简写 npm remove 包名
npm uninstall 包名 //删除
npm install 文件路径 //本地安装一个路径
npm install 包名 --registry=地址 //从镜像源安装
npm config set registry 地址 //设置镜像源
将npm服务器切到国内淘宝服务器(镜像服务器),在dos小黑窗中分别执行下面的命令:
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
npm init --yes //当前目录强制生成package.json
npm init [-y] //自动生成
packge.json:
"scripts": {
"start": "node ./bin/www", // 用 npm start 启动www.js 只有键为start可以省略 run
"dev":"nodemon ./bin/www" // 用npm run dev 启动 www.js
}
Buffer 缓冲区
// 创建一个10字节的buffer,长度一旦确定不能更改
var buf = Buffer.alloc(10);
// 转成16进制存入
buf[0] = 88;// <Buffer 58 00 00 00 00 00 00 00 00 00>
buf[1] = 0xaa; //<Buffer 58 aa 00 00 00 00 00 00 00 00>
buf[10] = 11;// 没有第十位 设置没效果
buf[3] = 256; // 00
/* 最大255,255转16进制是ff; 256 二进制1后面八个0,存的时候取二进制后8位,二进制8个0还是16进制00 */
console.log(buf[1]);// 170 0xaa 控制台打印是10进制
console.log(buf[1].toString(16)); //aa 16进制输出
var buf1 = Buffer.allocUnsafe(10); //<Buffer 31 34 11 c9 bf 02 00 00 49 34>
// allocUnsafe 创建10字节,但是不清空内存,之前别的程序使用的内存信息在这里面.可能有敏感信息
Buffer.from(str);//将字符串转换成Buffer 储存
base64存储
let buf = Buffer.from('字符').toString('base64'); // 存储,转换成base64
console.log(buf);//5a2X56ym
let buf1 = Buffer.from(buf,'base64');// buf是字符串 第二个参数以base64存储
console.log(buf1.toString('utf-8'));//字符
Buffer.alloc(size);//创建一个指定大小的Buffer
Buffer.allocUnsafe(size);//创建一个指定大小的buffer,可能包含敏感数据
buf.toString();//将缓冲区的数据转换成字符串
Buffer.allocUnsafeSlow(size);//慢,不安全的分配空间
Buffer.byteLength(string, 'utf8');//获取一个字符串占用内存的大小,默认utf-8
Buffer.compare(buf1, buf2);//比较两个Buffer是否是同一个
Buffer.concat([buf1,buf2]);//连接多个Buffer
Buffer.isBuffer(obj);//是否是一个Buffer 返回 true/false
Buffer.isEncoding(encoding);//返回是否支持encoding true/false
Buffer.isEncoding('utf-8');//true
Buffer.isEncoding('utf/8');//false
Buffer.poolSize ;//缓冲池的预分配的内部 Buffer 实例的大小(以字节为单位)可以修改
文件系统 (File System)
方法
fs.existsSync(path);//检查一个文件是否存在 返回true/false 不能检查目录
fs.stat(path,(e,stat) => { //是文件还是目录
stat.size;//文件大小
stat.isFile();// 是否是文件
stat.isDirectory();//是否是目录
})
fs.readFileSync(path);// 读取文件 文件不存在会报错
fs.writeFileSync(path,'123');// 写入文件(覆盖) 返回undefined 文件不存在会自动创建
fs.unlinkSync(path); // 删除文件 返回undefined 不存在会报错
fs.readdirSync(path[, options]);// 读取目录下的所有文件名 返回数组
fs.truncateSync(path[, len])// 截断文件 把文件设为3个字节,后面的内容截断 不存在会报错
fs.mkdirSync(path[, options])// 新建文件夹 已存在会报错
fs.rmdirSync(path[, options])// 删除文件夹 文件夹内有文件会报错 不存在会报错
fs.renameSync(oldPath, newPath)// 重命名 文件/目录名 旧路径至新路径可以实现移动文件
// 监听文件
fs.watchFile(filename[, options], listener)
filename 监听的文件名
options 配置
interval:1000 每隔1秒监听一次
listener 回调函数,当文件发生变化时,回调函数会执行;会有两个参数
curr 当前文件的状态
prev 修改前文件的状态
这两个对象都是stats对象
fs.watchFile('hello.txt',{interval : 1000},function(curr,prev){
console.log('修改前文件大小' + prev.size);
console.log('修改后文件大小' + curr.size);
})
流式文件读取
let rs = fs.createReadStream(path);//创建可读流
let ws = fs.createWriteStream(path);//创建可写流
rs.pipe(ws);// 可读流传输到可写流
rs.on('open',() => {});//可读流打开
rs.once('close',() => {}); //可读流关闭 可读流关闭后 调用 rs.end()
ws.on('open',() => {});// 可写流打开
ws.once('close', () => {});// 可写流关闭
rs.on('data',function(data){
console.log(data.length);//查看每次读取到的字节
ws.write(data);// 写入读取到的data
})
flag操作符
r 读取文件,文件不存在则出现异常
r+ 读写又件,又件不存在则出现异常
rs 在同步模式下打开文件用于读取
rs+ 在同步模式下打开文件用于读写
w 打开文件用于写操作如果不存在则创建,如果存在则酸断
wx 打开文件用于写操作如果存在则打开失败
w+ 打开文件用于读写如果不存在则创如果存在则载断
wx+ 打开文件用于读写如果存在则打开失败
a 打开丈件用于遍加如果不存在则创建
ax 打开文件用于追加如果路径存在则失败
a+ 打开文件进行读取和追加如果不存在则创建该文件
ax+ 打开文件进行读取和追加如果路径存在则失败
url
返回与传统parse一样的对象
const u = new URL('https://www.baidu.com:8080?abc=ca&cb=qw#aa');
判断某个字符串是否是以指定的字符开头: startsWith() 字符串. startsWith(‘/ad’)
url.parse('https://www.baidu.com:8080/api.php?from=qian&soucces=123#lenst1',true)
返回一个对象,其中query键为?后面查询的字符串
// 参数1 地址
// 参数2 是否对?后面的解析成对象,false不解析,就是字符串
// 参数3 在地址不知道http协议下,传入true(protocol\slashes\auth\host\port\hostname)可以解析,不传都是null
Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'www.baidu.com:8080',
port: '8080',
hostname: 'www.baidu.com',
hash: '#lenst1',
search: '?from=qian&soucces=123',
query: 'from=qian&soucces=123',
pathname: '/api.php',
path: '/api.php?from=qian&soucces=123',
href: 'https://www.baidu.com:8080/api.php?from=qian&soucces=123#lenst1'
}
//将url对象解析成地址
url.format({protocol: 'https:',slashes: true,auth:...等});
// https://www.baidu.com:8080/api.php?from=qian&soucces=123#lenst1
// 将两端url解析成一个完整的url
url.resolve('http://www.baidu.com','/api/list.php');
// http://www.baidu.com/api/list.php
querystring
querystring.stringify(obj[, sep[, eq[, options]]]) 将对象转换成字符串
obj 对象
sep 键值对与键值对 之间的连接符号 默认'&'
eq 键与值之间连接符号 默认'='
querystring.parse(str[, sep[, eq[, options]]]) 将字符串转换成对象
与字符串同理
querystring.escape(str) //将字符串转换成字符编码
querystring.unescape(str)//将字符编码转换成字符串
http
创建服务器
const http = require('http');
const server = http.createServer();//创建服务器
// [参数1:配置信息][参数2:fun(request请求,response相应)]
// 返回 hppt.server对象
// 返回的对象,监听 req请求
server.on('request',(req,res) => {
// request:浏览器请求信息 response:返回响应信息
// 设置头文件 防止乱码
res.writeHead(200,'ok',{'content-type' : 'text/html;charset=utf-8;'});
// 参数1:200 [参数2:备注信息][参数3:配置信息,设置utf-8] 返回ServerResponse可用链式调用
res.setHeader('content-type','text/html;charset=utf-8;');
// 设置单个响应头的值 同上
res.write('返回1'); // 返回响应的信息,可调用多次
res.end('结束'); // 结束响应,必须、且只能调用一次;后续的代码不会执行
});
// 参数1:设置端口号 [参数2:回调]
server.listen(8888,() =>{
console.log('server at 8888');
})
设置允许跨域
app.all('*', function(req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型
res.header('Access-Control-Allow-Headers', 'Content-type');
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS,PATCH");
next();
});
events
const events = require('events');
// 需要先new构造函数
const eventsEmiter = new events();
eventsEmiter.on('aa',() => {
console.log('自定义事件');
})
eventsEmiter.emit('aa');//调用
eventsEmiter.once('cc',() => {
console.log('自能调用一次后失效');
})
eventsEmiter.emit('cc');//只能调用一次
path 路径
const path = require('path');
path.extname('javascript.min.js');// .js 获取文件名后缀
// 多个路径拼接成完整的绝对路径
path.resolve('a/b','he/','index.js')
// 将多个路径合并为一个
// e:\PHPnow-1.5.6\htdocs\OneDrive\Web\a\b\he\index.js
path.resolve('a/b','../','index.js');
// ../会返回上一目录
// e:\PHPnow-1.5.6\htdocs\OneDrive\Web\a\index.js
path.resolve('a/b','/cc','index.js');
// /开头会从根目录开始
// e:\cc\index.js
// 多个路径拼接成绝对路径,根据当前系统使用分隔符 window使用 /分隔 Linux使用\分隔
path.join('a/b','c/d/index.js')
// a\b\c\d\index.js
path.join('a/b','/ad','index.js')
// a\b\ad\index.js
express
const express = require('express');
const app = express();
app.listen('3000'); // 监听端口
独立功能和功能数组的组合
var cb0 = function (req, res, next) {
console.log('CB0')
next()
}
var cb1 = function (req, res, next) {
console.log('CB1')
next()
}
多个函数 next()
app.get('/example/d', [cb0, cb1], function (req, res, next) {
console.log('the response will be sent by the next function ...')
next()
}, function (req, res) {
res.send('Hello from D!')
})
Router()
const express = require('express');
const route = express.Router();
route.get('/',(req,res) => {})
exports = route; 对外暴露
//引入上面模块中间件调用
app.use(route);
use中间件
// 中间件 在请求之后,响应之前触发
一般写在路由之前
app.use((req,res,next) => {
// 代码块
next();//next是一个函数 查找后面匹配的路由,执行
})
错误处理中间件
app.use(req, res, () => {
if (0) {
next();
} else { //错误
//当给next()方法传参数会自动执行含有err、req、res、next四个参数的中间件(错误处理中间件)
next('error message');
}
})
//错误处理中间件
app.use((err, req, res, next) => {
res.end(err);
});
static静态资源托管
// app.use([path],callback)
app.use(express.static(path.resolve(__dirname,'小U商城PC版')));// 静态资源托管
// 访问的第二个参数为images下的文件,html文件请求会是images下的/images。所以第一个参数path加上images
app.use('/images',express.static(path.resolve(__dirname,'小U商城PC版','images')));
app.use('/css',express.static(path.resolve(__dirname,'小U商城PC版','css')))
get接参query、params
// get请求 path路径支持正则
app.get('/api/:a/:b',(req,res) => {});
接参
1、查询字符串格式: res.query
2、path路径格式:路径改为 /:变量名/:变量名 , 回调函数获取 : req.params 得到对象
res.send(data);//发送数据
res.sendFile(path);//发送文件
// all方法后面的路由不会再执行,一般写在最后匹配所有
app.all('*',(req,res) => {res.end('404 页面找不到')});
post接参urlencoded
// POST调用中间件接参
app.use(express.urlencoded({extended : true}))
app.post('/app', (req, res) => {
console.log(req.body);
})
第三方中间件
cookie-parser
设置cookie
res.cookie('key', 'value');
获取cookie
const cookieParser = require('cookie-parser');
app.use(cookieParser());//中间件调用
app.get('/get',(req,res) => {
req.cookies; //获取
// res.cookie(key,value,[option]);//设置
res.cookie('键','值',{
maxAge : '多少毫秒后过期',
expires : '过期的时间戳',
httpOnly : true, // 是否只能服务端访问,默认false
path : '固定路径才能访问',
domain : '固定域名才能访问'
})
})
cookie-session
const cookieSeesion = require('cookie-session');
app.use(cookieSeesion({
name:'key',//储存在cookie的键名
keys : ['12331a&&%#',"#&!^sa"]// 加密
}));
app.get('/get',(req,res){
req.session.name = '设置';
req.session;//获取
})
第三方库
ejs模板
npm i ejs 不需要require引入 直接用
app.set('view engine','ejs');// 固定两个参数语法,设置模板引擎为ejs
app.set('views',[path.resolve(__dirname,'lib')])// 设置路径位置,数组可以多个路径
app.engine('html',require('ejs').__express);// 告诉ejs用html文件解析
app.get('/',(req,res) => {
let name = '参数';
res.render('index.ejs',{name})//调用 传参
})
<% '脚本标签',流程开始
<%= 要输出的数据
<%# 注释
<%% 输出字符串%
%> 结束标签
<%- include('相对路径'); %>
express-generator项目生成器
npm i express-generator
express --view=ejs mydemo 在当前目录下创建
ejs模板 文件夹名称
进入这个文件夹 npm
i 安装依赖
目录列表
app.js 入口文件
bin/www 启动文件
views 模板文件
public 静态资源
routes router级别路由文件
配置以热更新方式启动项目
修改项目根下的package.json文件中的"scripts"配置项
"scripts": {
"start": "node ./bin/www",
"dev": "nodemon ./bin/www"
}
npm run dev运行 dev后面的代码
express操作MySQL
npm i mysql
const mysql = require('mysql');
// 创建连接
let dbObj = mysql.createConnection({
port: 3306,//端口号
host : localhost,//地址
user : root, //用户名
password : 'root',//密码 [注意]密码是数字也要双引号变成字符串,数字可能连接不上
database : mydemo,// 操作的数据库
charset : 'utf8',//链接的编码
connectTimeout : 1000//超时毫秒
});
// 发送连接
dbObj.connect();
// 执行语句
//sqly语句中 ? 为占位符 ,替换对应的参数1,参数2的变量 等
//let sql = `insert into classes(zhuanye,teacher)values(?,?)`; // [参数1,参数2]
dbObj.query(sql语句,[参数1,参数2...],(err,d) => {d/* d查询到的数据 */})
// 字符串拼接sql可以能会被sql注入,可以正则检验,或使用第二个参数
npm 包
svg-captcha生成验证码
const svgCaptcha = require('svg-captcha');
let captcha = svgCaptcha.create({
ignoreChars : 'ilo0',
color : true,
width : 100,
noise : 3
});
uuid生成唯一uid
const { v4: uuidv4 } = require('uuid');
uuidv4();
browserify后台代码编译成前端
npm i -g browserify
browserify 源文件[入口文件.js] -o 目标文件(编译之后的文件)
babel 将es6语法转换成es5
还可以操作jsx语法[react]。
npm i -g babel-cli 安装全局工具包
npm install babel-preset-es2015 --save-dev 开发目录下安装开发依赖
--save-dev 开发依赖(主要在开发阶段使用
在根目录下创建 .babelrc 文件
{"presets": ["es2015"]}
babel ./src[src为es6语法的目录] -d ./dest[转换成es5的目录]
[注意] 转换前源代码需要放在一个目录下,根目录创建.babelrc文件
socket.io协议/websocket
socket.emit('自定义事件名','消息内容'); //发送消息给某个客户端
socket.broadcast.emit('自定义事件名',‘消息内容’); //发送消息给除当前客户端外的其他客户端
io.emit('自定义事件名','消息内容'); //给所有客户端发送消息
socket.on('自定义事件名',回调函数); //接收消息
socket.handshake.query.房间号参数名 //接收房间号
socket.join(房间号,回调函数) //加入不同的房间
socket.to(房间号).emit('自定义事件名',‘消息内容’); //给指定房间号的所有客户端发送消息
服务端
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
const path = require('path');
server.listen(3000);
app.use(express.static(path.resolve(__dirname,'www')));
// 监听,但客服端发送请求触发
io.on('connection', (socket) => {
// 一建立连接就发给所有客户端
io.emit('back','所有的客户端都搜到消息')
// 接到消息后
socket.on('msg',(m) => {
console.log(m); //客户端发来的消息
socket.emit('back','返回给客户端的消息')
socket.broadcast.emit('back','广播消息,除了请求的客户端以外其他都能接搜到')
io.emit('back','所有的客户端都搜到消息')
})
});
客户端
启动服务后,服务端会在根目录创建socket.io.js,需要在客户端引入
<script src="/socket.io/socket.io.js"></script>
<script>
let socket = io(); // 执行io的构造函数
socket.emit('msg','发给服务端的消息');
socket.on('back',(m) => {
console.log(m);
})
</script>
es6模块化
单个暴露:
export let/var 属性名=属性值
export function 方法名(){ }
批量暴露:
let/var 属性名=值
function 方法名(){}
export {属性名,属性名 as 别名,方法名}
使用模块:
import {属性名,方法名,属性名 as 别名} from '模块文件名'
koa框架
npm i koa-generator -g 安装
koa2 -e(表示ejs模板) 项目文件夹名 新建项目
// 安装依赖
cd 项目文件夹名
npm i
// 启动热更新
npm run dev
koa与express的区别: 【重点】
1、ctx对象中封装的nodejs的request对象、response对象;
2、koa中使用级联操作替代express中的回调函数;
3、koa中没有中间件,express有中间件;
想使用这些中间件及包的话就选择express,
而koa追求的是性能及可定制性,如果项目中的功能都想自己来开发则选择koa
webpack
安装webpack@4版本与webpack-cli客户端
npm install webpack@4
webpack-cli -g
1、npm init -y 创建package.json文件
2、根目录新建 webpack.config.js 文件
配置信息
module.exports = {
entry : '', // 入口文件
output: '', // 输出文件
module : {}, // 处理对应模块
plugins: [], // 对应的插件
devServer : {}, // 开发服务器配置
mode : 'development', //模式配置
}
实例
webpack命令打包文件,只能打包js文件
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, './src/app.js'), //入口文件
output: {
path: path.resolve(__dirname, './dest'), //打包后的目录
filename: 'dabao.js' //打包后的文件名
},
}
插件
打包html文件
npm i html-webpack-plugin@4 -D 安装到开发依赖
const HtmlWebpackPlugin = require('html-webpack-plugin');
//设置插件配置项
module.exports = {
plugins: [
new HtmlWebpackPlugin({
//在src目录[项目目录]下创建一个index.html页面当作模板来使用
template: './src/index.html'
})
]
}
而index.html文件内容会增加一行内容:
<script type="text/javascript" src="打包后的.js"></script>
如果在打包过程中报如下的错误:
Error: Cannot
find module 'webpack/lib/node/NodeTemplatePlugin
安装
npm i webpack@4 -D
打包css到js文件内
npm i style-loader css-loader@3.6.0 -D
css-loader是负责解析css的[当使用插件拆分css时就不再需要style-loader]
style-loader将css以内部样式表的形式嵌入到html中
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
module: {
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader'] // loader就是要处理对应test规则的文件 loader的use规则,是从右向左处理
}]
}
}
打包外链css
npm i style-loader extract-text-webpack-plugin@next -D
目前版本不支持webpack4
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
module.exports = {
plugins: [
//css拆分后会把css文件放到dest目录下的css/styles.css中
new ExtractTextWebpackPlugin('css/style.css')
],
module: {
rules: [{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract({ use: 'css-loader' }) //将css用link方式引入就不需要style-loader了
}]
}
}
打包CSS中的图片
npm i url-loader file-loader -D
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192 // 字节在8192以下会被转码为base64格式
}
}]
}]
}
使用jQuery功能
npm i jquery
import $ from 'jquery'; //引入jquery库
压缩JS代码
module.exports = {
mode: 'production' //默认是production表示压缩js代码
// 'development' //development表示不压缩代码
}
压缩css代码
npm i optimize-css-assets-webpack-plugin --save-dev
const OptimizeCssAssetsPlugin= require('optimize-css-assets-webpack-plugin');
module.exports = {
plugins: [
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor:require('cssnano'),
cssProcessorOptions:{safe:true,discardComments:{removeAll:true}},
canPrint:true
})
],
}
压缩HTML代码
// 不需要安装插件
module.exports = {
plugins: [
new HtmlWebpackPlugin({
//在src目录下创建一个index.html页面当作模板来使用
template: './src/index.html',
minify:{
removeAttributeQuotes:true,
removeComments:true,
collapseWhitespace:true,
removeScriptTypeAttributes:true,
removeStyleLinkTypeAttributes:true
}
}),
],
}
webpack热更新
npm i webpack-dev-server@next -D
const Webpack = require('webpack');
module.exports = {
plugins: [
new Webpack.HotModuleReplacementPlugin(), //webpack热更新插件
],
//新增热更新配置:
devServer:{
//设置服务器访问的基本目录
//contentBase:path.resolve(__dirname,'dest'),
//设置服务器ip地址,可以是localhost
host:'localhost',
//设置端口
port:8090,
//设置自动打开浏览器
open:true,
//设置热更新
hot:true
}
}
服务器部署
腾讯云 免费产品
https://cloud.tencent.com/act/free?fromSource=gwzcw.367585.367585.367585
宝塔面板
安装宝塔面板
yum install -y wget && wget -O
install.sh http://download.bt.cn/install/install_6.0.sh
&& bash install.sh
安装完成dos小黑窗有外网地址,账号密码
外网面板地址: http://82.157.16.202:8888/ee402e7f
内网面板地址: http://172.21.0.7:8888/ee402e7f
username: knavrubb
password: 7ebacbe0
安装LAMP
安装PM2管理器
新建数据库
上传后端文件
解压
放行端口
修改后端文件链接mysql配置
PM2配置映射
映射外网地址端口
查看