koa+Vite+vue3+ts+pinia构建项目
一、 初始化构建项目
npm create vite myProject -- --template vue-ts
注:Vite 需要 Node.js 版本 14.18+,16+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本。
二、创建服务器
使用 Koa2
1. 安装koa
npm i koa --save && npm i @types/koa --save-dev
2. 安装中间件(koa-connect)
npm i koa-connect --save
3. 安装koa处理跨域(koa2-cors)
npm i koa2-cors --save
4. 安装中间件(koa-bodyparser)
利用koa-bodyparser来处理POST请求参数
npm i koa-bodyparser --save
POST请求参数的处理有2种方式:
- 利用
node.js
原生的querystring.parse()
方式拿到前端传过来的数据。 - 利用第三方中间件
koa-bodyparser
注:
- 本模块不支持解析multipart表单格式数据,请使用co-busboy解析multipart表单格式数据。
- middleware的顺序很重要,这个koa-bodyparser必须在router之前被注册到app对象上
5. 注册中间件
- 新增bin/app.js文件
const Koa = require('koa');const cors = require('koa2-cors')const bodyParser = require('koa-bodyparser')(async () => {const app = new Koa();app.use(cors())app.use(bodyParser())app.use(async (ctx, next) => {console.log(ctx)ctx.body = `<!DOCTYPE html><html lang="en"><head><title>koa2 + vite + ts + vue3 + vue-router</title></head><body><h1 style="text-align: center;">Hello</h1></body></html>`;});// parse request body:app.listen(9000, () => {console.log('server is listening in 9000');});
})();
6. node进行启动服务
node bin/app.js
三、安装模板引擎
npm i nunjucks --save
nunjucks文档:Nunjucks 中文文档
廖雪峰nunjucks文档:使用Nunjucks - 廖雪峰的官方网站
- 创建config/templates.js
const nunjucks = require('nunjucks');function createEnv(path, opts) {var autoescape = opts.autoescape === undefined ? true : opts.autoescape,noCache = opts.noCache || false,watch = opts.watch || false,throwOnUndefined = opts.throwOnUndefined || false,env = new nunjucks.Environment(new nunjucks.FileSystemLoader(path, {noCache: noCache,watch: watch,}),{autoescape: autoescape,throwOnUndefined: throwOnUndefined,});if (opts.filters) {for (var f in opts.filters) {env.addFilter(f, opts.filters[f]);}}return env;
}function templates(path, opts) {var env = createEnv(path, opts);return async (ctx, next) => {ctx.render = function (view, model) {ctx.response.body = env.render(view, Object.assign({}, ctx.state || {}, model || {}));ctx.response.type = "text/html";};await next();};
}module.exports = templates;
- bin/app.js
// nunjucks 模板渲染
const templates = require('../config/templates')// add nunjucks as ./:
app.use(templates('./', {noCache: !isProduction,watch: !isProduction})
)
四、路由配置
1. 安装 koa-router
npm i koa-router --save
2. 创建config/controller.js
const router = require('koa-router')()
router.staticFiles = {}// add url-route in /controllers:function interception(str) {return str.substring(0, str.lastIndexOf('/'))
}
function addMapping(mapping) {for (const url in mapping) {if (url.startsWith('GET ')) {const path = url.substring(4)const funStr = mapping[url].toString()if (funStr.indexOf('ctx.render') > 0) {const str1 = funStr.match(/ctx.render[\s]*\([\s]*'(\S*)', \{/g)[0]const str2 = str1.replace(/ctx.render[\s]*\([\s]*'/g, '')const str3 = str2.replace(/'[\s]*,[\s]*\{/g, '')const strUrl = url.replace('GET ', '')if (strUrl != '/') {router.staticFiles[interception(strUrl)] = interception(str3)}}router.get(path, mapping[url])console.log(`register URL mapping: GET ${path}`);} else if (url.startsWith('POST ')) {const path = url.substring(5)router.post(path, mapping[url])console.log(`register URL mapping: POST ${path}`)} else if (url.startsWith('PUT ')) {const path = url.substring(4)router.put(path, mapping[url])console.log(`register URL mapping: PUT ${path}`)} else if (url.startsWith('DELETE ')) {const path = url.substring(7)router.del(path, mapping[url])console.log(`register URL mapping: DELETE ${path}`)} else {console.log(`invalid URL: ${url}`)}}
}function addControllers(filePath) {const fs = require('fs')fs.readdirSync(filePath).filter(f => {if (fs.statSync(filePath + '/' + f).isFile()) {if (f.endsWith('.js')) {const mapping = require(filePath + '/' + f)()addMapping(mapping)}}if (fs.statSync(filePath + '/' + f).isDirectory()) {addControllers(filePath + '/' + f)}})
}module.exports = function (dir, app) {// 读取/routes目录的路由配置const controllers_dir = dir || '../routes'addControllers(__dirname + '/' + controllers_dir)return router.routes()
}
3. routes/admin/index.js配置
module.exports = function () {return {'GET /': async (ctx, next) => {const pageInfo = {title: '页面标题'}ctx.render('src/mobile/official/dist/index.html', {pageInfo})}}
}
五、集成 vue-router
1. 安装vue-router
npm i vue-router --save
2. 新增项目模块(test)
- src/test/index.html(页面)
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, width=device-width" /><meta name="format-detection" content="telephone=no" /></head><body><div id="app"></div><script type="module" src="./main.ts"></script></body>
</html>
- src/test/views/index.vue (子页面)
<template><h1>内容</h1>
</template><script setup lang="ts">
import { inject } from 'vue'
const title = 'test'
</script>
- test/router/index.ts (路由配置)
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'const routes: RouteRecordRaw[] = [{path: '/',redirect: to => {return '/index'}},{path: '/index',name: 'Index',component: () => import('../views/index.vue')}
]const router = createRouter({history: createWebHistory(),routes
})export default router
- test/main.ts(main.js)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import { createPinia } from 'pinia'const app = createApp(App)
app.use(createPinia)
app.use(router)
app.mount('#app')
六、Vite配置(vite.config.ts)
Vite 会自动解析根目录下名为vite.config.ts的文件
配置 Vite | Vite 官方中文文档
1. 基本配置(vite.config.ts)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { existsSync } from 'fs'// 获取模块路径
const modulePath = process.env.npm_config_path.endsWith('/')? process.env.npm_config_path.slice(0, -1): process.env.npm_config_pathconst projectDirname = resolve(__dirname, './' + modulePath)let publicPath = '//res.test.com'if (!modulePath || !existsSync(projectDirname)) {// 路径不存在,停止运行console.log('\x1b[40m \x1b[31m 模块路径错误,请检查路径 \x1b[0m')process.exit(0)
}export default defineConfig(({ mode }) => {const alias: Record<string, string> = {'@': resolve(__dirname, 'src'),'@admin': resolve(__dirname, 'src/admin'),'@mobile': resolve(__dirname, 'src/mobile'),'@pc': resolve(__dirname, 'src/pc')}// 路径存在,配置入口/出口路径const moduleName = modulePath.split('/').reverse()[0]const project_pages = {}project_pages[moduleName] = resolve(__dirname, modulePath + '/index.html')return {// https://cn.vitejs.dev/guide/#index-html-and-project-rootroot: modulePath, // 项目根目录base: mode === 'production' ? publicPath + modulePath.replace(/^(.\/)?src+/, '') + '/' : '/',plugins: [vue()],resolve: {extensions: ['.js', '.ts', '.vue', '.json'],alias},server: {port: 8081,open: false,proxy: {}},build: {rollupOptions: {input: project_pages,output: {dir: resolve(__dirname, modulePath + '/dist'),chunkFileNames: 'static/js/[name]-[hash].js',entryFileNames: 'static/js/[name]-[hash].js',assetFileNames: 'static/[ext]/[name]-[hash].[ext]'}},minify: 'terser',terserOptions: {compress: {drop_console: true,drop_debugger: true}}}}
})
1. element-plus 按需引入
首先你需要安装 unplugin-vue-components 和 unplugin-auto-import这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import viteCompression from 'vite-plugin-compression'export default defineConfig(({ mode }) => {return {plugins: [vue(),AutoImport({imports: ['vue', 'vue-router'], // 自动导入vue和vue-router相关函数eslintrc: {enabled: false, // 默认false, true启用。生成一次就可以,避免每次工程启动都生成filepath: './.eslintrc-auto-import.json', // 生成json文件globalsPropValue: true}}),// gzip压缩 生产环境生成 .gz 文件viteCompression({verbose: true,disable: false,threshold: 10240,algorithm: 'gzip',ext: '.gz'})]}
})
2. Vant按需引入
npm i vite-plugin-style-import -D
vite.config.ts
注:2.0版本需要使用的是createStyleImportPlugin不要使用styleImprot了
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
import { existsSync } from 'fs'//2.0之后版本用createStyleImportPlugin
import { createStyleImportPlugin, VantResolve } from 'vite-plugin-style-import';export default defineConfig(({ mode }) => {const alias: Record<string, string> = {'@': resolve(__dirname, 'src'),'@admin': resolve(__dirname, 'src/admin'),'@mobile': resolve(__dirname, 'src/mobile'),'@pc': resolve(__dirname, 'src/pc')}// 路径存在,配置入口/出口路径const moduleName = modulePath.split('/').reverse()[0]const project_pages = {}project_pages[moduleName] = resolve(__dirname, modulePath + '/index.html')return {root: modulePath,base: mode === 'production' ? '//res.test.com' + modulePath.replace(/^(.\/)?src+/, '') + '/' : '/',plugins: [vue(),createStyleImportPlugin({resolves: [VantResolve()],libs: [{libraryName: 'vant',esModule: true,resolveStyle: name => `../es/${name}/style`}]})],resolve: {extensions: ['.js', '.ts', '.vue', '.json'],alias},server: {port: 8081,open: false,proxy: {}},build: {rollupOptions: {input: project_pages,output: {dir: resolve(__dirname, modulePath + '/dist'),chunkFileNames: 'static/js/[name]-[hash].js',entryFileNames: 'static/js/[name]-[hash].js',assetFileNames: 'static/[ext]/[name]-[hash].[ext]'}},minify: 'terser',terserOptions: {compress: {drop_console: true,drop_debugger: true}}}}
})
如出现 Error: Cannot find module ‘consola‘
则需要安装consola(由于改依赖包有使用到consola)
npm i consola -D
七、本地启动服务、打包项目的命令设置
package.json
{"name": "myProject","private": true,"version": "0.0.0","scripts": {"dev": "vite","vuedev": "vite serve --force --","build": "vue-tsc && vite build","vuebuild": "vue-tsc --noEmit && vite build --","preview": "vite preview"},"dependencies": {"axios": "^1.3.4","element-plus": "^2.3.0","koa": "^2.14.1","koa-bodyparser": "^4.3.0","koa-connect": "^2.1.0","koa-router": "^12.0.0","koa2-cors": "^2.0.6","nunjucks": "^3.2.3","pinia": "^2.0.33","qs": "^6.11.1","vant": "^4.1.0","vite-plugin-compression": "^0.5.1","vite-plugin-style-import": "^2.0.0","vue": "^3.2.45","vue-router": "^4.1.6"},"devDependencies": {"@types/koa": "^2.13.5","@vitejs/plugin-vue": "^4.0.0","consola": "^2.15.3","cross-env": "^7.0.3","less": "^4.1.3","typescript": "^4.9.3","unplugin-auto-import": "^0.15.1","unplugin-vue-components": "^0.24.1","vite": "^4.1.0","vue-tsc": "^1.0.24"}
}
npm run vuedev --path=src/test
相关文章:
koa+Vite+vue3+ts+pinia构建项目
一、 初始化构建项目 npm create vite myProject -- --template vue-ts 注:Vite 需要 Node.js 版本 14.18,16。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版…...
k8s-yaml文件
文章目录一、K8S支持的文件格式1、yaml和json的主要区别2、YAML语言格式二、YAML1、查看 API 资源版本标签2、编写资源配置清单2.1 编写 nginx-test.yaml 资源配置清单2.2 创建资源对象2.3 查看创建的pod资源3、创建service服务对外提供访问并测试3.1 编写nginx-svc-test.yaml文…...
存储引擎
目录 ❤ MySQL存储引擎 什么是存储引擎? MySQL支持哪个存储引擎? ❤ 各种存储引擎的特性 概述 各种存储引擎的特性 各种搜索引擎介绍 ❤ 常用存储引擎及适用场景 ❤ 存储引擎在mysql中的使用 存储引擎相关sql语句 指定存储引擎建表 在建表时指定 在配置文件中…...
Go中 channel的使用
文章目录背景channel 简介使用说明声明发送和接受数据关闭channel使用示例背景 使用 sync 包和 context 包的工具可以实现多个协程之间互相协作, 但是没有一种很好的方式解决多个协程之间通信的问题. golang 作者 Rob Pike 说过一句话,不要通过共享内存来通信&…...
【C++】string OJ练习
文章目录1. 仅仅反转字母思路分析代码实现2. 字符串中的第一个唯一字符题目分析代码实现3. 《剑指offer》——替换空格解法一:寻找替换思路分析代码实现优化解法二:空间换时间思路分析代码实现4.字符串最后一个单词的长度思路分析代码实现5. 字符串相加思…...
进程间通信IPC
进程间通信IPC (InterProcess Communication) 一、进程间通信的概念 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据…...
操作系统-页面淘汰算法(下)-软件设计(二十六)
操作系统-PV操作(上)-软件设计(二十五)https://blog.csdn.net/ke1ying/article/details/129476031 存储管理-分区存储组织 问:计算机系统内存大小为128k,当前系统分配情况如图,那么作业4再次申…...
23种设计模式-责任链模式(Android开发实际应用场景介绍)
什么是责任链模式 责任链模式是一种行为型设计模式,它的核心思想是将请求从一系列处理者中传递,直到其中一个处理者能够处理它为止。在这个过程中,请求可以被任何一个处理者处理,也可以被拒绝,直到有一个处理者能够处…...
Socket+Select+Epoll笔记
讲到epoll,就必须了解Socket,上篇博客写了Socket的基本使用方法,步骤主要为创建一个socketsocket是进程之间通信的,那么进程通信如何找到这个socket呢?当然是端口号,所以socket就要和端口号进行绑定&#x…...
git查看最近修改的文件
git log --name-status 每次修改的文件列表, 显示状态 git log --name-only 每次修改的文件列表 git log --stat 每次修改的文件列表, 及文件修改的统计 git whatchanged 每次修改的文件列表 git whatchanged --stat 每次修改的文件列表, 及文件修改的统计 git show 显示最…...
【算法基础(四)】堆排序(二)
堆排序(二) 把数组从零开始连续的一段 完全二叉树 size i 左 son 2*11 i 右 son 2*12 父 (i-1) / 2 堆是完全二叉树,分为大根堆和小根堆 在完全二叉树里,每一棵子数最大的值是头节点的值,就是大根堆 同理&…...
C++类型转换
C语言的转换是在变量前加类型名进行转换的,比如double pi 3.14;int a (int) pi;对于指针也是如此double* dptr πint* iptr (int*)dptr;虽然c兼容了C语言的转型方式,但是也做了很多限制,比如向上类型转换,在c中建议使用…...
Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)
注:这个是MDK6,不是MDK5 AC6,属于下一代MDK视频版: https://www.bilibili.com/video/BV16s4y157WF Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台一年一度的全球顶级嵌入式会展Embedded Wor…...
蓝桥杯刷题第九天
题目描述本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。素数就是不能再进行等分的整数。比如7,11。而 9 不是素数,因为它可以平分为 3 等份。一般认为最小的素数是2,接着是 3,5&…...
a-tree-select 基本使用,下拉框高度和宽度设置、回显时滚动条定位解决。
目录一、基本使用1. 界面效果2. 代码实现3. 问题1:下拉框占满整个屏幕4. 问题4:菜单内容过长时,下拉菜单宽度无限变宽。二、数据回显、滚动条定位1. 界面效果2. 代码实现2.1 获取默认展开节点2.1.1 代码实现2.1.2 说明2.2 设置滚动条定位2.2.…...
【Linux】之nc命令(连接与扫描指定端口、监测服务端口的使用情况)解析、详解实例、邮件告警
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 文章目录nc命令简介nc命令的安装nc命令语法格式…...
cdn简单配置
cdn配置域名接入CDN编辑CDN配置本地修改hosts文件,绕过公网解析域名接入CDN 添加CDN域名以及回源配置 编辑CDN配置 默认后端端口是80,如果测试发现无法访问,则可能是443或其它 如果域名在CDN后端有https强制跳转,后端端口一定是44…...
前端安全(自留)
目录XSS——跨站脚本常见解决CSRF ——跨站请求伪造常见解决XSS——跨站脚本 当目标站点在渲染html的过程中,遇到陌生的脚本指令执行。 攻击者通过在网站注入恶意脚本,使之在用户的浏览器上运行,从而盗取用户的信息如 cookie 等。 常见 解…...
零基础转行云计算可行吗
目前处于云年代,云计算运维工程师的工作远景还是十分广泛的。像是阿里云计算,滴滴,抖音等等互联网大厂目前都在使用云核算技能。 云计算运维工程师的薪资水平也十分可观。 运维工程师(Operations),在国内又称为运维开发工程师(Dev…...
【AcWing】蓝桥杯备赛-深度优先搜索-dfs(1)
目录 写在前面: 题目:92. 递归实现指数型枚举 - AcWing题库 读题: 输入格式: 输出格式: 数据范围: 输入样例: 输出样例: 解题思路: 代码: AC &…...
孩子免费就读|私企经理自费赴美国东海岸高校访学
私企U经理无文章无课题,出国访学除了为考察市场、拓宽人脉、提升履资外,另一个主要目的是带孩子在美国接受当地免费的公立中小学教育,并把访学目标学校定位在东海岸。最终其采纳了板凳费相对较低的佐治亚大学邀请函,签证时居然全家…...
前端面试hr经常会问的问题
文章目录前言1.自我介绍2.为什么你要离职?3.工作经历4.职业规划5.优点、缺点6.还有什么要问的总结前言 这里记录了一些面试中hr或者项目负责人经常会问的一些问题,可以提前参考参考,想想该怎么回答,为之后的面试做好准备…...
C动态数组
在实际项目中,我们经常与各式各样的数据打交道。 例如:我们处理的是学生的数据。 struct student {int id; // 学号char name[20]; // 姓名int gender; // 性别int mark; // 成绩 };学生数据使用一个结构体表示,该结构体拥有4个成员。分别为…...
【STL一】STL组件(容器、迭代器、算法)
【STL一】STL组件(容器、迭代器、算法)一、STL二、STL组件(component)1、stl六大组件2、C STL的13个头文件3、stl所有头文件三、容器(container)1、序列容器(Sequence container)——顺序容器2、关联容器&a…...
Java每日一练(20230312)
目录 1. 两数之和 II ★ 2. 反转链表 ★★ 3. 二叉树的层序遍历 II ★★★ 🌟 每日一练刷题专栏 C/C 每日一练 专栏 Python 每日一练 专栏 Java 每日一练 专栏 1. 两数之和 II 给定一个已按照 非递减顺序排列 的整数数组 numbers ,请你从数…...
Linux中sudo,su与su -命令的区别
前言 su命令就是切换用户的工具,怎么理解呢?比如我们以普通用户tom登录的,但要添加用户任务,执行useradd ,tom用户没有这个权限,而这个权限恰恰由root所拥有。解决办法无法有两个,一是退出tom用…...
归并排序有多简单?一幅图教你看懂【C语言】
目录 归并排序的递归实现 代码实现 归并排序的非递归实现 代码实现 归并排序的思想很简单——分治法。简单地说,归并排序的是将序列拆分成几段子序列,将每一段子序列分别进行排序,排好之后再将有序的子序列归并(有点像合并两…...
C++-Z字扫描实现(Zigzag Scan)
Z字扫描(Zigzag Scan) 将二维矩阵压缩成行输出: int index0; for(int i0;i<rowscols-1;i){//i是第几条对角线if(i&1){//odd,向下扫描for(int jmax(0,i-cols1);j<min(i,row-1);j){res[index]mtx[j][i-j];}//}else{//偶数,向上扫描for(int jmi…...
【华为机试真题详解 Python实现】求最大数字【2023 Q1 | 100分】
文章目录 前言题目描述输入描述输出描述示例 1示例 2题目解析参考代码前言 《华为机试真题详解》专栏含牛客网华为专栏、华为面经试题、华为OD机试真题。 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即…...
面对数万亿产业规模,如何掘金工业互联网?
近年来,加速工业互联网建设的声音越来越响亮。一方面,政策利好,持续驱动。从2017年的《国务院关于深化“互联网先进制造业” 发展工业互联网的指导意见》到《工业互联网创新发展三年行动计划(2021-2023年)》࿰…...
保定网站制作公司/网络推广方案范例
一、先来个简单的1.安装docker2.安装eureka——运行docker命令安装3.安装eureka——运行dokcer镜像安装(1)构建eureka的镜像,网易云的docker镜像比较全一些,也可以去https://hub.docker.com/拷贝下(2)运行镜像启动,等响应。可以把本地镜像传到…...
响应式网站设计的要求/小红书网络营销策划方案
文章目录1. Mybatis概述1.1 简介1.2 如何获得Mybatis1.3 持久化1.4 持久层1.5 为什么需要Mybatis1.6 Mybatis开发工作流程2 第一个Mybatis程序2.1 搭建环境2.2 创建一个模块2.3 编写代码2.4 测试本文章涉及环境版本: mysql 5.7Mybatis 3.5.xMaven 3.6.xJDK 1.8 项目…...
国家补贴软件网站开发政策/哪个公司做网站推广最好
此检查next_day不在mcal.get_calendar(NYSE)中。valid_days(start_date2000-12-20, end_date2020-01-10)非常耗时,因为它需要从7000天的数组中查找。你需要对每一个操作都这样做,所以我认为这是效率低下的主要原因。 您可以通过转换mcal.get_…...
哪个网站可以做英文兼职/百度爱采购官方网站
1. 文件处理命令:touch 命令名称:touch命令所在路径:/bin/touch执行权限:所有用户语法:touch [文件名]功能描述:创建空文件范例: 文件名不包含空格 touch Japanlovestory.list 文件名包含空格 t…...
南昌网站小程序开发/seo公司运营
一:依赖关系 1:依赖和血缘关系介绍 rdd.todebugstring:打印血缘关系 rdd.dependencies:打印依赖关系 2:保存血缘关系 3:OneToOne依赖---窄依赖 4:shuffle依赖--宽依赖 新的RDD的一个分区的数据…...
网购哪个平台最好正品/内江seo
上一周每一天都在“合成大西瓜”然后出了个“合成大西瓜魔改版”最近还比了个“合成小芝麻”但是我想说百变水果,它来了你还在为“合成大西瓜”经常打不开!不小心滑出去无法记录成绩!画质渣到感人!右上角的宝箱广告!失…...