Koa基础
介绍
核心概念
原理
特点
基础实现
npm init -y
npm install --save koa
index.js
根目录
const Koa = require("koa");
const app = new Koa();
app.use(async (ctx) => {
ctx.body = "hello,koa";
});
app.listen(3000);
kao-Router
npm install -S koa-router
使用
const Koa = require("koa");
const app = new Koa();
const Router = require("koa-router");
const router = new Router();
router.get("/", (ctx) => {
console.log(ctx);
console.log(ctx.request);
ctx.body = "hello,koa";
});
router.get("/api", (ctx) => {
console.log(ctx);
console.log(ctx.request);
ctx.body = "hello,api";
});
app
.use(router.routes())
// 拦截所有没有的请求,返回4xx 5xx错误
.use(router.allowedMethods());
app.listen(3000);
next()
按照use执行完以后后执行之后的语句
async await
router.get("/async", async (ctx) => {
let result = await new Promise((resolve, reject) => {
setTimeout(() => {
resolve("hello world 2s later");
}, 2000);
});
ctx.body = result;
});
Koa开发RESTful接口
npm install -S koa-router koa-body @koa/cors
.prefix
定义路由的前缀,加入拦截器
如果没有权限访问前缀路由,阻止访问
加上api以后
koa-body
koa数据body部分转义,转义POST过去JSON格式
post
const cors = require("@koa/cors");
const koaBody = require("koa-body");
...
router.post("/post", (ctx) => {
let { body } = ctx.request;
console.log(body);
console.log(ctx.request);
// ctx.body 等价于ctx.response
ctx.body = {
...body,
};
});
...
get params
router.get("/api", (ctx) => {
// 获取get请求中的params
const params = ctx.request.query;
console.log(params);
// 比如传输的数据 name : "zero" , age : "18"
console.log(params.name, params.age);
ctx.body = {
name: params.name,
age: params.age,
};
});
@koa/cors
解决跨域问题
koa-json
npm install -S koa-json
const json = require("koa-json")
app
.use(koaBody())
.use(cors())
.use(json({ pretty: false, param: "pretty" }))
如果没有工具也会格式化
方式二
Koa路由进阶配置
开发目录结构
npm install koa koa-router koa-body @koa/cors koa-json -S
koa-combine-routers
所有的routers进行合并
npm install koa-combine-routers
src
api
a.js
module.exports = function (ctx) {
ctx.body = {
message: "hello from a",
};
};
b.js
// function a(ctx) {
// ctx.body = {
// message: "hello from b",
// };
// }
// module.exports = {
// a,
// };
module.exports = function (ctx) {
ctx.body = {
message: "hello from b",
};
};
routes
aRouter.js
const Router = require("koa-router");
const a = require("../api/a");
const router = new Router();
router.get("/a", a);
module.exports = router;
bRouter.js
const Router = require("koa-router");
const b = require("../api/b");
const router = new Router();
router.get("/b", b);
module.exports = router;
routes.js
const combineRoutes = require("koa-combine-routers");
const arouters = require("./aRouter");
const brouters = require("./bRouter");
module.exports = combineRoutes(arouters, brouters);
index.js
const koa = require("koa");
const app = new koa();
const router = require("./routes/routes");
app.use(router());
app.listen(3000);
优点
在routes里面主要功能以及路径管理
在api里面全部都是功能代码,实际实现的业务 对request做的的处理,response的响应
kao安全header处理
koa-helemt
https://www.npmjs.com/package/koa-helmet
加入了安全的头
npm i koa-helmet -S
index.js
const koa = require("koa");
const app = new koa();
const helmet = require("koa-helmet");
const router = require("./routes/routes");
app.use(helmet());
app.use(router());
app.listen(3000);
koa-static
静态文件的服务
npm install koa-static -S
index.js
const koa = require("koa");
const path = require("path");
const app = new koa();
const helmet = require("koa-helmet");
const statics = require("koa-static");
const router = require("./routes/routes");
app.use(helmet());
app.use(statics(path.join(__dirname, "../public")));
app.use(router());
app.listen(3000);
node src/index.js
koa配置开发热加载
ES6语法支持&webpack配置
nodemon
监视js变化重启服务
https://www.npmjs.com/package/nodemon
npm install -D nodemon
npx nodemon --version
npx nodemon src/index.js
package.json
"scripts": {
"start": "nodemon src/index.js"
},
webpack
npm install -D webpack webpack-cli
webpack插件
npm install -D clean-webpack-plugin webpack-node-externals @babel/core @babel/node @babel/preset-env babel-loader cross-env
node: {
console: true,
global: true,
process: true,
Buffer: true,
__filename: true,
__dirname: true,
setImmediate: true,
path: true,
},
webpack.config.js
根目录
const path = require("path");
const nodeExcternals = require("webpack-node-externals");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpackconfig = {
target: "node",
mode: "development",
entry: {
server: path.join(__dirname, "src/index.js"),
},
output: {
filename: "[name].bundle.js",
path: path.join(__dirname, "./dist"),
},
devtool: "eval-source-map",
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
},
exclude: [path.join(__dirname, "/node_modules")],
},
],
},
externals: [nodeExcternals()],
plugins: [new CleanWebpackPlugin()],
};
module.exports = webpackconfig;
.babelrc
根目录
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
package.json
"scripts": {
"start": "nodemon src/index.js"
},
npx webpack
使用ES6语法
改写src/index.js
// const koa = require("koa");
// const path = require("path");
import koa from "koa";
import path from "path";
import helmet from "koa-helmet";
import statics from "koa-static";
import router from "./routes/routes";
const app = new koa();
// const helmet = require("koa-helmet");
// const statics = require("koa-static");
// const router = require("./routes/routes");
app.use(helmet());
app.use(statics(path.join(__dirname, "../public")));
app.use(router());
app.listen(3000);
npx babel-node src/index.js
npx nodemon --exec babel-node src/index.js
package.json
"scripts": {
"start": "npx nodemon --exec babel-node src/index.js"
},
调试webpack
方式一
npx node --inspect-brk .\node_modules.bin\webpack --inline --progress
打开chrome chrome://inspect/#devices
vscode调试
添加调试
添加配置
- ${workspaceFolder}代表的是项目工程目录
runtimeArgs
指定babel的应用
nodemon执行commJs规范
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "nodemon",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/nodemon",
"program": "${workspaceFolder}/src/index.js",
"restart": true,
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"skipFiles": ["<node_internals>/**"],
"runtimeArgs": ["--exec", "babel-node"]
}
]
}
运行
优化webpack配置
前面达不到生产要求
没有koabody
只是开发过程中webpack
npm-check-updates
- 检查npm依赖包是否有新的版本
npm install -g npm-check-update
ncu
ncu --help
- 查看是否有版本更新
nuc -u
更新指令
rm -rf node_modules/
删除node_modules 或者右键直接删除node_modules
npm i
重新安装
koa-compose
- 整合koa的中间件
npm install koa-compose
使用koa-compose
// const koa = require("koa");
// const path = require("path");
import koa from "koa";
import path from "path";
import helmet from "koa-helmet";
import statics from "koa-static";
import router from "./routes/routes";
// 优化新增
import koaBody from "koa-body";
import jsonutil from "koa-json";
import cors from "@koa/cors";
import compose from "koa-compose";
const app = new koa();
// const helmet = require("koa-helmet");
// const statics = require("koa-static");
// const router = require("./routes/routes");
// app.use(helmet());
// app.use(statics(path.join(__dirname, "../public")));
// app.use(router());
// 使用koa-compose 集成中间件
const middleware = compose([
koaBody(),
statics(path.join(__dirname, "../public")),
cors(),
jsonutil({ pretty: false, param: "pretty" }),
helmet(),
]);
app.use(middleware);
app.use(router());
app.listen(3000);
配置webpack
根目录创建config文件夹
webpack.config.base.js
const path = require("path");
const webpack = require("webpack");
const nodeExcternals = require("webpack-node-externals");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// debugger;
const webpackconfig = {
target: "node",
entry: {
server: path.join(__dirname, "src/index.js"),
},
output: {
filename: "[name].bundle.js",
path: path.join(__dirname, "./dist"),
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
},
exclude: [path.join(__dirname, "/node_modules")],
},
],
},
externals: [nodeExcternals()],
plugins: [
new CleanWebpackPlugin(),
new webpack.DefinePlugins({
"process.env": {
NODE_ENV:
process.env.NODE_ENV === "production" ||
process.env.NODE_ENV === "prod"
? "'production'"
: "'development'",
},
}),
],
};
module.exports = webpackconfig;
webpack.config.dev.js
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.config.base");
const webpackConfig = webpackMerge(baseWebpackConfig, {
mode: "development",
devtool: "eval-source-map",
stats: { children: false },
});
module.exports = webpackConfig;
webpack.config.prod.js
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.config.base");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const webpackConfig = webpackMerge(baseWebpackConfig, {
mode: "production",
stats: { children: false, warnings: false },
optimization: {
minimizer: [
new TerserWebpackPlugin({
terserOptions: {
warnings: false,
compress: {
warnings: false,
// 是否注释掉console
drop_console: false,
dead_code: true,
drop_debugger: true,
},
output: {
comments: false,
beautify: false,
},
mangle: true,
},
parallel: true,
sourceMap: false,
}),
],
},
});
module.exports = webpackConfig;
webpack-merge
合并webpack配置
npm i webpack-merge -D
terser-webpack-plugin
npm install terser-webpack-plugin --save-dev
TerserWebpackPlugin
压缩JS代码
https://v4.webpack.docschina.org/plugins/terser-webpack-plugin/
webpack打包配置优化(生产需求)
SplitChunksPlugin
webpack.config.prod.js
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.config.base");
const TerserWebpackPlugin = require("terser-webpack-plugin");
const webpackConfig = webpackMerge(baseWebpackConfig, {
mode: "production",
stats: { children: false, warnings: false },
optimization: {
minimizer: [
new TerserWebpackPlugin({
terserOptions: {
warnings: false,
compress: {
warnings: false,
// 是否注释掉console
drop_console: false,
dead_code: true,
drop_debugger: true,
},
output: {
comments: false,
beautify: false,
},
mangle: true,
},
parallel: true,
sourceMap: false,
}),
],
splitChunks: {
cacheGroups: {
commons: {
name: "commons",
chunks: "initial",
minChunks: 3,
enforce: true,
},
},
},
},
});
module.exports = webpackConfig;
package.json
配置script
"build": "cross-env NODE_ENV=prod webpack --config config/webpack.config.prod.js"
是因为现在webpack的配置不在根目录下面了
解决路径问题
config下面新建utils.js文件
const path = require("path");
exports.resolve = function resolve(dir) {
return path.join(__dirname, "..", dir);
};
exports.APP_PATH = exports.resolve("src");
exports.DIST_PATH = exports.resolve("dist");
删除webpack.config.js
修改webpack.config.base.js
const path = require("path");
// webpack打包配置优化新增(解决报错)
const utils = require("./utils");
const webpack = require("webpack");
const nodeExcternals = require("webpack-node-externals");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
// debugger;
const webpackconfig = {
target: "node",
entry: {
// server: path.join(__dirname, "src/index.js"),
server: path.join(utils.APP_PATH, "index.js"),
},
output: {
filename: "[name].bundle.js",
// path: path.join(__dirname, "./dist"),
path: utils.DIST_PATH,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: "babel-loader",
},
exclude: [path.join(__dirname, "/node_modules")],
},
],
},
externals: [nodeExcternals()],
plugins: [
new CleanWebpackPlugin(),
new webpack.DefinePlugin({
"process.env": {
NODE_ENV:
process.env.NODE_ENV === "production" ||
process.env.NODE_ENV === "prod"
? "'production'"
: "'development'",
},
}),
],
};
module.exports = webpackconfig;
npm run build
npm install -D rimraf
package.json
所有脚本配置 注意clean需要下载rimraf包
"start": "nodemon --exec babel-node src/index.js",
"webpack:debug": "node --inspect-brk ./node_modules/.bin/webpack --inline --progress",
"build": "cross-env NODE_ENV=prod webpack --config config/webpack.config.prod.js",
"dev": "cross-env NODE_ENV=dev nodemon --exec babel-node --inspect ./src/index.js",
"clean": "rimraf dist"
路由相关
红色删除 绿色新增
demoController.js
class DemoController {
constructor() {}
async demo(ctx) {
ctx.body = {
msg: "body message",
};
}
}
export default new DemoController();
demoRouter.js
import Router from "koa-router";
import demoController from "../api/demoController";
const router = new Router();
router.get("/demo", demoController.demo);
module.exports = router;
routes.js
// const combineRoutes = require("koa-combine-routers");
import combineRoutes from "koa-combine-routers";
import demoRouter from "./demoRouter";
// const arouters = require("./aRouter");
// const brouters = require("./bRouter");
// module.exports = combineRoutes(arouters, brouters);
export default combineRoutes(demoRouter);
npm run dev
koa-compress
npm install koa-compress -S
index.js
// const koa = require("koa");
// const path = require("path");
import koa from "koa";
import path from "path";
import helmet from "koa-helmet";
import statics from "koa-static";
import router from "./routes/routes";
// 优化新增
import koaBody from "koa-body";
import jsonutil from "koa-json";
import cors from "@koa/cors";
import compose from "koa-compose";
import compress from "koa-compress";
const app = new koa();
const isDevMode = process.env.NODE_ENV === "production" ? false : true;
// 使用koa-compose 集成中间件
const middleware = compose([
koaBody(),
statics(path.join(__dirname, "../public")),
cors(),
jsonutil({ pretty: false, param: "pretty" }),
helmet(),
]);
if (!isDevMode) {
app.use(compress());
}
app.use(middleware);
app.use(router());
app.listen(3000);