├── vite-nuxt3-app ├── .npmrc ├── src │ ├── stores │ │ ├── index.ts │ │ └── useUserStore.ts │ ├── assets │ │ └── styles │ │ │ └── default.scss │ ├── composables │ │ └── useFoo.ts │ ├── layouts │ │ ├── footer.vue │ │ ├── header.vue │ │ └── default.vue │ ├── plugins │ │ └── directives.ts │ ├── pages │ │ ├── index.vue │ │ ├── list.vue │ │ ├── [id] │ │ │ └── index.vue │ │ └── user-[group] │ │ │ └── [id].vue │ ├── app.vue │ └── components │ │ └── ListItem.vue ├── .gitignore ├── tsconfig.json ├── README.md ├── nuxt.config.ts └── package.json ├── vite-vue3-admin ├── .eslintignore ├── public │ └── favicon.ico ├── src │ ├── views │ │ ├── login │ │ │ ├── images │ │ │ │ └── bg.jpg │ │ │ └── login.vue │ │ └── home │ │ │ └── index.vue │ ├── types │ │ ├── shims-vue.d.ts │ │ ├── shims-store.d.ts │ │ └── shims-axios.d.ts │ ├── main.ts │ ├── App.vue │ ├── assets │ │ └── css │ │ │ └── reset.css │ ├── store │ │ └── index.ts │ ├── router │ │ └── index.ts │ ├── config │ │ └── element.ts │ └── layout │ │ ├── Sidebar.vue │ │ └── AppLayout.vue ├── .gitignore ├── index.html ├── README.md ├── prettier.config.js ├── tsconfig.json ├── package.json ├── vite.config.ts └── .eslintrc.js ├── pnpm-tool-template ├── packages │ ├── shared │ │ ├── index.ts │ │ ├── package.json │ │ └── is │ │ │ └── index.ts │ ├── core │ │ ├── index.ts │ │ ├── package.json │ │ ├── getDevice │ │ │ ├── index.md │ │ │ ├── index.test.ts │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── .vitepress │ │ ├── theme │ │ │ └── index.ts │ │ └── config.ts │ ├── guide │ │ └── index.md │ └── index.md ├── .eslintignore ├── pnpm-workspace.yaml ├── commitlint.config.ts ├── README.md ├── .husky │ ├── commit-msg │ └── pre-commit ├── .gitignore ├── .prettierrc ├── .npmingnore ├── .changeset │ ├── config.json │ └── README.md ├── test.ts ├── .eslintrc ├── tsconfig.json ├── tsup.config.ts ├── LICENSE ├── .github │ └── workflows │ │ └── docs-deploy.yml └── package.json ├── vite-react ├── src │ ├── vite-env.d.ts │ ├── main.tsx │ ├── index.css │ ├── App.css │ ├── App.tsx │ ├── favicon.svg │ └── logo.svg ├── tsconfig.node.json ├── vite.config.ts ├── .gitignore ├── index.html ├── package.json └── tsconfig.json ├── vite-vue2 ├── App.vue ├── src │ └── main.js ├── vite.config.js ├── style.css ├── .gitignore ├── package.json ├── index.html └── favicon.svg ├── vite-plugin-template ├── .eslintignore ├── .vscode │ └── extensions.json ├── examples │ ├── vite-react │ │ ├── src │ │ │ ├── vite-env.d.ts │ │ │ ├── main.tsx │ │ │ ├── index.css │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ ├── favicon.svg │ │ │ └── logo.svg │ │ ├── tsconfig.node.json │ │ ├── vite.config.ts │ │ ├── index.html │ │ ├── package.json │ │ └── tsconfig.json │ ├── vite-vue2 │ │ ├── App.vue │ │ ├── src │ │ │ └── main.js │ │ ├── style.css │ │ ├── vite.config.js │ │ ├── index.html │ │ ├── package.json │ │ └── favicon.svg │ └── vite-vue3 │ │ ├── src │ │ ├── store │ │ │ ├── index.ts │ │ │ └── user.ts │ │ ├── styles │ │ │ └── index.css │ │ ├── assets │ │ │ └── logo.png │ │ ├── api │ │ │ ├── index.ts │ │ │ └── module │ │ │ │ ├── index.ts │ │ │ │ └── login.ts │ │ ├── main.ts │ │ ├── env.d.ts │ │ ├── App.vue │ │ ├── pages │ │ │ ├── login.vue │ │ │ ├── vueUse.vue │ │ │ ├── index.vue │ │ │ └── request.vue │ │ ├── components │ │ │ └── UsePinia.vue │ │ ├── utils │ │ │ └── axios.ts │ │ ├── types │ │ │ └── shims-axios.d.ts │ │ └── router │ │ │ └── index.ts │ │ ├── public │ │ └── favicon.ico │ │ ├── tsconfig.node.json │ │ ├── index.html │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── vite.config.ts ├── README.md ├── .npmignore ├── .gitignore ├── .prettierrc ├── .eslintrc ├── tsconfig.json ├── package.json └── src │ └── index.ts ├── vite-vue3-ts-pinia ├── .eslintignore ├── .vscode │ └── extensions.json ├── .husky │ ├── pre-commit │ └── commit-msg ├── public │ └── favicon.ico ├── src │ ├── assets │ │ └── logo.png │ ├── store │ │ ├── index.ts │ │ └── user.ts │ ├── styles │ │ └── index.css │ ├── api │ │ ├── index.ts │ │ └── module │ │ │ ├── index.ts │ │ │ └── login.ts │ ├── main.ts │ ├── env.d.ts │ ├── App.vue │ ├── pages │ │ ├── login.vue │ │ ├── vueUse.vue │ │ ├── index.vue │ │ └── request.vue │ ├── components │ │ └── UsePinia.vue │ ├── utils │ │ └── axios.ts │ ├── types │ │ └── shims-axios.d.ts │ └── router │ │ └── index.ts ├── tsconfig.node.json ├── .gitignore ├── index.html ├── prettier.config.js ├── vite.config.ts ├── tsconfig.json ├── .cz-config.js ├── commitlint.config.js ├── .eslintrc.js ├── package.json └── README.md ├── koa2-ssr-vite-vue3-ts-pinia ├── .eslintignore ├── .vscode │ └── extensions.json ├── src │ ├── types │ │ └── shims-global.d.ts │ ├── assets │ │ └── logo.png │ ├── main.ts │ ├── store │ │ ├── index.ts │ │ └── user.ts │ ├── env.d.ts │ ├── App.vue │ ├── pages │ │ ├── login.vue │ │ ├── user.vue │ │ ├── vueUse.vue │ │ └── index.vue │ ├── entry-client.ts │ ├── components │ │ └── UsePinia.vue │ ├── router │ │ └── index.ts │ └── entry-server.ts ├── public │ └── favicon.ico ├── .gitignore ├── vite.config.ts ├── prettier.config.js ├── index.html ├── tsconfig.json ├── test.js ├── server-prod.js ├── .cz-config.js ├── commitlint.config.js ├── server-dev.js ├── .eslintrc.js ├── package.json └── README.md ├── vite-vue3 ├── .vscode │ └── extensions.json ├── public │ └── favicon.ico ├── src │ ├── assets │ │ └── logo.png │ ├── main.ts │ ├── env.d.ts │ ├── App.vue │ └── components │ │ └── HelloWorld.vue ├── tsconfig.node.json ├── vite.config.ts ├── .gitignore ├── index.html ├── package.json ├── tsconfig.json └── README.md ├── .gitignore └── README.md /vite-nuxt3-app/.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist=true -------------------------------------------------------------------------------- /vite-vue3-admin/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/stores/index.ts: -------------------------------------------------------------------------------- 1 | export * from './useUserStore' -------------------------------------------------------------------------------- /pnpm-tool-template/packages/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './is'; 2 | -------------------------------------------------------------------------------- /vite-react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vite-vue2/App.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './getDevice'; 2 | -------------------------------------------------------------------------------- /vite-plugin-template/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | examples/ 3 | dist/ 4 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | index.html 4 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ 3 | index.html 4 | server.js -------------------------------------------------------------------------------- /vite-nuxt3-app/src/assets/styles/default.scss: -------------------------------------------------------------------------------- 1 | $bgColor: rgb(125, 159, 172); 2 | $theme: red; -------------------------------------------------------------------------------- /vite-plugin-template/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["vue.volar" ] 3 | } 4 | -------------------------------------------------------------------------------- /vite-vue3/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-tool-template/.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | coverage 4 | !.vitepress/ 5 | !.changeset/ -------------------------------------------------------------------------------- /pnpm-tool-template/pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/* 3 | - playground 4 | - docs 5 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/App.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /vite-nuxt3-app/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | .nuxt 4 | .nitro 5 | .cache 6 | .output 7 | .env 8 | dist 9 | -------------------------------------------------------------------------------- /vite-vue3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3/public/favicon.ico -------------------------------------------------------------------------------- /vite-vue3/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3/src/assets/logo.png -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/types/shims-global.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | __INITIAL_STATE__: string; 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-tool-template/commitlint.config.ts: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | }; 4 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/composables/useFoo.ts: -------------------------------------------------------------------------------- 1 | export const useFoo = () => { 2 | return useState('foo', () => 'bar') 3 | } 4 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /vite-vue3-admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3-admin/public/favicon.ico -------------------------------------------------------------------------------- /vite-vue3/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /pnpm-tool-template/README.md: -------------------------------------------------------------------------------- 1 | 2 | # pnpm-tool-template 3 | > ## 这是一个前端工具库的通用模板 4 | > 5 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! -------------------------------------------------------------------------------- /pnpm-tool-template/.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit "" 5 | -------------------------------------------------------------------------------- /pnpm-tool-template/.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /vite-nuxt3-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // https://nuxt.com/docs/guide/concepts/typescript 3 | "extends": "./.nuxt/tsconfig.json" 4 | } 5 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3-ts-pinia/public/favicon.ico -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3-ts-pinia/src/assets/logo.png -------------------------------------------------------------------------------- /vite-nuxt3-app/README.md: -------------------------------------------------------------------------------- 1 | 2 | # vite-nuxt3-app 3 | > ## 这是一个nuxt3 + vite3 前端 SSR 项目通用模板 4 | > 5 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! -------------------------------------------------------------------------------- /vite-plugin-template/README.md: -------------------------------------------------------------------------------- 1 | # vite-plugin-templates 2 | > ## 这是一个写 vite 插件的通用模板 3 | > 4 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! 5 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia'; 2 | 3 | const store = createPinia(); 4 | 5 | export default store; 6 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/koa2-ssr-vite-vue3-ts-pinia/public/favicon.ico -------------------------------------------------------------------------------- /vite-vue3-admin/src/views/login/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-vue3-admin/src/views/login/images/bg.jpg -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/styles/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-bg-color: black; 3 | } 4 | 5 | .root { 6 | color: var(--main-bg-color); 7 | } 8 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/koa2-ssr-vite-vue3-ts-pinia/src/assets/logo.png -------------------------------------------------------------------------------- /pnpm-tool-template/packages/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme'; 2 | 3 | export default { 4 | ...DefaultTheme, 5 | }; 6 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/layouts/footer.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/layouts/header.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /vite-vue2/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./../App.vue" 3 | 4 | new Vue({ 5 | el: "#app", 6 | render: (h) => h(App) 7 | }).$mount(); -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia'; 2 | 3 | const store = createPinia(); 4 | 5 | export default store; 6 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/layouts/default.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/styles/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --main-bg-color: black; 3 | } 4 | 5 | .root { 6 | color: var(--main-bg-color); 7 | } 8 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-plugin-template/examples/vite-vue3/public/favicon.ico -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeddygong/vite-templates/HEAD/vite-plugin-template/examples/vite-vue3/src/assets/logo.png -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as login from './module/login'; 2 | import * as index from './module/index'; 3 | 4 | export default Object.assign({}, login, index); 5 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./../App.vue" 3 | 4 | new Vue({ 5 | el: "#app", 6 | render: (h) => h(App) 7 | }).$mount(); -------------------------------------------------------------------------------- /vite-vue2/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { createVuePlugin } from 'vite-plugin-vue2' 3 | 4 | export default defineConfig({ 5 | plugins: [createVuePlugin()] 6 | }) -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/api/index.ts: -------------------------------------------------------------------------------- 1 | import * as login from './module/login'; 2 | import * as index from './module/index'; 3 | 4 | export default Object.assign({}, login, index); 5 | -------------------------------------------------------------------------------- /vite-react/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite-vue3/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite-vue3/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()] 7 | }) 8 | -------------------------------------------------------------------------------- /pnpm-tool-template/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .history 3 | .vscode 4 | .idea 5 | .eslintcache 6 | .pnpm-debug.log 7 | *.local 8 | dist 9 | node_modules 10 | types 11 | coverage 12 | 13 | .changeset/pre.json -------------------------------------------------------------------------------- /vite-vue3-admin/src/types/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue'; 3 | const component: DefineComponent<{}, {}, any>; 4 | export default component; 5 | } 6 | -------------------------------------------------------------------------------- /vite-react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()] 7 | }) 8 | -------------------------------------------------------------------------------- /vite-plugin-template/.npmignore: -------------------------------------------------------------------------------- 1 | 2 | .eslintignore 3 | .eslintrc 4 | .gitignore 5 | tsconfig.json 6 | pnpm-lock.yaml 7 | 8 | node_modules/ 9 | examples/ 10 | src/ 11 | 12 | demo.gif 13 | README.md 14 | LICENSE -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createSSRApp } from 'vue'; 2 | import App from './App.vue'; 3 | 4 | export const createApp = () => { 5 | const app = createSSRApp(App); 6 | return { app }; 7 | }; 8 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "esnext", 5 | "moduleResolution": "node" 6 | }, 7 | "include": ["vite.config.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /vite-vue2/style.css: -------------------------------------------------------------------------------- 1 | #app { 2 | font-family: Avenir, Helvetica, Arial, sans-serif; 3 | -webkit-font-smoothing: antialiased; 4 | -moz-osx-font-smoothing: grayscale; 5 | text-align: center; 6 | color: #2c3e50; 7 | margin-top: 60px; 8 | } 9 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia'; 2 | import useUserStore from './user'; 3 | 4 | export default () => { 5 | const pinia = createPinia(); 6 | 7 | useUserStore(pinia); 8 | 9 | return pinia; 10 | }; 11 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/style.css: -------------------------------------------------------------------------------- 1 | #app { 2 | font-family: Avenir, Helvetica, Arial, sans-serif; 3 | -webkit-font-smoothing: antialiased; 4 | -moz-osx-font-smoothing: grayscale; 5 | text-align: center; 6 | color: #2c3e50; 7 | margin-top: 60px; 8 | } 9 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import { createVuePlugin } from 'vite-plugin-vue2' 3 | import template from 'vite-plugin-template'; 4 | 5 | export default defineConfig({ 6 | plugins: [createVuePlugin(), template()] 7 | }) -------------------------------------------------------------------------------- /vite-react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ) 12 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import template from 'vite-plugin-template'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react(), template()] 8 | }) 9 | -------------------------------------------------------------------------------- /pnpm-tool-template/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "bracketSpacing": true, 3 | "jsxBracketSameLine": true, 4 | "jsxSingleQuote": false, 5 | "printWidth": 140, 6 | "semi": true, 7 | "useTabs": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "endOfLine": "auto", 11 | "trailingComma": "all" 12 | } 13 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ) 12 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | import store from './store'; 4 | import router from './router'; 5 | 6 | // 创建vue实例 7 | const app = createApp(App); 8 | 9 | app.use(store); 10 | app.use(router); 11 | 12 | // 挂载实例 13 | app.mount('#app'); 14 | -------------------------------------------------------------------------------- /vite-vue3/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from './App.vue'; 3 | import store from './store'; 4 | import router from './router'; 5 | 6 | // 创建vue实例 7 | const app = createApp(App); 8 | 9 | app.use(store); 10 | app.use(router); 11 | 12 | // 挂载实例 13 | app.mount('#app'); 14 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any> 7 | export default component 8 | } 9 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/guide/index.md: -------------------------------------------------------------------------------- 1 | # 快速开始 2 | 3 | ## 安装 4 | 5 | ```bash 6 | npm i @vmejs/core 7 | ``` 8 | 9 | ## 简单使用 10 | 11 | ```ts 12 | import { getDevice } from '@vmejs/core'; 13 | 14 | const browser = getDevice(); 15 | 16 | // do something 17 | ``` 18 | 19 | 20 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/stores/useUserStore.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | 3 | const USER_INFO = { 4 | userName: '易师傅', 5 | id: 1, 6 | sex: '男', 7 | } 8 | 9 | export const useUserStore = defineStore('userInfo', () => { 10 | 11 | const userInfo = reactive(USER_INFO) 12 | 13 | return { 14 | userInfo, 15 | } 16 | }) -------------------------------------------------------------------------------- /vite-vue3-admin/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | 7 | # 本地配置 8 | .env.local 9 | .env.*.local 10 | 11 | # 日志文件 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | 17 | # 编辑器忽略配置 18 | .idea 19 | .vscode 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue'; 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any>; 7 | export default component; 8 | } 9 | -------------------------------------------------------------------------------- /pnpm-tool-template/.npmingnore: -------------------------------------------------------------------------------- 1 | .eslintignore 2 | .eslintrc 3 | .gitignore 4 | .prettierrc 5 | 6 | # 配置 7 | tsconfig.json 8 | tsup.config.ts 9 | pnpm-lock.yaml 10 | pnpm-workspace.yaml 11 | commitlint.config.ts 12 | 13 | # 文件 14 | node_modules/ 15 | examples/ 16 | types 17 | coverage 18 | .changeset 19 | .husky 20 | .github 21 | .vitepress 22 | .changeset -------------------------------------------------------------------------------- /vite-nuxt3-app/src/plugins/directives.ts: -------------------------------------------------------------------------------- 1 | export default defineNuxtPlugin((nuxtApp) => { 2 | nuxtApp.vueApp.directive('focus', { 3 | mounted (el) { 4 | console.log('focus'); 5 | el.focus() 6 | }, 7 | getSSRProps (binding, vnode) { 8 | // you can provide SSR-specific props here 9 | return {} 10 | } 11 | }) 12 | }) -------------------------------------------------------------------------------- /pnpm-tool-template/.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue'; 5 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 6 | const component: DefineComponent<{}, {}, any>; 7 | export default component; 8 | } 9 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/types/shims-store.d.ts: -------------------------------------------------------------------------------- 1 | import { Store } from '@/store'; 2 | import { ElMessage, ElMessageBox } from 'element-plus'; 3 | 4 | declare module '@vue/runtime-core' { 5 | interface ComponentCustomProperties { 6 | $store: Store; 7 | $message: typeof ElMessage; 8 | $confirm: typeof ElMessageBox.confirm; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /pnpm-tool-template/test.ts: -------------------------------------------------------------------------------- 1 | // import { defineComponent, h } from 'vue'; 2 | 3 | // export default defineComponent({ 4 | // name: 'SButton', 5 | 6 | // // template:'' 7 | 8 | // render() { 9 | // return h('button', null, 'MyButton'); 10 | // }, 11 | // }); 12 | 13 | // const fn = () => { 14 | // console.log(dddd, 333) 15 | // } 16 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /vite-react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vite-vue2/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vite-vue3/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/app.vue: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/store/user.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export const useUserStore = defineStore({ 4 | id: 'user', // id必填,且需要唯一 5 | state: () => { 6 | return { 7 | name: '张三' 8 | }; 9 | }, 10 | actions: { 11 | updateName(name: string) { 12 | this.name = name; 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /vite-plugin-template/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | -------------------------------------------------------------------------------- /vite-plugin-template/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": true, 6 | "singleQuote": true, 7 | "quoteProps": "as-needed", 8 | "trailingComma": "all", 9 | "bracketSpacing": true, 10 | "arrowParens": "always", 11 | "requirePragma": false, 12 | "insertPragma": false, 13 | "proseWrap": "preserve", 14 | "endOfLine": "auto" 15 | } -------------------------------------------------------------------------------- /vite-vue2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue2", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "devDependencies": { 11 | "vite": "^2.8.0", 12 | "vite-plugin-vue2": "^1.9.3", 13 | "vue": "^2.6.14", 14 | "vue-template-compiler": "^2.6.14" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import * as path from 'path'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | resolve: { 8 | //设置别名 9 | alias: { 10 | '@': path.resolve(__dirname, 'src') 11 | } 12 | }, 13 | plugins: [vue()] 14 | }); 15 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/store/user.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export const useUserStore = defineStore({ 4 | id: 'user', // id必填,且需要唯一 5 | state: () => { 6 | return { 7 | name: '张三' 8 | }; 9 | }, 10 | actions: { 11 | updateName(name: string) { 12 | this.name = name; 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /vite-vue3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/views/home/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 15 | 16 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/pages/login.vue: -------------------------------------------------------------------------------- 1 | 8 | 14 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/pages/user.vue: -------------------------------------------------------------------------------- 1 | 8 | 14 | -------------------------------------------------------------------------------- /vite-vue3-admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import App from '@/App.vue'; 3 | import router from '@/router'; 4 | import { store } from '@/store'; 5 | import { setupElement } from '@/config/element'; 6 | 7 | // 创建vue实例 8 | const app = createApp(App); 9 | 10 | // 按需引入element-plus插件 11 | setupElement(app); 12 | 13 | app.use(router); 14 | app.use(store); 15 | 16 | // 挂载实例 17 | app.mount('#app'); 18 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/pages/login.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | -------------------------------------------------------------------------------- /vite-vue2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-vue3-admin/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Vite + Vue3 + Typescript + Element-plus 4 | 5 | > ## 一个前端后台管理系统项目 6 | > 7 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! 8 | > 9 | > 备注:模板项目中 `element-plus` 和 `vite-plugin-style-import` 版本依赖较为老,若想使用新版本,请查阅对应官方文档 10 | 11 | 12 | # 安装依赖模块 13 | 14 | npm install 15 | 16 | 17 | 18 | # 开启一个本地服务 localhost:3000 19 | 20 | npm run dev 21 | 22 | 23 | 24 | # 打包 25 | 26 | npm run build 27 | 28 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/pages/login.vue: -------------------------------------------------------------------------------- 1 | 8 | 15 | -------------------------------------------------------------------------------- /vite-react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /vite-nuxt3-app/nuxt.config.ts: -------------------------------------------------------------------------------- 1 | // https://nuxt.com/docs/api/configuration/nuxt-config 2 | export default defineNuxtConfig({ 3 | srcDir: 'src/', 4 | 5 | modules: [ 6 | // ... 7 | '@pinia/nuxt', 8 | '@vueuse/nuxt' 9 | ], 10 | vite: { 11 | css: { 12 | preprocessorOptions: { 13 | scss: { 14 | additionalData: '@import "@/assets/styles/default.scss";' 15 | } 16 | } 17 | } 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/store/user.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia'; 2 | 3 | export default defineStore('user', { 4 | state: () => { 5 | return { 6 | name: '张三', 7 | age: 20 8 | }; 9 | }, 10 | actions: { 11 | updateName(name: string) { 12 | this.name = name; 13 | }, 14 | updateAge(age: number) { 15 | this.age = age; 16 | } 17 | } 18 | }); 19 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue3", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vue-tsc --noEmit && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "vue": "^3.2.25" 12 | }, 13 | "devDependencies": { 14 | "@vitejs/plugin-vue": "^2.2.0", 15 | "typescript": "^4.5.4", 16 | "vite": "^2.8.0", 17 | "vue-tsc": "^0.29.8" 18 | } 19 | } -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/pages/list.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/pages/[id]/index.vue: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue2", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "preview": "vite preview" 9 | }, 10 | "devDependencies": { 11 | "vite-plugin-vue2": "^1.9.3", 12 | "vue": "^2.6.14", 13 | "vite": "link:../../node_modules/vite", 14 | "vite-plugin-progress": "link:../../", 15 | "vue-template-compiler": "^2.6.14" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/App.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 4, 4 | useTabs: false, 5 | semi: true, 6 | vueIndentScriptAndStyle: true, 7 | singleQuote: true, // 单引号 8 | quoteProps: 'as-needed', 9 | bracketSpacing: true, 10 | trailingComma: 'none', 11 | arrowParens: 'always', 12 | insertPragma: false, 13 | requirePragma: false, 14 | proseWrap: 'never', 15 | htmlWhitespaceSensitivity: 'strict', 16 | endOfLine: 'auto' 17 | }; 18 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 4, 4 | useTabs: false, 5 | semi: true, 6 | vueIndentScriptAndStyle: true, 7 | singleQuote: true, // 单引号 8 | quoteProps: 'as-needed', 9 | bracketSpacing: true, 10 | trailingComma: 'none', 11 | arrowParens: 'always', 12 | insertPragma: false, 13 | requirePragma: false, 14 | proseWrap: 'never', 15 | htmlWhitespaceSensitivity: 'strict', 16 | endOfLine: 'auto' 17 | }; 18 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/pages/user-[group]/[id].vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /vite-vue3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "useDefineForClassFields": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "esModuleInterop": true, 12 | "lib": ["esnext", "dom"] 13 | }, 14 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 15 | "references": [{ "path": "./tsconfig.node.json" }] 16 | } 17 | -------------------------------------------------------------------------------- /pnpm-tool-template/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "browser": true, 5 | "es2021": true, 6 | "es6": true, 7 | "node": true 8 | }, 9 | "parser": "@typescript-eslint/parser", 10 | "parserOptions": { 11 | "sourceType": "module", 12 | "ecmaVersion": 12, 13 | "ecmaFeatures": { 14 | "jsx": true, 15 | "tsx": true 16 | } 17 | }, 18 | "plugins": ["@typescript-eslint"], 19 | "rules": { 20 | "no-console": "error", 21 | "no-debugger": "error" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /vite-nuxt3-app/src/components/ListItem.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vite-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-react", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "tsc && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "react": "^17.0.2", 12 | "react-dom": "^17.0.2" 13 | }, 14 | "devDependencies": { 15 | "@types/react": "^17.0.33", 16 | "@types/react-dom": "^17.0.10", 17 | "@vitejs/plugin-react": "^1.0.7", 18 | "typescript": "^4.5.4", 19 | "vite": "^2.8.0" 20 | } 21 | } -------------------------------------------------------------------------------- /pnpm-tool-template/.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /vite-plugin-template/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "browser": true, 5 | "es2021": true, 6 | "es6": true, 7 | "node": true 8 | }, 9 | "extends": [ 10 | "eslint:recommended", 11 | "plugin:@typescript-eslint/recommended", 12 | "prettier", 13 | "plugin:prettier/recommended" 14 | ], 15 | "parser": "@typescript-eslint/parser", 16 | "parserOptions": { 17 | "ecmaVersion": 12, 18 | "sourceType": "module" 19 | }, 20 | "plugins": ["@typescript-eslint"], 21 | "rules": { 22 | "no-console": 1 23 | } 24 | } -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/components/UsePinia.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | -------------------------------------------------------------------------------- /vite-vue3-admin/prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, 3 | tabWidth: 4, 4 | useTabs: false, 5 | semi: true, 6 | vueIndentScriptAndStyle: true, 7 | singleQuote: true, // 单引号 8 | quoteProps: 'as-needed', 9 | bracketSpacing: true, 10 | trailingComma: 'none', 11 | jsxBracketSameLine: false, 12 | jsxSingleQuote: false, 13 | arrowParens: 'always', 14 | insertPragma: false, 15 | requirePragma: false, 16 | proseWrap: 'never', 17 | htmlWhitespaceSensitivity: 'strict', 18 | endOfLine: 'auto' 19 | }; 20 | -------------------------------------------------------------------------------- /vite-plugin-template/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "target": "esnext", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "declaration": true, 8 | "noUnusedLocals": true, 9 | "esModuleInterop": true, 10 | "outDir": "dist", 11 | "lib": ["ESNext"], 12 | "sourceMap": false, 13 | "noEmitOnError": true, 14 | "noImplicitAny": false 15 | }, 16 | "include": [ 17 | "src/*", 18 | "*.d.ts" 19 | ], 20 | "exclude": [ 21 | "node_modules", 22 | "examples", 23 | "dist" 24 | ] 25 | } -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/components/UsePinia.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 21 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | koa2 + vite + ts + vue3 8 | 9 | 10 | 11 |
12 | 13 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/pages/vueUse.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/entry-client.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from './main'; 2 | import { createRouter } from './router'; 3 | import createStore from '@/store'; 4 | 5 | const router = createRouter('client'); 6 | const pinia = createStore(); 7 | 8 | const { app } = createApp(); 9 | 10 | app.use(router); 11 | app.use(pinia); 12 | 13 | // 初始化 pinia 14 | // 注意:__INITIAL_STATE__需要在 src/types/shims-global.d.ts中定义 15 | if (window.__INITIAL_STATE__) { 16 | pinia.state.value = JSON.parse(window.__INITIAL_STATE__); 17 | } 18 | 19 | router.isReady().then(() => { 20 | app.mount('#app', true); 21 | }); 22 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/api/module/index.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/axios'; 2 | 3 | /** 4 | * 登录 5 | */ 6 | 7 | interface IResponseType

{ 8 | code?: number; 9 | status: number; 10 | msg: string; 11 | data: P; 12 | } 13 | interface ILogin { 14 | token: string; 15 | expires: number; 16 | } 17 | export const login = (username: string, password: string) => { 18 | return request>({ 19 | url: '/api/auth/login', 20 | method: 'post', 21 | data: { 22 | username, 23 | password 24 | } 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/api/module/login.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/axios'; 2 | 3 | /** 4 | * 登录 5 | */ 6 | 7 | interface IResponseType

{ 8 | code?: number; 9 | status: number; 10 | msg: string; 11 | data: P; 12 | } 13 | interface ILogin { 14 | token: string; 15 | expires: number; 16 | } 17 | export const login = (username: string, password: string) => { 18 | return request>({ 19 | url: '/api/auth/login', 20 | method: 'post', 21 | data: { 22 | username, 23 | password 24 | } 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/pages/vueUse.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 23 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-react", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "tsc && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "react": "^17.0.2", 12 | "react-dom": "^17.0.2" 13 | }, 14 | "devDependencies": { 15 | "@types/react": "^17.0.33", 16 | "@types/react-dom": "^17.0.10", 17 | "@vitejs/plugin-react": "^1.0.7", 18 | "typescript": "^4.5.4", 19 | "vite": "link:../../node_modules/vite", 20 | "vite-plugin-progress": "link:../../" 21 | } 22 | } -------------------------------------------------------------------------------- /vite-vue3-admin/src/assets/css/reset.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | } 4 | body, div, span, header, footer, nav, section, aside, article, ul, dl, dt, dd, li, a, p, h1, h2, h3, h4,h5, h6, i, b, textarea, button, input, select, figure, figcaption { 5 | padding: 0; 6 | margin: 0; 7 | list-style: none; 8 | font-style: normal; 9 | text-decoration: none; 10 | border: none; 11 | box-sizing: border-box; 12 | font-family: Microsoft Yahei,sans-serif; 13 | -webkit-tap-highlight-color:transparent; 14 | -webkit-font-smoothing: antialiased; 15 | } 16 | html,body,#app,.el-container{ 17 | height: 100%; 18 | } -------------------------------------------------------------------------------- /vite-vue3-admin/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from 'vuex'; 2 | 3 | export interface State { 4 | userInfo: { 5 | id: number; 6 | username: string; 7 | nickname: string; 8 | }; 9 | } 10 | 11 | export const store = createStore({ 12 | state() { 13 | return { 14 | userInfo: { 15 | id: 0, 16 | username: '', 17 | nickname: '' 18 | } 19 | }; 20 | }, 21 | mutations: { 22 | setUserInfo(state, userInfo) { 23 | state.userInfo = userInfo; 24 | } 25 | } 26 | }); 27 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/api/module/index.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/axios'; 2 | 3 | /** 4 | * 登录 5 | */ 6 | 7 | interface IResponseType

{ 8 | code?: number; 9 | status: number; 10 | msg: string; 11 | data: P; 12 | } 13 | interface ILogin { 14 | token: string; 15 | expires: number; 16 | } 17 | export const login = (username: string, password: string) => { 18 | return request>({ 19 | url: '/api/auth/login', 20 | method: 'post', 21 | data: { 22 | username, 23 | password 24 | } 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/api/module/login.ts: -------------------------------------------------------------------------------- 1 | import request from '@/utils/axios'; 2 | 3 | /** 4 | * 登录 5 | */ 6 | 7 | interface IResponseType

{ 8 | code?: number; 9 | status: number; 10 | msg: string; 11 | data: P; 12 | } 13 | interface ILogin { 14 | token: string; 15 | expires: number; 16 | } 17 | export const login = (username: string, password: string) => { 18 | return request>({ 19 | url: '/api/auth/login', 20 | method: 'post', 21 | data: { 22 | username, 23 | password 24 | } 25 | }); 26 | }; 27 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/pages/vueUse.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 25 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "esnext", 5 | "useDefineForClassFields": true, 6 | "module": "esnext", 7 | "moduleResolution": "node", 8 | "strict": true, 9 | "jsx": "preserve", 10 | "sourceMap": true, 11 | "resolveJsonModule": true, 12 | "isolatedModules": true, 13 | "esModuleInterop": true, 14 | "lib": ["esnext", "dom"], 15 | "types": [ 16 | "node" 17 | ], 18 | "paths": { 19 | "@/*": ["src/*"] 20 | } 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "server-dev.js"] 23 | } 24 | -------------------------------------------------------------------------------- /vite-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /vite-vue3/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 23 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 23 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/pages/index.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 23 | -------------------------------------------------------------------------------- /vite-vue3-admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "typeRoots": [ 4 | "node_modules/@types", // 默认值 5 | "src/types" 6 | ], 7 | "target": "esnext", 8 | "module": "esnext", 9 | "moduleResolution": "node", 10 | "strict": true, 11 | "jsx": "preserve", 12 | "sourceMap": true, 13 | "resolveJsonModule": true, 14 | "esModuleInterop": true, 15 | "lib": ["esnext", "dom"], 16 | "types": ["vite/client"], 17 | "skipLibCheck": true, 18 | "baseUrl":".", 19 | "paths": { 20 | "@/*": [ 21 | "src/*", 22 | ] 23 | } 24 | }, 25 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 26 | } 27 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/test.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const Koa = require('koa'); 5 | 6 | (async () => { 7 | const app = new Koa(); 8 | 9 | // 获取index.html 10 | const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8'); 11 | 12 | app.use(async (ctx) => { 13 | let vueTemplate = '

现在假装这是一个vue模板

'; 14 | 15 | // 替换 index.html 中的 标记 16 | let html = template.replace('', vueTemplate); 17 | 18 | ctx.body = html; 19 | }); 20 | 21 | app.listen(9000, () => { 22 | console.log('server is listening in 9000'); 23 | }); 24 | })(); 25 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/utils/axios.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'; 2 | 3 | const service = axios.create(); 4 | 5 | // Request interceptors 6 | service.interceptors.request.use( 7 | (config: AxiosRequestConfig) => { 8 | // do something 9 | return config; 10 | }, 11 | (error: any) => { 12 | Promise.reject(error); 13 | } 14 | ); 15 | 16 | // Response interceptors 17 | service.interceptors.response.use( 18 | async (response: AxiosResponse) => { 19 | console.log(response); 20 | 21 | // do something 22 | }, 23 | (error: any) => { 24 | // do something 25 | return Promise.reject(error); 26 | } 27 | ); 28 | 29 | export default service; 30 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/utils/axios.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'; 2 | 3 | const service = axios.create(); 4 | 5 | // Request interceptors 6 | service.interceptors.request.use( 7 | (config: AxiosRequestConfig) => { 8 | // do something 9 | return config; 10 | }, 11 | (error: any) => { 12 | Promise.reject(error); 13 | } 14 | ); 15 | 16 | // Response interceptors 17 | service.interceptors.response.use( 18 | async (response: AxiosResponse) => { 19 | console.log(response); 20 | 21 | // do something 22 | }, 23 | (error: any) => { 24 | // do something 25 | return Promise.reject(error); 26 | } 27 | ); 28 | 29 | export default service; 30 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue3-ts-pinia", 3 | "private": true, 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vue-tsc --noEmit && vite build", 8 | "preview": "vite preview" 9 | }, 10 | "dependencies": { 11 | "@vueuse/core": "^8.2.0", 12 | "axios": "^0.26.1", 13 | "pinia": "^2.0.12", 14 | "vue": "^3.2.25", 15 | "vue-router": "^4.0.14" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^17.0.23", 19 | "@vitejs/plugin-vue": "^2.2.0", 20 | "typescript": "^4.5.4", 21 | "vite": "link:../../node_modules/vite", 22 | "vite-plugin-template": "link:../../", 23 | "vue-tsc": "^0.29.8" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/shared/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vmejs/shared", 3 | "version": "0.0.1-alpha.1", 4 | "description": "", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "unpkg": "./dist/index.iife.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "require": "./dist/index.js", 12 | "import": "./dist/index.mjs", 13 | "types": "./dist/index.d.ts" 14 | }, 15 | "./*": "./*" 16 | }, 17 | "sideEffects": false, 18 | "engines": { 19 | "node": ">=14", 20 | "pnpm": ">=7.0.0" 21 | }, 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "scripts": { 26 | "test": "echo \"Error: no test specified\" && exit 1" 27 | }, 28 | "keywords": [], 29 | "author": "", 30 | "license": "ISC" 31 | } 32 | -------------------------------------------------------------------------------- /vite-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | button { 41 | font-size: calc(10px + 2vmin); 42 | } 43 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import * as path from 'path'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | resolve: { 8 | //设置别名 9 | alias: { 10 | '@': path.resolve(__dirname, 'src') 11 | } 12 | }, 13 | plugins: [vue()], 14 | server: { 15 | port: 8080, //启动端口 16 | hmr: { 17 | host: 'localhost', 18 | port: 8080 19 | }, 20 | // 设置代理 21 | proxy: { 22 | '/api': { 23 | target: 'your https address', 24 | changeOrigin: true, 25 | rewrite: (path: string) => path.replace(/^\/api/, '') 26 | } 27 | } 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-templates(模板大全) 2 | > ## 该仓库是所有用 vite 构建工具创建的相关项目模板(持续更新) 3 | > 4 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! 5 | 6 | ## 1. koa2-ssr-vite-vue3-ts-pinia 7 | koa2 + vite + vue3 + typescript + pinia 构建的前端 SSR 项目 8 | 9 | ## 2. vite-plugin-template 10 | 每一个写 vite 插件的一个通用模板 11 | 12 | ## 3. vite-react 13 | react + vite + typescript 构建项目模板 14 | 15 | ## 4. vite-vue2 16 | vite + vue2 构建的项目模板 17 | 18 | ## 5. vite-vue3-admin 19 | vite + vue3 + typescript + element-plus 前端后台管理系统项目 20 | 21 | ## 6. vite-vue3-ts-pinia 22 | vite + vue3 + typescript + pinia + vue-router + vueuse 构建的项目模板 23 | 24 | ## 7. vite-vue3 25 | vite + vue3 + typescript 构建的项目模板 26 | 27 | ## 8. pnpm-tool-template 28 | pnpm workspace + typescript 搭建的前端工具库项目模板 29 | 30 | ## 9. vite-nuxt3-app 31 | nuxt3 + vite3 前端 SSR 项目通用模板 32 | -------------------------------------------------------------------------------- /vite-nuxt3-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "build": "nuxt build", 5 | "dev": "nuxt dev", 6 | "generate": "nuxt generate", 7 | "preview": "nuxt preview", 8 | "postinstall": "nuxt prepare" 9 | }, 10 | "devDependencies": { 11 | "@typescript-eslint/eslint-plugin": "5.0.0", 12 | "@typescript-eslint/parser": "^5.44.0", 13 | "eslint": "^8.28.0", 14 | "eslint-config-prettier": "^8.5.0", 15 | "eslint-plugin-prettier": "^4.2.1", 16 | "eslint-plugin-vue": "^9.8.0", 17 | "nuxt": "3.0.0", 18 | "prettier": "^2.8.0", 19 | "sass": "^1.56.1", 20 | "typescript": "^4.9.3" 21 | }, 22 | "dependencies": { 23 | "@pinia/nuxt": "^0.4.5", 24 | "@vueuse/core": "^9.6.0", 25 | "@vueuse/nuxt": "^9.6.0", 26 | "pinia": "^2.0.26" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "typeRoots": [ 4 | "node_modules/@types", // 默认值 5 | "src/types" 6 | ], 7 | "target": "esnext", 8 | "useDefineForClassFields": true, 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "strict": true, 12 | "jsx": "preserve", 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "esModuleInterop": true, 16 | "lib": ["esnext", "dom"], 17 | "baseUrl": "./", 18 | "paths": { 19 | "@": ["src"], 20 | "@/*": ["src/*"] 21 | } 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; 2 | 3 | const routes: Array = [ 4 | { 5 | path: '/login', 6 | name: 'Login', 7 | meta: { 8 | title: '登录', 9 | keepAlive: true, 10 | requireAuth: false 11 | }, 12 | component: () => import('@/views/login/login.vue') 13 | }, 14 | { 15 | path: '/', 16 | name: 'Index', 17 | meta: { 18 | title: '首页', 19 | keepAlive: true, 20 | requireAuth: true 21 | }, 22 | component: () => import('@/views/home/index.vue') 23 | } 24 | ]; 25 | const router = createRouter({ 26 | history: createWebHistory(), 27 | routes 28 | }); 29 | export default router; 30 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/components/UsePinia.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 27 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | button { 41 | font-size: calc(10px + 2vmin); 42 | } 43 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "typeRoots": [ 4 | "node_modules/@types", // 默认值 5 | "src/types" 6 | ], 7 | "target": "esnext", 8 | "useDefineForClassFields": true, 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "strict": true, 12 | "jsx": "preserve", 13 | "sourceMap": true, 14 | "resolveJsonModule": true, 15 | "esModuleInterop": true, 16 | "lib": ["esnext", "dom"], 17 | "baseUrl": "./", 18 | "paths": { 19 | "@": ["src"], 20 | "@/*": ["src/*"] 21 | } 22 | }, 23 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import template from 'vite-plugin-template'; 4 | import * as path from 'path'; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | resolve: { 9 | alias: { 10 | '@': path.resolve(__dirname, 'src') 11 | } 12 | }, 13 | plugins: [vue(), template()], 14 | server: { 15 | port: 8080, 16 | hmr: { 17 | host: 'localhost', 18 | port: 8080 19 | }, 20 | proxy: { 21 | '/api': { 22 | target: 'your https address', 23 | changeOrigin: true, 24 | rewrite: (path: string) => path.replace(/^\/api/, '') 25 | } 26 | } 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/types/shims-axios.d.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | /** 3 | * 自定义扩展axios模块 4 | * @author Maybe 5 | */ 6 | declare module 'axios' { 7 | export interface AxiosInstance { 8 | (config: AxiosRequestConfig): Promise; 9 | request(config: AxiosRequestConfig): Promise; 10 | get(url: string, config?: AxiosRequestConfig): Promise; 11 | delete(url: string, config?: AxiosRequestConfig): Promise; 12 | head(url: string, config?: AxiosRequestConfig): Promise; 13 | post(url: string, data?: any, config?: AxiosRequestConfig): Promise; 14 | put(url: string, data?: any, config?: AxiosRequestConfig): Promise; 15 | patch(url: string, data?: any, config?: AxiosRequestConfig): Promise; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@vmejs/core", 3 | "version": "0.0.1-alpha.1", 4 | "description": "", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "unpkg": "./dist/index.iife.js", 8 | "types": "./dist/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "require": "./dist/index.js", 12 | "import": "./dist/index.mjs", 13 | "types": "./dist/index.d.ts" 14 | }, 15 | "./*": "./*" 16 | }, 17 | "sideEffects": false, 18 | "engines": { 19 | "node": ">=14", 20 | "pnpm": ">=7.0.0" 21 | }, 22 | "publishConfig": { 23 | "access": "public" 24 | }, 25 | "scripts": { 26 | "test": "echo \"Error: no test specified\" && exit 1" 27 | }, 28 | "keywords": [], 29 | "author": "", 30 | "license": "ISC", 31 | "dependencies": { 32 | "@vmejs/shared": "workspace:*" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/types/shims-axios.d.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | /** 3 | * 自定义扩展axios模块 4 | * @author Maybe 5 | */ 6 | declare module 'axios' { 7 | export interface AxiosInstance { 8 | (config: AxiosRequestConfig): Promise; 9 | request(config: AxiosRequestConfig): Promise; 10 | get(url: string, config?: AxiosRequestConfig): Promise; 11 | delete(url: string, config?: AxiosRequestConfig): Promise; 12 | head(url: string, config?: AxiosRequestConfig): Promise; 13 | post(url: string, data?: any, config?: AxiosRequestConfig): Promise; 14 | put(url: string, data?: any, config?: AxiosRequestConfig): Promise; 15 | patch(url: string, data?: any, config?: AxiosRequestConfig): Promise; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/types/shims-axios.d.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | /** 3 | * 自定义扩展axios模块 4 | * @author Maybe 5 | */ 6 | declare module 'axios' { 7 | export interface AxiosInstance { 8 | (config: AxiosRequestConfig): Promise; 9 | request(config: AxiosRequestConfig): Promise; 10 | get(url: string, config?: AxiosRequestConfig): Promise; 11 | delete(url: string, config?: AxiosRequestConfig): Promise; 12 | head(url: string, config?: AxiosRequestConfig): Promise; 13 | post(url: string, data?: any, config?: AxiosRequestConfig): Promise; 14 | put(url: string, data?: any, config?: AxiosRequestConfig): Promise; 15 | patch(url: string, data?: any, config?: AxiosRequestConfig): Promise; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vite-vue3/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + Typescript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 ` 36 | -------------------------------------------------------------------------------- /pnpm-tool-template/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig([ 4 | { 5 | entry: ['packages/core/index.ts'], 6 | format: ['cjs', 'esm', 'iife'], 7 | outDir: 'packages/core/dist', 8 | dts: true, // 添加 .d.ts 文件 9 | metafile: true, // 添加 meta 文件 10 | minify: true, // 压缩 11 | splitting: false, 12 | sourcemap: true, // 添加 sourcemap 文件 13 | clean: true, // 是否先清除打包的目录,例如 dist 14 | outExtension: outExtensionFn, 15 | }, 16 | { 17 | entry: ['packages/shared/index.ts'], 18 | format: ['cjs', 'esm', 'iife'], 19 | outDir: 'packages/shared/dist', 20 | dts: true, // 添加 .d.ts 文件 21 | metafile: true, // 添加 meta 文件 22 | minify: true, // 压缩 23 | splitting: false, 24 | sourcemap: true, // 添加 sourcemap 文件 25 | clean: true, // 是否先清除打包的目录,例如 dist 26 | outExtension: outExtensionFn, 27 | }, 28 | ]); 29 | 30 | function outExtensionFn({ format }) { 31 | if (format === 'esm') return { js: `.${format}.js` }; 32 | if (format === 'iife') return { js: `.mjs` }; 33 | return { js: `.js` }; 34 | } 35 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/pages/request.vue: -------------------------------------------------------------------------------- 1 | 7 | 36 | -------------------------------------------------------------------------------- /pnpm-tool-template/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 vmejs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vite-vue3/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 35 | 36 | 53 | -------------------------------------------------------------------------------- /vite-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import logo from './logo.svg' 3 | import './App.css' 4 | 5 | function App() { 6 | const [count, setCount] = useState(0) 7 | 8 | return ( 9 |
10 |
11 | logo 12 |

Hello Vite + React!

13 |

14 | 17 |

18 |

19 | Edit App.tsx and save to test HMR updates. 20 |

21 |

22 | 28 | Learn React 29 | 30 | {' | '} 31 | 37 | Vite Docs 38 | 39 |

40 |
41 |
42 | ) 43 | } 44 | 45 | export default App 46 | -------------------------------------------------------------------------------- /vite-vue3-admin/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import styleImport from 'vite-plugin-style-import'; 4 | import path from 'path'; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | resolve: { 9 | alias: { 10 | '@': path.resolve(__dirname, 'src') //设置别名 11 | } 12 | }, 13 | plugins: [ 14 | vue(), 15 | styleImport({ 16 | libs: [ 17 | { 18 | libraryName: 'element-plus', 19 | esModule: true, 20 | resolveStyle: (name) => { 21 | // 解决引入element-plus中文css不存在问题 22 | // if (name === 'locale') { 23 | // return 'element-plus/lib/theme-chalk/el-option.css'; 24 | // } 25 | return `element-plus/lib/theme-chalk/${name}.css`; 26 | }, 27 | ensureStyleFile: true // 忽略文件是否存在, 导入不存在的CSS文件时防止错误。 28 | } 29 | ] 30 | }) 31 | ], 32 | server: { 33 | port: 3000, //启动端口 34 | hmr: { 35 | host: '127.0.0.1', 36 | port: 3000 37 | } 38 | } 39 | }); 40 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | sidebar: false 4 | 5 | title: vmejs 6 | titleTemplate: 一个令人疯狂的开源前端工具库 7 | 8 | hero: 9 | name: vmejs 10 | text: 一个令人疯狂的开源前端工具库 11 | tagline: 🎉 🎉 🎉 一个令人疯狂的开源前端工具库,A crazy tool library, So may you v me 50? 12 | actions: 13 | - theme: brand 14 | text: 快速开始 15 | link: /guide/ 16 | - theme: alt 17 | text: 工具函数集合 18 | link: /core/getDevice/ 19 | - theme: alt 20 | text: Vue Hooks 21 | link: /vue 22 | - theme: alt 23 | text: React Hooks 24 | link: /react 25 | - theme: alt 26 | text: View on GitHub 27 | link: https://github.com/jeddygong 28 | 29 | features: 30 | - title: 功能丰富 31 | details: 众多工具函数任你选择 32 | icon: 🎛 33 | - title: React Hooks(建设中) 34 | details: 集成你想要的 React hooks 35 | icon: 🚀 36 | - title: Vue Hooks(建设中) 37 | details: 集成你想要的 Vue hooks 38 | icon: ⚡ 39 | - title: 强类型支持 40 | details: 使用TypeScript编写,良好类型支持 41 | icon: 🦾 42 | - title: SSR 支持(建设中) 43 | details: 支持服务端渲染,无需额外配置 44 | icon: 🛠 45 | - title: 轻量级 46 | details: 不依赖任何第三方库,体积小巧 47 | icon: ☁️ 48 | - title: 更多插件支持 49 | details: (建设中...) 50 | icon: 🔌 51 | - title: 更多功能 52 | details: (持续充电建设中...) 53 | icon: 🔋 54 | --- 55 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | import logo from './logo.svg' 3 | import './App.css' 4 | 5 | function App() { 6 | const [count, setCount] = useState(0) 7 | 8 | return ( 9 |
10 |
11 | logo 12 |

Hello Vite + React!

13 |

14 | 17 |

18 |

19 | Edit App.tsx and save to test HMR updates. 20 |

21 |

22 | 28 | Learn React 29 | 30 | {' | '} 31 | 37 | Vite Docs 38 | 39 |

40 |
41 |
42 | ) 43 | } 44 | 45 | export default App 46 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/server-prod.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | 3 | const Koa = require('koa'); 4 | const sendFile = require('koa-send'); 5 | 6 | const path = require('path'); 7 | const fs = require('fs'); 8 | 9 | const resolve = (p) => path.resolve(__dirname, p); 10 | 11 | const clientRoot = resolve('dist/client'); 12 | const template = fs.readFileSync(resolve('dist/client/index.html'), 'utf-8'); 13 | const render = require('./dist/server/entry-server.js').render; 14 | const manifest = require('./dist/client/ssr-manifest.json'); 15 | 16 | (async () => { 17 | const app = new Koa(); 18 | 19 | app.use(async (ctx) => { 20 | // 请求的是静态资源 或者/favicon.ico 21 | if (ctx.path.startsWith('/assets')) { 22 | await sendFile(ctx, ctx.path, { root: clientRoot }); 23 | return; 24 | } 25 | 26 | const [renderedHtml, state, preloadLinks] = await render(ctx, manifest); 27 | 28 | const html = template 29 | .replace('', preloadLinks) 30 | .replace('', state) 31 | .replace('', renderedHtml); 32 | 33 | ctx.type = 'text/html'; 34 | ctx.body = html; 35 | }); 36 | 37 | app.listen(8080, () => console.log('started server on http://localhost:8080')); 38 | })(); 39 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/config/element.ts: -------------------------------------------------------------------------------- 1 | import lang from 'element-plus/lib/locale/lang/zh-tw'; 2 | import 'dayjs/locale/zh-tw'; 3 | import { 4 | locale, 5 | ElAside, 6 | ElButton, 7 | ElContainer, 8 | ElHeader, 9 | ElMain, 10 | ElMenu, 11 | ElSubmenu, 12 | ElMenuItem, 13 | ElCard, 14 | ElForm, 15 | ElFormItem, 16 | ElInput, 17 | ElIcon, 18 | ElInfiniteScroll, 19 | ElLoading, 20 | ElMessage, 21 | ElMessageBox, 22 | ElNotification 23 | } from 'element-plus'; 24 | 25 | const components = [ 26 | ElAside, 27 | ElButton, 28 | ElContainer, 29 | ElHeader, 30 | ElMain, 31 | ElMenu, 32 | ElSubmenu, 33 | ElMenuItem, 34 | ElCard, 35 | ElForm, 36 | ElFormItem, 37 | ElInput, 38 | ElIcon 39 | ]; 40 | 41 | const plugins = [ElInfiniteScroll, ElLoading, ElMessage, ElMessageBox, ElNotification]; 42 | 43 | export const setupElement = (app: any, options = {}) => { 44 | // 引入语言 45 | locale(lang); 46 | // 全局注册组件 47 | components.forEach((component) => { 48 | app.component(component.name, component); 49 | }); 50 | 51 | // 注册element-plus services 52 | plugins.forEach((plugin) => { 53 | app.use(plugin); 54 | }); 55 | 56 | // 设置全局option,默认 {} 57 | app.config.globalProperties.$ELEMENT = options; 58 | }; 59 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.cz-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | types: [ 5 | { value: 'feature', name: 'feature: 增加新功能' }, 6 | { value: 'bug', name: 'bug: 测试反馈bug列表中的bug号' }, 7 | { value: 'fix', name: 'fix: 修复bug' }, 8 | { value: 'ui', name: 'ui: 更新UI' }, 9 | { value: 'docs', name: 'docs: 文档变更' }, 10 | { value: 'style', name: 'style: 代码格式(不影响代码运行的变动)' }, 11 | { value: 'perf', name: 'perf: 性能优化' }, 12 | { value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)' }, 13 | { value: 'release', name: 'release: 发布' }, 14 | { value: 'deploy', name: 'deploy: 部署' }, 15 | { value: 'test', name: 'test: 增加测试' }, 16 | { value: 'chore', name: 'chore: 构建过程或辅助工具的变动(更改配置文件)' }, 17 | { value: 'revert', name: 'revert: 回退' }, 18 | { value: 'build', name: 'build: 打包' } 19 | ], 20 | // override the messages, defaults are as follows 21 | messages: { 22 | type: '请选择提交类型:', 23 | customScope: '请输入您修改的范围(可选):', 24 | subject: '请简要描述提交 message (必填):', 25 | body: '请输入详细描述(可选,待优化去除,跳过即可):', 26 | footer: '请输入要关闭的issue(待优化去除,跳过即可):', 27 | confirmCommit: '确认使用以上信息提交?(y/n/e/h)' 28 | }, 29 | allowCustomScopes: true, 30 | skipQuestions: ['body', 'footer'], 31 | subjectLimit: 72 32 | }; 33 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; 2 | 3 | const routes: Array = [ 4 | { 5 | path: '/login', 6 | name: 'LoginPage', 7 | meta: { 8 | title: '登录', 9 | keepAlive: true, 10 | requireAuth: false 11 | }, 12 | component: () => import('@/pages/login.vue') 13 | }, 14 | { 15 | path: '/', 16 | name: 'IndexPage', 17 | meta: { 18 | title: '首页', 19 | keepAlive: true, 20 | requireAuth: true 21 | }, 22 | component: () => import('@/pages/index.vue') 23 | }, 24 | { 25 | path: '/vueUse', 26 | name: 'VueUse', 27 | meta: { 28 | title: 'vueUse demo', 29 | keepAlive: true, 30 | requireAuth: true 31 | }, 32 | component: () => import('@/pages/vueUse.vue') 33 | }, 34 | { 35 | path: '/request', 36 | name: 'RequestPage', 37 | meta: { 38 | title: 'request demo', 39 | keepAlive: true, 40 | requireAuth: true 41 | }, 42 | component: () => import('@/pages/request.vue') 43 | } 44 | ]; 45 | 46 | const router = createRouter({ 47 | history: createWebHistory(), 48 | routes 49 | }); 50 | export default router; 51 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/.cz-config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | types: [ 5 | { value: 'feature', name: 'feature: 增加新功能' }, 6 | { value: 'bug', name: 'bug: 测试反馈bug列表中的bug号' }, 7 | { value: 'fix', name: 'fix: 修复bug' }, 8 | { value: 'ui', name: 'ui: 更新UI' }, 9 | { value: 'docs', name: 'docs: 文档变更' }, 10 | { value: 'style', name: 'style: 代码格式(不影响代码运行的变动)' }, 11 | { value: 'perf', name: 'perf: 性能优化' }, 12 | { value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)' }, 13 | { value: 'release', name: 'release: 发布' }, 14 | { value: 'deploy', name: 'deploy: 部署' }, 15 | { value: 'test', name: 'test: 增加测试' }, 16 | { value: 'chore', name: 'chore: 构建过程或辅助工具的变动(更改配置文件)' }, 17 | { value: 'revert', name: 'revert: 回退' }, 18 | { value: 'build', name: 'build: 打包' } 19 | ], 20 | // override the messages, defaults are as follows 21 | messages: { 22 | type: '请选择提交类型:', 23 | customScope: '请输入您修改的范围(可选):', 24 | subject: '请简要描述提交 message (必填):', 25 | body: '请输入详细描述(可选,待优化去除,跳过即可):', 26 | footer: '请输入要关闭的issue(待优化去除,跳过即可):', 27 | confirmCommit: '确认使用以上信息提交?(y/n/e/h)' 28 | }, 29 | allowCustomScopes: true, 30 | skipQuestions: ['body', 'footer'], 31 | subjectLimit: 72 32 | }; 33 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/getDevice/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | category: UA 3 | --- 4 | 5 | # getDevice 6 | 7 | 用于从 User-Agent(用户代理数据) 中解析出 `设备类型与供应商`,在浏览器(客户端)或 node.js(服务器端)中使用。 8 | 9 | ## Usage 10 | 11 | ```ts 12 | import { getDevice } from '@vmejs/core'; 13 | 14 | const browser = getDevice(); 15 | 16 | // do something 17 | ``` 18 | 19 | ## 文档 20 | 21 | ### 参数 [ua]:可选] 22 | 23 | - 浏览器(客户端)中使用 [ua 可选] 24 | 25 | ```ts 26 | import { getDevice } from '@vmejs/core'; 27 | // 未带参数 28 | const browser = getDevice(); 29 | 30 | // 使用参数 31 | const browser = getDevice(window.navigator.userAgent); 32 | ``` 33 | 34 | - node.js(服务器端)中使用 [ua 必传] 35 | 36 | ```ts 37 | import http from 'http'; 38 | import { getDevice } from '@vmejs/core'; 39 | 40 | http 41 | .createServer(function (req, res) { 42 | // get user-agent header 43 | const browser = getDevice(req.headers['user-agent']); 44 | 45 | // write the result as response 46 | res.end(JSON.stringify(ua, null, ' ')); 47 | }) 48 | .listen(3000, '127.0.0.1'); 49 | ``` 50 | 51 | ### 返回值:`{model: '', vendor: ''}` 52 | 53 | - device.model:常见设备类型 54 | 55 | ```bash 56 | # Chrome/其它 57 | pc 58 | 59 | # ios/android/平板 60 | mobile 61 | ``` 62 | 63 | - device.vendor:常见供应商 64 | 65 | ```bash 66 | # mobile 常见供应商: 67 | Samsung, Apple, Coogle, Huawei, Xiaomi, OPPO, Vivo 68 | 69 | # 其它 70 | other 71 | ``` 72 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue3/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; 2 | 3 | const routes: Array = [ 4 | { 5 | path: '/login', 6 | name: 'LoginPage', 7 | meta: { 8 | title: '登录', 9 | keepAlive: true, 10 | requireAuth: false 11 | }, 12 | component: () => import('@/pages/login.vue') 13 | }, 14 | { 15 | path: '/', 16 | name: 'IndexPage', 17 | meta: { 18 | title: '首页', 19 | keepAlive: true, 20 | requireAuth: true 21 | }, 22 | component: () => import('@/pages/index.vue') 23 | }, 24 | { 25 | path: '/vueUse', 26 | name: 'VueUse', 27 | meta: { 28 | title: 'vueUse demo', 29 | keepAlive: true, 30 | requireAuth: true 31 | }, 32 | component: () => import('@/pages/vueUse.vue') 33 | }, 34 | { 35 | path: '/request', 36 | name: 'RequestPage', 37 | meta: { 38 | title: 'request demo', 39 | keepAlive: true, 40 | requireAuth: true 41 | }, 42 | component: () => import('@/pages/request.vue') 43 | } 44 | ]; 45 | 46 | const router = createRouter({ 47 | history: createWebHistory(), 48 | routes 49 | }); 50 | export default router; 51 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | const Guide = [{ text: 'Get Started', link: '/guide/' }]; 2 | 3 | const functions = [Guide, { text: 'getDevice', link: '/core/getDevice/' }]; 4 | 5 | const vueHooks = [functions, { text: '建设中', link: '' }]; 6 | 7 | const reactHooks = [functions, { text: '建设中', link: '' }]; 8 | 9 | const DefaultSideBar = [ 10 | { text: '指导', items: Guide }, 11 | { text: '工具函数集合', items: functions }, 12 | { text: 'Vue Hooks集合', items: vueHooks }, 13 | { text: 'React Hooks集合', items: reactHooks }, 14 | ]; 15 | 16 | export default { 17 | base: '/vmejs/', 18 | title: 'vmejs', 19 | lang: 'zh-CN', 20 | themeConfig: { 21 | logo: '/logo.png', 22 | lastUpdated: true, 23 | lastUpdatedText: '最后修改时间', 24 | socialLinks: [{ icon: 'github', link: 'https://github.com/vmejs/vmejs' }], 25 | // editLinks: true, 26 | // editLink: { 27 | // pattern: 'https://github.com/vmejs/vmejs/main/docs/:path', 28 | // text: '为此页提供修改建议', 29 | // }, 30 | nav: [ 31 | { text: '指南', link: '/guild/' }, 32 | { text: '函数集合', link: '/core/getDevice/' }, 33 | ], 34 | // 侧边栏 35 | sidebar: { 36 | '/guide/': [ 37 | { 38 | text: '', 39 | items: DefaultSideBar, 40 | }, 41 | ], 42 | '/core/': [ 43 | { 44 | text: '', 45 | items: DefaultSideBar, 46 | }, 47 | ], 48 | }, 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /pnpm-tool-template/.github/workflows/docs-deploy.yml: -------------------------------------------------------------------------------- 1 | on: # 触发条件 2 | # 每当 push 到 main 分支时触发部署 3 | push: 4 | branches: [main] 5 | 6 | jobs: 7 | docs: 8 | runs-on: ubuntu-latest # 指定运行所需要的虚拟机环境(必填) 9 | 10 | steps: 11 | - uses: actions/checkout@v3 12 | with: 13 | # “最近更新时间” 等 git 日志相关信息,需要拉取全部提交记录 14 | fetch-depth: 0 15 | 16 | - name: Install pnpm 17 | uses: pnpm/action-setup@v2 18 | with: 19 | version: 7 20 | 21 | - name: Setup Node.js 22 | uses: actions/setup-node@v2 23 | with: 24 | # 选择要使用的 node 版本 25 | node-version: '16' 26 | cache: 'pnpm' 27 | 28 | # 如果缓存没有命中,安装依赖 29 | - name: Install dependencies 30 | run: pnpm install --no-frozen-lockfile --ignore-scripts 31 | 32 | # 运行构建脚本 33 | - name: Build vitepress site 34 | run: pnpm docs:build 35 | env: 36 | DOC_ENV: preview 37 | NODE_OPTIONS: --max-old-space-size=4096 38 | 39 | # 查看 workflow 的文档来获取更多信息 40 | # @see https://github.com/crazy-max/ghaction-github-pages 41 | - name: Deploy to GitHub Pages 42 | uses: crazy-max/ghaction-github-pages@v2 43 | # 环境变量 44 | env: 45 | # 对应 github 设置的 ACTION_SECRET 46 | GITHUB_TOKEN: ${{ secrets.ACTION_SECRET }} 47 | with: 48 | # 部署到 gh-pages 分支 49 | target_branch: gh-pages 50 | # 部署目录为 vitepress 的默认输出目录 51 | build_dir: packages/.vitepress/dist 52 | -------------------------------------------------------------------------------- /vite-vue2/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /vite-react/src/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-vue2/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/favicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/shared/is/index.ts: -------------------------------------------------------------------------------- 1 | export const isClient = typeof window !== 'undefined'; 2 | const toString = Object.prototype.toString; 3 | export const isArray = Array.isArray; 4 | export const isMap = (val: unknown): val is Map => toString.call(val) === '[object Map]'; 5 | export const isSet = (val: unknown): val is Set => toString.call(val) === '[object Set]'; 6 | 7 | export const isDate = (val: unknown): val is Date => toString.call(val) === '[object Date]'; 8 | export const isBoolean = (val: unknown): val is boolean => typeof val === 'boolean'; 9 | export const isFunction = (val: unknown): val is T => typeof val === 'function'; 10 | export const isNumber = (val: unknown): val is number => typeof val === 'number'; 11 | export const isString = (val: unknown): val is string => typeof val === 'string'; 12 | export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'; 13 | export const isObject = (val: unknown): val is Record => toString.call(val) === '[object Object]'; 14 | 15 | export const isPromise = (val: unknown): val is Promise => { 16 | return isObject(val) && isFunction(val.then) && isFunction(val.catch); 17 | }; 18 | 19 | export const isWindow = (val: unknown): val is Window => typeof window !== 'undefined' && toString.call(val) === '[object Window]'; 20 | export const isIOS = /* #__PURE__ */ isClient && window?.navigator?.userAgent && /iP(ad|hone|od)/.test(window.navigator.userAgent); 21 | export const hasOwn = (val: T, key: K): key is K => Object.prototype.hasOwnProperty.call(val, key); 22 | -------------------------------------------------------------------------------- /pnpm-tool-template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vmejs", 3 | "version": "0.0.1-alpha.1", 4 | "description": "", 5 | "main": "index.js", 6 | "keywords": [], 7 | "author": "", 8 | "license": "ISC", 9 | "scripts": { 10 | "preinstall": "npx only-allow pnpm", 11 | "prepare": "husky install", 12 | "dev": "tsup --watch", 13 | "build": "tsup", 14 | "docs:dev": "vitepress dev packages", 15 | "docs:build": "vitepress build packages", 16 | "release": "changeset publish", 17 | "lint": "eslint . --ext .vue,.js,.ts,.jsx,.tsx,.json --max-warnings 0 --cache", 18 | "lint:fix": "pnpm run lint --fix", 19 | "format": "prettier --write --cache .", 20 | "test": "vitest run", 21 | "test:update": "vitest test", 22 | "coverage": "vitest run --coverage" 23 | }, 24 | "lint-staged": { 25 | "*.{vue,js,ts,jsx,tsx,json}": [ 26 | "pnpm run lint", 27 | "pnpm run format" 28 | ] 29 | }, 30 | "devDependencies": { 31 | "@changesets/cli": "^2.25.2", 32 | "@commitlint/cli": "^17.2.0", 33 | "@commitlint/config-conventional": "^17.2.0", 34 | "@types/node": "^18.11.9", 35 | "@typescript-eslint/eslint-plugin": "^5.42.1", 36 | "@typescript-eslint/parser": "^5.42.1", 37 | "@vitest/coverage-c8": "^0.25.1", 38 | "eslint": "^8.27.0", 39 | "eslint-config-prettier": "^8.5.0", 40 | "eslint-plugin-prettier": "^4.2.1", 41 | "husky": "^8.0.2", 42 | "lint-staged": "^13.0.3", 43 | "prettier": "^2.7.1", 44 | "tsup": "^6.4.0", 45 | "typescript": "^4.8.4", 46 | "vitepress": "1.0.0-alpha.28", 47 | "vitest": "^0.25.1" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional', 'cz'], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', 7 | [ 8 | 'feature', // 新功能(feature) 9 | 'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况 10 | 'fix', // 修补bug 11 | 'ui', // 更新 ui 12 | 'docs', // 文档(documentation) 13 | 'style', // 格式(不影响代码运行的变动) 14 | 'perf', // 性能优化 15 | 'release', // 发布 16 | 'deploy', // 部署 17 | 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动) 18 | 'test', // 增加测试 19 | 'chore', // 构建过程或辅助工具的变动 20 | 'revert', // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit) 21 | 'merge', // 合并分支, 例如: merge(前端页面): feature-xxxx修改线程地址 22 | 'build' // 打包 23 | ] 24 | ], 25 | // 格式 小写 26 | 'type-case': [2, 'always', 'lower-case'], 27 | // 不能为空 28 | 'type-empty': [2, 'never'], 29 | // 范围不能为空 30 | 'scope-empty': [2, 'never'], 31 | // 范围格式 32 | 'scope-case': [0], 33 | // 主要 message 不能为空 34 | 'subject-empty': [2, 'never'], 35 | // 以什么为结束标志,禁用 36 | 'subject-full-stop': [0, 'never'], 37 | // 格式,禁用 38 | 'subject-case': [0, 'never'], 39 | // 以空行开头 40 | 'body-leading-blank': [1, 'always'], 41 | 'header-max-length': [0, 'always', 72] 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional', 'cz'], 3 | rules: { 4 | 'type-enum': [ 5 | 2, 6 | 'always', 7 | [ 8 | 'feature', // 新功能(feature) 9 | 'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况 10 | 'fix', // 修补bug 11 | 'ui', // 更新 ui 12 | 'docs', // 文档(documentation) 13 | 'style', // 格式(不影响代码运行的变动) 14 | 'perf', // 性能优化 15 | 'release', // 发布 16 | 'deploy', // 部署 17 | 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动) 18 | 'test', // 增加测试 19 | 'chore', // 构建过程或辅助工具的变动 20 | 'revert', // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit) 21 | 'merge', // 合并分支, 例如: merge(前端页面): feature-xxxx修改线程地址 22 | 'build' // 打包 23 | ] 24 | ], 25 | // 格式 小写 26 | 'type-case': [2, 'always', 'lower-case'], 27 | // 不能为空 28 | 'type-empty': [2, 'never'], 29 | // 范围不能为空 30 | 'scope-empty': [2, 'never'], 31 | // 范围格式 32 | 'scope-case': [0], 33 | // 主要 message 不能为空 34 | 'subject-empty': [2, 'never'], 35 | // 以什么为结束标志,禁用 36 | 'subject-full-stop': [0, 'never'], 37 | // 格式,禁用 38 | 'subject-case': [0, 'never'], 39 | // 以空行开头 40 | 'body-leading-blank': [1, 'always'], 41 | 'header-max-length': [0, 'always', 72] 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/server-dev.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const Koa = require('koa'); 5 | const koaConnect = require('koa-connect'); 6 | 7 | const vite = require('vite'); 8 | 9 | (async () => { 10 | const app = new Koa(); 11 | 12 | // 创建 vite 服务 13 | const viteServer = await vite.createServer({ 14 | root: process.cwd(), 15 | logLevel: 'error', 16 | server: { 17 | middlewareMode: true 18 | } 19 | }); 20 | 21 | // 注册 vite 的 Connect 实例作为中间件(注意:vite.middlewares 是一个 Connect 实例) 22 | app.use(koaConnect(viteServer.middlewares)); 23 | 24 | app.use(async (ctx) => { 25 | try { 26 | // 1. 获取index.html 27 | let template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8'); 28 | 29 | // 2. 应用 Vite HTML 转换。这将会注入 Vite HMR 客户端, 30 | template = await viteServer.transformIndexHtml(ctx.path, template); 31 | 32 | // 3. 加载服务器入口, vite.ssrLoadModule 将自动转换 33 | const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts'); 34 | 35 | // 4. 渲染应用的 HTML 36 | const [renderedHtml, state] = await render(ctx, {}); 37 | 38 | const html = template 39 | .replace('', renderedHtml) 40 | .replace('', state); 41 | 42 | ctx.type = 'text/html'; 43 | ctx.body = html; 44 | } catch (e) { 45 | viteServer && viteServer.ssrFixStacktrace(e); 46 | console.log(e.stack); 47 | ctx.throw(500, e.stack); 48 | } 49 | }); 50 | 51 | app.listen(9000, () => { 52 | console.log('server is listening in 9000'); 53 | }); 54 | })(); 55 | -------------------------------------------------------------------------------- /vite-vue3-admin/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'vue-eslint-parser', 3 | 4 | parserOptions: { 5 | parser: '@typescript-eslint/parser', 6 | ecmaVersion: 2020, 7 | sourceType: 'module', 8 | ecmaFeatures: { 9 | jsx: true 10 | } 11 | }, 12 | 13 | extends: [ 14 | 'plugin:vue/vue3-recommended', 15 | 'plugin:@typescript-eslint/recommended', 16 | 'prettier', 17 | 'plugin:prettier/recommended' 18 | ], 19 | 20 | rules: { 21 | '@typescript-eslint/ban-ts-ignore': 'off', 22 | '@typescript-eslint/explicit-function-return-type': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | '@typescript-eslint/no-var-requires': 'off', 25 | '@typescript-eslint/no-empty-function': 'off', 26 | 'vue/custom-event-name-casing': 'off', 27 | 'no-use-before-define': 'off', 28 | '@typescript-eslint/no-use-before-define': 'off', 29 | '@typescript-eslint/ban-ts-comment': 'off', 30 | '@typescript-eslint/ban-types': 'off', 31 | '@typescript-eslint/no-non-null-assertion': 'off', 32 | '@typescript-eslint/explicit-module-boundary-types': 'off', 33 | '@typescript-eslint/no-unused-vars': [ 34 | 'error', 35 | { 36 | argsIgnorePattern: '^h$', 37 | varsIgnorePattern: '^h$' 38 | } 39 | ], 40 | 'no-unused-vars': [ 41 | 'error', 42 | { 43 | argsIgnorePattern: '^h$', 44 | varsIgnorePattern: '^h$' 45 | } 46 | ], 47 | 'space-before-function-paren': 'off', 48 | quotes: ['error', 'single'], 49 | 'comma-dangle': ['error', 'never'] 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'vue-eslint-parser', 3 | 4 | parserOptions: { 5 | parser: '@typescript-eslint/parser', 6 | ecmaVersion: 2020, 7 | sourceType: 'module', 8 | ecmaFeatures: { 9 | jsx: true 10 | } 11 | }, 12 | 13 | extends: [ 14 | 'plugin:vue/vue3-recommended', 15 | 'plugin:@typescript-eslint/recommended', 16 | 'prettier', 17 | 'plugin:prettier/recommended' 18 | ], 19 | 20 | rules: { 21 | '@typescript-eslint/ban-ts-ignore': 'off', 22 | '@typescript-eslint/explicit-function-return-type': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | '@typescript-eslint/no-var-requires': 'off', 25 | '@typescript-eslint/no-empty-function': 'off', 26 | 'vue/custom-event-name-casing': 'off', 27 | 'no-use-before-define': 'off', 28 | '@typescript-eslint/no-use-before-define': 'off', 29 | '@typescript-eslint/ban-ts-comment': 'off', 30 | '@typescript-eslint/ban-types': 'off', 31 | '@typescript-eslint/no-non-null-assertion': 'off', 32 | '@typescript-eslint/explicit-module-boundary-types': 'off', 33 | '@typescript-eslint/no-unused-vars': [ 34 | 'error', 35 | { 36 | argsIgnorePattern: '^h$', 37 | varsIgnorePattern: '^h$' 38 | } 39 | ], 40 | 'no-unused-vars': [ 41 | 'error', 42 | { 43 | argsIgnorePattern: '^h$', 44 | varsIgnorePattern: '^h$' 45 | } 46 | ], 47 | 'space-before-function-paren': 'off', 48 | quotes: ['error', 'single'], 49 | 'comma-dangle': ['error', 'never'] 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: 'vue-eslint-parser', 3 | 4 | parserOptions: { 5 | parser: '@typescript-eslint/parser', 6 | ecmaVersion: 2020, 7 | sourceType: 'module', 8 | ecmaFeatures: { 9 | jsx: true 10 | } 11 | }, 12 | 13 | extends: [ 14 | 'plugin:vue/vue3-recommended', 15 | 'plugin:@typescript-eslint/recommended', 16 | 'prettier', 17 | 'plugin:prettier/recommended' 18 | ], 19 | 20 | rules: { 21 | '@typescript-eslint/ban-ts-ignore': 'off', 22 | '@typescript-eslint/explicit-function-return-type': 'off', 23 | '@typescript-eslint/no-explicit-any': 'off', 24 | '@typescript-eslint/no-var-requires': 'off', 25 | '@typescript-eslint/no-empty-function': 'off', 26 | 'vue/custom-event-name-casing': 'off', 27 | 'no-use-before-define': 'off', 28 | '@typescript-eslint/no-use-before-define': 'off', 29 | '@typescript-eslint/ban-ts-comment': 'off', 30 | '@typescript-eslint/ban-types': 'off', 31 | '@typescript-eslint/no-non-null-assertion': 'off', 32 | '@typescript-eslint/explicit-module-boundary-types': 'off', 33 | '@typescript-eslint/no-unused-vars': [ 34 | 'error', 35 | { 36 | argsIgnorePattern: '^h$', 37 | varsIgnorePattern: '^h$' 38 | } 39 | ], 40 | 'no-unused-vars': [ 41 | 'error', 42 | { 43 | argsIgnorePattern: '^h$', 44 | varsIgnorePattern: '^h$' 45 | } 46 | ], 47 | 'space-before-function-paren': 'off', 48 | quotes: ['error', 'single'], 49 | 'comma-dangle': ['error', 'never'] 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createRouter as createVueRouter, 3 | createMemoryHistory, 4 | createWebHistory, 5 | Router 6 | } from 'vue-router'; 7 | 8 | export const createRouter = (type: 'client' | 'server'): Router => 9 | createVueRouter({ 10 | history: type === 'client' ? createWebHistory() : createMemoryHistory(), 11 | 12 | routes: [ 13 | { 14 | path: '/', 15 | name: 'index', 16 | meta: { 17 | title: '首页', 18 | keepAlive: true, 19 | requireAuth: true 20 | }, 21 | component: () => import('@/pages/index.vue') 22 | }, 23 | { 24 | path: '/login', 25 | name: 'login', 26 | meta: { 27 | title: '登录', 28 | keepAlive: true, 29 | requireAuth: false 30 | }, 31 | component: () => import('@/pages/login.vue') 32 | }, 33 | { 34 | path: '/user', 35 | name: 'user', 36 | meta: { 37 | title: '用户中心', 38 | keepAlive: true, 39 | requireAuth: true 40 | }, 41 | component: () => import('@/pages/user.vue') 42 | }, 43 | { 44 | path: '/vueuse', 45 | name: 'vueuse', 46 | meta: { 47 | title: 'vueuse', 48 | keepAlive: true, 49 | requireAuth: true 50 | }, 51 | component: () => import('@/pages/vueUse.vue') 52 | } 53 | ] 54 | }); 55 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/layout/Sidebar.vue: -------------------------------------------------------------------------------- 1 | 22 | 35 | 36 | 50 | -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-vue3-ts-pinia", 3 | "private": true, 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vue-tsc --noEmit && vite build", 8 | "preview": "vite preview", 9 | "eslint:comment": "使用 ESLint 检查并自动修复 src 目录下所有扩展名为 .js 和 .vue 的文件", 10 | "eslint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src", 11 | "prettier:comment": "自动格式化当前目录下的所有文件", 12 | "prettier": "prettier . --write", 13 | "commit:comment": "引导设置规范化的提交信息", 14 | "commit": "git-cz" 15 | }, 16 | "config": { 17 | "commitizen": { 18 | "path": "./node_modules/cz-customizable" 19 | } 20 | }, 21 | "lint-staged": { 22 | "*.{js,ts,vue}": [ 23 | "pnpm run eslint", 24 | "pnpm run prettier" 25 | ] 26 | }, 27 | "dependencies": { 28 | "@vueuse/core": "^8.2.0", 29 | "axios": "^0.26.1", 30 | "pinia": "^2.0.12", 31 | "vue": "^3.2.25", 32 | "vue-router": "^4.0.14" 33 | }, 34 | "devDependencies": { 35 | "@commitlint/cli": "^16.2.3", 36 | "@commitlint/config-conventional": "^16.2.1", 37 | "@types/node": "^17.0.23", 38 | "@typescript-eslint/eslint-plugin": "^5.16.0", 39 | "@typescript-eslint/parser": "^5.16.0", 40 | "@vitejs/plugin-vue": "^2.2.0", 41 | "commitizen": "^4.2.4", 42 | "commitlint-config-cz": "^0.13.3", 43 | "cz-conventional-changelog": "^3.3.0", 44 | "cz-customizable": "^6.3.0", 45 | "eslint": "^8.12.0", 46 | "eslint-config-prettier": "^8.5.0", 47 | "eslint-plugin-prettier": "^4.0.0", 48 | "eslint-plugin-vue": "^8.5.0", 49 | "husky": "^7.0.4", 50 | "lint-staged": "^12.3.7", 51 | "prettier": "^2.6.1", 52 | "typescript": "^4.5.4", 53 | "vite": "^2.8.0", 54 | "vue-tsc": "^0.29.8" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-ssr-vue3-koa2", 3 | "private": true, 4 | "version": "0.0.0", 5 | "scripts": { 6 | "dev": "node server-dev.js", 7 | "serve": "node server-prod.js", 8 | "build": "pnpm build:client && pnpm build:server", 9 | "build:client": "vite build --ssrManifest --outDir dist/client", 10 | "build:server": "vite build --ssr src/entry-server --outDir dist/server", 11 | "preview": "vite preview", 12 | "eslint:comment": "使用 ESLint 检查并自动修复 src 目录下所有扩展名为 .js 和 .vue 的文件", 13 | "eslint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src", 14 | "prettier:comment": "自动格式化当前目录下的所有文件", 15 | "prettier": "prettier --write", 16 | "commit:comment": "引导设置规范化的提交信息", 17 | "commit": "git-cz" 18 | }, 19 | "config": { 20 | "commitizen": { 21 | "path": "node_modules/cz-customizable" 22 | } 23 | }, 24 | "dependencies": { 25 | "@koa/router": "^10.1.1", 26 | "@vue/server-renderer": "^3.2.31", 27 | "@vueuse/core": "^8.2.5", 28 | "koa": "^2.13.4", 29 | "koa-connect": "^2.1.0", 30 | "koa-send": "^5.0.1", 31 | "pinia": "^2.0.13", 32 | "vue": "^3.2.25", 33 | "vue-router": "^4.0.14" 34 | }, 35 | "devDependencies": { 36 | "@commitlint/cli": "^16.2.3", 37 | "@commitlint/config-conventional": "^16.2.1", 38 | "@types/koa": "^2.13.4", 39 | "@typescript-eslint/eslint-plugin": "^5.18.0", 40 | "@typescript-eslint/parser": "^5.18.0", 41 | "@vitejs/plugin-vue": "^2.3.0", 42 | "commitizen": "^4.2.4", 43 | "commitlint-config-cz": "^0.13.3", 44 | "cz-conventional-changelog": "^3.3.0", 45 | "cz-customizable": "^6.3.0", 46 | "eslint": "^8.12.0", 47 | "eslint-config-prettier": "^8.5.0", 48 | "eslint-plugin-prettier": "^4.0.0", 49 | "eslint-plugin-vue": "^8.5.0", 50 | "husky": "^7.0.4", 51 | "lint-staged": "^12.3.7", 52 | "prettier": "^2.6.2", 53 | "typescript": "^4.5.4", 54 | "vite": "^2.9.0", 55 | "vue-tsc": "^0.29.8" 56 | } 57 | } -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/src/entry-server.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from './main'; 2 | import { renderToString } from '@vue/server-renderer'; 3 | import type { ParameterizedContext } from 'koa'; 4 | import { createRouter } from './router'; 5 | import createStore from '@/store'; 6 | 7 | export const render = async ( 8 | ctx: ParameterizedContext, 9 | manifest: Record 10 | ): Promise<[string, string, string]> => { 11 | const { app } = createApp(); 12 | 13 | // 路由注册 14 | const router = createRouter('server'); 15 | app.use(router); 16 | await router.push(ctx.path); 17 | await router.isReady(); 18 | 19 | // pinia 20 | const pinia = createStore(); 21 | app.use(pinia); 22 | const state = JSON.stringify(pinia.state.value); 23 | 24 | const renderCtx: { modules?: string[] } = {}; 25 | 26 | const renderedHtml = await renderToString(app, renderCtx); 27 | 28 | const preloadLinks = renderPreloadLinks(renderCtx.modules, manifest); 29 | 30 | return [renderedHtml, state, preloadLinks]; 31 | }; 32 | 33 | /** 34 | * 解析需要预加载的链接 35 | * @param modules 36 | * @param manifest 37 | * @returns 38 | */ 39 | function renderPreloadLinks( 40 | modules: undefined | string[], 41 | manifest: Record 42 | ): string { 43 | let links = ''; 44 | const seen = new Set(); 45 | if (modules === undefined) throw new Error(); 46 | modules.forEach((id) => { 47 | const files = manifest[id]; 48 | if (files) { 49 | files.forEach((file) => { 50 | if (!seen.has(file)) { 51 | seen.add(file); 52 | links += renderPreloadLink(file); 53 | } 54 | }); 55 | } 56 | }); 57 | return links; 58 | } 59 | 60 | /** 61 | * 预加载的对应的地址 62 | * 下面的方法只针对了 js 和 css,如果需要处理其它文件,自行添加即可 63 | * @param file 64 | * @returns 65 | */ 66 | function renderPreloadLink(file: string): string { 67 | if (file.endsWith('.js')) { 68 | return ``; 69 | } else if (file.endsWith('.css')) { 70 | return ``; 71 | } else { 72 | return ''; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /vite-plugin-template/src/index.ts: -------------------------------------------------------------------------------- 1 | import type { PluginOption } from 'vite'; 2 | 3 | export default function vitePluginTemplate(): PluginOption { 4 | return { 5 | // 插件名称 6 | name: 'vite-plugin-template', 7 | 8 | // pre 会较于 post 先执行 9 | enforce: 'pre', // post 10 | 11 | // 指明它们仅在 'build' 或 'serve' 模式时调用 12 | apply: 'build', // apply 亦可以是一个函数 13 | 14 | // 1. vite 独有的钩子:可以在 vite 被解析之前修改 vite 的相关配置。钩子接收原始用户配置 config 和一个描述配置环境的变量env 15 | config(config, { command }) {}, 16 | 17 | // 2. vite 独有的钩子:在解析 vite 配置后调用。使用这个钩子读取和存储最终解析的配置。当插件需要根据运行的命令做一些不同的事情时,它很有用。 18 | configResolved(resolvedConfig) {}, 19 | 20 | // 4. vite 独有的钩子:主要用来配置开发服务器,为 dev-server (connect 应用程序) 添加自定义的中间件 21 | configureServer(server) {}, 22 | 23 | // 18的前面. vite 独有的钩子:转换 index.html 的专用钩子。钩子接收当前的 HTML 字符串和转换上下文 24 | transformIndexHtml(html) {}, 25 | 26 | // vite 独有的钩子: 执行自定义HMR更新,可以通过ws往客户端发送自定义的事件 27 | handleHotUpdate({ file, server }) {}, 28 | 29 | // 3. 构建阶段的通用钩子:在服务器启动时被调用:获取、操纵Rollup选项 30 | options(options) {}, 31 | 32 | // 5. 构建阶段的通用钩子:在服务器启动时被调用:每次开始构建时调用 33 | buildStart(options) {}, 34 | 35 | // 构建阶段的通用钩子:在每个传入模块请求时被调用:创建自定义确认函数,可以用来定位第三方依赖 36 | resolveId(source, importer, options) {}, 37 | 38 | // 构建阶段的通用钩子:在每个传入模块请求时被调用:可以自定义加载器,可用来返回自定义的内容 39 | load(id) {}, 40 | 41 | // 构建阶段的通用钩子:在每个传入模块请求时被调用:在每个传入模块请求时被调用,主要是用来转换单个模块 42 | transform(code, id) {}, 43 | 44 | // 构建阶段的通用钩子:在构建结束后被调用,此处构建只是代表所有模块转义完成 45 | buildEnd() {}, 46 | 47 | // 输出阶段钩子通用钩子:接受输出参数 48 | outputOptions(options) {}, 49 | 50 | // 输出阶段钩子通用钩子:每次bundle.generate 和 bundle.write调用时都会被触发。 51 | renderStart(outputOptions, inputOptions) {}, 52 | 53 | // 输出阶段钩子通用钩子:用来给chunk增加hash 54 | augmentChunkHash(chunkInfo) {}, 55 | 56 | // 输出阶段钩子通用钩子:转译单个的chunk时触发。rollup输出每一个chunk文件的时候都会调用。 57 | renderChunk(code, chunk, options) { 58 | return null; 59 | }, 60 | 61 | // 输出阶段钩子通用钩子:在调用 bundle.write 之前立即触发这个hook 62 | generateBundle(options, bundle, isWrite) {}, 63 | 64 | // 输出阶段钩子通用钩子:在调用 bundle.write后,所有的chunk都写入文件后,最后会调用一次 writeBundle 65 | writeBundle(options, bundle) {}, 66 | 67 | // 通用钩子:在服务器关闭时被调用 68 | closeBundle() {}, 69 | }; 70 | } 71 | -------------------------------------------------------------------------------- /vite-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /vite-plugin-template/examples/vite-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/getDevice/index.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, describe, it } from 'vitest'; 2 | import { getDevice } from '.'; 3 | 4 | describe('device test', () => { 5 | it('The device should return {}', () => { 6 | const browser = getDevice(); 7 | expect(browser).toEqual({ 8 | model: '', 9 | vendor: '', 10 | }); 11 | }); 12 | 13 | it('The device should return mobile/Samsung', () => { 14 | const uaStr = 15 | 'Mozilla/5.0 (Linux; U; Android 2.3.5; de-de; SAMSUNG GT-S5830/S5830BUKS2 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'; 16 | const device = getDevice(uaStr); 17 | expect(device).toEqual({ 18 | model: 'mobile', 19 | vendor: 'Samsung', 20 | }); 21 | }); 22 | 23 | it('The device should return mobile/Apple', () => { 24 | const uaStr = 25 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'; 26 | const device = getDevice(uaStr); 27 | expect(device).toEqual({ 28 | model: 'mobile', 29 | vendor: 'Apple', 30 | }); 31 | }); 32 | 33 | it('The device should return mobile/Apple', () => { 34 | const uaStr = 35 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1'; 36 | const device = getDevice(uaStr); 37 | expect(device).toEqual({ 38 | model: 'mobile', 39 | vendor: 'Apple', 40 | }); 41 | }); 42 | 43 | it('The device should return mobile/Huawei', () => { 44 | const uaStr = 45 | 'Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; KNT-AL20 Build/HUAWEIKNT-AL20) AppleWebKit/537.36 (KHTML, like Gecko) MQQBrowser/7.3 Chrome/37.0.0.0 Mobile Safari/537.36'; 46 | const device = getDevice(uaStr); 47 | expect(device).toEqual({ 48 | model: 'mobile', 49 | vendor: 'Huawei', 50 | }); 51 | }); 52 | 53 | it('The device should return mobile/other', () => { 54 | const uaStr = 55 | 'Mozilla/5.0 (Linux; U; Android 2.3.5; en-gb; HTC Desire HD A9191 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'; 56 | const device = getDevice(uaStr); 57 | expect(device).toEqual({ 58 | model: 'mobile', 59 | vendor: 'other', 60 | }); 61 | }); 62 | 63 | it('The device should return pc/other', () => { 64 | const uaStr = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; de-CH) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.2'; 65 | const device = getDevice(uaStr); 66 | expect(device).toEqual({ 67 | model: 'pc', 68 | vendor: 'other', 69 | }); 70 | }); 71 | }); 72 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/getDevice/index.ts: -------------------------------------------------------------------------------- 1 | import { isString } from '@vmejs/shared'; 2 | 3 | export const DEVICES = [ 4 | { 5 | regs: [ 6 | /\b(sch-i[89]0\d|shw-m380s|sm-[pt]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i, 7 | /\b((?:s[cgp]h|gt|sm)-\w+|galaxy nexus)/i, 8 | /samsung[- ]([-\w]+)/i, 9 | /sec-(sgh\w+)/i, 10 | ], 11 | vendor: 'Samsung', 12 | }, 13 | { 14 | regs: [ 15 | /\((ip(?:hone|od)[\w ]*);/i, 16 | /\((ipad);[-\w\),; ]+apple/i, 17 | /applecoremedia\/[\w\.]+ \((ipad)/i, 18 | /\b(ipad)\d\d?,\d\d?[;\]].+ios/i, 19 | ], 20 | vendor: 'Apple', 21 | }, 22 | { 23 | regs: [/(pixel c)\b/i, /droid.+; (pixel[\daxl ]{0,6})(?: bui|\))/i], 24 | vendor: 'Google', 25 | }, 26 | { 27 | regs: [ 28 | /\b((?:ag[rs][23]?|bah2?|sht?|btv)-a?[lw]\d{2})\b(?!.+d\/s)/i, 29 | /(?:huawei|honor)([-\w ]+)[;\)]/i, 30 | /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][012359c][adn]?)\b(?!.+d\/s)/i, 31 | ], 32 | vendor: 'Huawei', 33 | }, 34 | { 35 | regs: [ 36 | /\b(poco[\w ]+)(?: bui|\))/i, // Xiaomi POCO 37 | /\b; (\w+) build\/hm\1/i, // Xiaomi Hongmi 'numeric' models 38 | /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i, // Xiaomi Hongmi 39 | /\b(redmi[\-_ ]?(?:note|k)?[\w_ ]+)(?: bui|\))/i, // Xiaomi Redmi 40 | /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note lte|max|cc)?[_ ]?(?:\d?\w?)[_ ]?(?:plus|se|lite)?)(?: bui|\))/i, // Xiaomi Mi 41 | /\b(mi[-_ ]?(?:pad)(?:[\w_ ]+))(?: bui|\))/i, // Mi Pad tablets 42 | ], 43 | vendor: 'Xiaomi', 44 | }, 45 | { 46 | regs: [/; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i], 47 | vendor: 'OPPO', 48 | }, 49 | { 50 | regs: [/vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i], 51 | vendor: 'Vivo', 52 | }, 53 | { 54 | regs: [/(Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i], 55 | vendor: 'other', 56 | }, 57 | ]; 58 | 59 | /** 60 | * 获取设备类型与供应商 61 | * @param ua window.navigator.userAgent 62 | * @returns { model: '', vendor: '' } 63 | */ 64 | export const getDevice = (ua?: string) => { 65 | const device = { 66 | model: '', 67 | vendor: '', 68 | }; 69 | 70 | if (!isString(ua)) { 71 | // node runtimes env 72 | if (global) return device; 73 | 74 | ua = window.navigator.userAgent; 75 | } 76 | 77 | device.model = 'pc'; 78 | device.vendor = 'other'; 79 | 80 | for (let i = 0; i <= DEVICES.length; i++) { 81 | if (!DEVICES[i]) break; 82 | 83 | const { regs, vendor } = DEVICES[i]; 84 | const findVal = regs.find((item) => item.exec(ua as string)); 85 | 86 | if (findVal) { 87 | device.model = 'mobile'; 88 | device.vendor = vendor; 89 | break; 90 | } 91 | } 92 | 93 | return device; 94 | }; 95 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/layout/AppLayout.vue: -------------------------------------------------------------------------------- 1 | 24 | 53 | 95 | -------------------------------------------------------------------------------- /vite-vue3-admin/src/views/login/login.vue: -------------------------------------------------------------------------------- 1 | 35 | 64 | 90 | -------------------------------------------------------------------------------- /pnpm-tool-template/packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs" /* Specify what module code is generated. */, 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */, 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, 77 | 78 | /* Type Checking */ 79 | "strict": true /* Enable all strict type-checking options. */, 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /koa2-ssr-vite-vue3-ts-pinia/README.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 大家好,我是 [易](https://juejin.cn/user/2305054774145918/posts),在上一篇文章中,我们有讲到[《如何使用 vite+vue3+ts+pinia+vueuse 打造前端企业级项目》](https://juejin.cn/post/7079785777692934174),能看的出来很多同学喜欢,今天给大家带来爆肝许久的 `如何使用 vite 打造前端 SSR 企业级项目`,希望大家能喜欢! 3 | 4 | 如果大家对 Vite 感兴趣可以去看看专栏: [《Vite 从入门到精通》](https://juejin.cn/column/7074954144817086472) 5 | 6 | 7 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! 8 | 9 | # 了解 SSR 10 | ## 什么是 SSR 11 | `服务器端渲染`(Server-Side Rendering)是指由服务端完成页面的 HTML 结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。 12 | 13 | 简单理解就是html是由服务端写出,可以动态改变页面内容,即所谓的动态页面。早年的 [php](https://baike.baidu.com/item/php/9337)、[asp](https://baike.baidu.com/item/asp/128906) 、[jsp](https://baike.baidu.com/item/jsp/141543) 这些 Server page 都是 SSR 的。 14 | 15 | ## 为什么使用 SSR 16 | - 网页内容在服务器端渲染完成,一次性传输到浏览器,所以 `首屏加载速度非常快`; 17 | - `有利于SEO`,因为服务器返回的是一个完整的 html,在浏览器可以看到完整的 dom,对于爬虫、百度搜索等引擎就比较友好; 18 | 19 | # 快速查看 20 | [github 仓库地址](https://github.com/jeddygong/vite-templates/tree/master/koa2-ssr-vite-vue3-ts-pinia) 21 | 22 | **长话短说,直接开干 ~** 23 | 24 | > `建议包管理器使用优先级:pnpm > yarn > npm > cnpm` 25 | 26 | 27 | # 一、初始化项目 28 | 29 | ```shell 30 | pnpm create vite koa2-ssr-vue3-ts-pinia -- --template vue-ts 31 | ``` 32 | 33 | ## **集成基本配置** 34 | 35 | 由于本文的重点在于 `SSR 配置`,为了优化读者的观感体验,所以项目的`基本配置`就不做详细介绍,在我上一篇文章[《手把手教你用 vite+vue3+ts+pinia+vueuse 打造企业级前端项目》](https://juejin.cn/post/7079785777692934174)中已详细介绍,大家可以自行查阅 36 | 37 | 38 | 39 | 1. 修改 `tsconfig.json` :[查看代码](https://github.com/jeddygong/vite-templates/blob/master/koa2-ssr-vite-vue3-ts-pinia/tsconfig.json) 40 | 2. 修改 `vite.config.ts`:[查看代码](https://github.com/jeddygong/vite-templates/blob/master/koa2-ssr-vite-vue3-ts-pinia/vite.config.ts) 41 | 3. 集成 `eslint` 和 `prettier` 统一代码质量风格的:[查看教程](https://juejin.cn/post/7079785777692934174#heading-8) 42 | 4. 集成 `commitizen` 和 `husky` 规范 git 提交:[查看教程](https://juejin.cn/post/7079785777692934174#heading-28) 43 | 44 | 到这里我们项目的基本框架都搭建完成啦~ 45 | 46 | # 二、修改客户端入口 47 | 48 | 1. 修改 `~/src/main.ts` 49 | 50 | ```ts 51 | import { createSSRApp } from "vue"; 52 | import App from "./App.vue"; 53 | 54 | // 为了保证数据的互不干扰,每次请求需要导出一个新的实例 55 | export const createApp = () => { 56 | const app = createSSRApp(App); 57 | return { app }; 58 | } 59 | ``` 60 | 61 | 2. 新建 `~/src/entry-client.ts` 62 | 63 | ```ts 64 | import { createApp } from "./main" 65 | 66 | const { app } = createApp(); 67 | 68 | app.mount("#app"); 69 | ``` 70 | 71 | 3. 修改 `~/index.html` 的入口 72 | 73 | ```html 74 | 75 | 76 | 77 | ... 78 | 79 | 80 | 81 | ... 82 | 83 | 84 | ``` 85 | 86 | 到这里你运行 `pnpm run dev` ,发现页面中还是可以正常显示,因为到目前只是做了一个文件的拆分,以及更换了 `createSSRApp` 方法; 87 | 88 | # 三、创建开发服务器 89 | ## 使用 Koa2 90 | 91 | 1. 安装 `koa2` 92 | 93 | ```shell 94 | pnpm i koa --save && pnpm i @types/koa --save-dev 95 | ``` 96 | 97 | 2. 安装中间件 `koa-connect` 98 | 99 | ```shell 100 | pnpm i koa-connect --save 101 | ``` 102 | 103 | 3. 使用:新建 `~/server.js` 104 | 105 | > 备注:因为该文件为 node 运行入口,所以用 js 即可,如果用 ts 文件,需单独使用 ts-node 等去运行,导致程序变复杂 106 | 107 | ```js 108 | const Koa = require('koa'); 109 | 110 | (async () => { 111 | const app = new Koa(); 112 | 113 | app.use(async (ctx) => { 114 | ctx.body = ` 115 | 116 | koa2 + vite + ts + vue3 + vue-router 117 | 118 |

使用 koa2 + vite + ts + vue3 + vue-router 集成前端 SSR 企业级项目

119 | 120 | `; 121 | }); 122 | 123 | app.listen(9000, () => { 124 | console.log('server is listening in 9000'); 125 | }); 126 | })(); 127 | ``` 128 | 129 | 4. 运行 `node server.js` 130 | 5. 结果: 131 | ![Untitled.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cae49df3d82444dc8a95f8f40f29f1ad~tplv-k3u1fbpfcp-watermark.image?) 132 | 133 | 134 | ## 渲染替换成项目根目录下的 `index.html` 135 | 136 | 1. 修改 `server.js` 中的 `ctx.body` 返回的是 `index.html` 137 | 138 | ```js 139 |  const fs = require('fs'); 140 |  const path = require('path'); 141 |  ​ 142 |  const Koa = require('koa'); 143 |  ​ 144 |  (async () => { 145 |      const app = new Koa(); 146 |  ​ 147 |      // 获取 index.html 148 |      const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8'); 149 |  ​ 150 |      app.use(async (ctx) => { 151 |          ctx.body = template; 152 |     }); 153 |  ​ 154 |      app.listen(9000, () => { 155 |          console.log('server is listening in 9000'); 156 |     }); 157 |  })(); 158 | ``` 159 | 2. 运行 `node server.js`后, 我们就会看到返回的是空白内容的 `index.html` 了,但是我们需要返回的是 `vue 模板` ,那么我们只需要做个 `正则的替换` 160 | 3. 给 `index.html` 添加 `` 标记 161 | 162 | ```html 163 |   164 |   165 |     166 |       167 |       168 |       169 |      koa2 + vite + ts + vue3 170 |     171 |     172 |      
173 |       174 |     175 |   176 | ``` 177 | 4. 修改 `server.js` 中的 `ctx.body` 178 | ```js 179 | // other code ... 180 | 181 | (async () => { 182 | const app = new Koa(); 183 | 184 | // 获取index.html 185 | const template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8'); 186 | 187 | app.use(async (ctx) => { 188 | let vueTemplate = '

现在假装这是一个vue模板

'; 189 | 190 | // 替换 index.html 中的 标记 191 | let html = template.replace('', vueTemplate); 192 | 193 | ctx.body = html; 194 | }); 195 | 196 | app.listen(9000, () => { 197 | console.log('server is listening in 9000'); 198 | }); 199 | })(); 200 | ``` 201 | 5. 运行 `node server.js`后,我们就会看到返回的 `变量 vueTemplate` 内容 202 | 203 | 那么到现在服务已正常启动了,但是我们试想一下,我们页面模板使用的是 vue,并且 vue 返回的是一个 `vue 实例模板`,所以我就要把这个 `vue 实例模板` 转换成 `可渲染的 html`,那么 `@vue/server-renderer` 就应运而生了 204 | 205 | # 四、新增服务端入口 206 | 因为 vue 返回的是 `vue 实例模板` 而不是 `可渲染的 html` ,所以我们需要使用 `@vue/server-renderer` 进行转换 207 | 208 | 1. 安装 `@vue/server-renderer` 209 | ```shell 210 | pnpm i @vue/server-renderer --save 211 | ``` 212 | 213 | 2. 新建 `~/src/entry-server.ts` 214 | 215 | ```ts 216 | import { createApp } from './main'; 217 | import { renderToString } from '@vue/server-renderer'; 218 | 219 | export const render = async () => { 220 | const { app } = createApp(); 221 | 222 | // 注入vue ssr中的上下文对象 223 | const renderCtx: {modules?: string[]} = {} 224 | 225 | let renderedHtml = await renderToString(app, renderCtx) 226 | 227 | return { renderedHtml }; 228 | } 229 | ``` 230 | 231 | 那么如何去使用 `entry-server.ts` 呢,到这里就需要 `vite` 了 232 | 233 | # 五、注入 `vite` 234 | 235 | 1. 修改 `~/server.js` 236 | 237 | ```js 238 | const fs = require('fs') 239 | const path = require('path') 240 | 241 | const Koa = require('koa') 242 | const koaConnect = require('koa-connect') 243 | 244 | const vite = require('vite') 245 | 246 | ;(async () => { 247 | const app = new Koa(); 248 | 249 | // 创建 vite 服务 250 | const viteServer = await vite.createServer({ 251 | root: process.cwd(), 252 | logLevel: 'error', 253 | server: { 254 | middlewareMode: true, 255 | }, 256 | }) 257 | 258 | // 注册 vite 的 Connect 实例作为中间件(注意:vite.middlewares 是一个 Connect 实例) 259 | app.use(koaConnect(viteServer.middlewares)) 260 | 261 | app.use(async ctx => { 262 | try { 263 | // 1. 获取index.html 264 | let template = fs.readFileSync(path.resolve(__dirname, 'index.html'), 'utf-8'); 265 | 266 | // 2. 应用 Vite HTML 转换。这将会注入 Vite HMR 客户端, 267 | template = await viteServer.transformIndexHtml(ctx.path, template) 268 | 269 | // 3. 加载服务器入口, vite.ssrLoadModule 将自动转换 270 | const { render } = await viteServer.ssrLoadModule('/src/entry-server.ts') 271 | 272 | // 4. 渲染应用的 HTML 273 | const { renderedHtml } = await render(ctx, {}) 274 | 275 | const html = template.replace('', renderedHtml) 276 | 277 | ctx.type = 'text/html' 278 | ctx.body = html 279 | } catch (e) { 280 | viteServer && viteServer.ssrFixStacktrace(e) 281 | console.log(e.stack) 282 | ctx.throw(500, e.stack) 283 | } 284 | }) 285 | 286 | app.listen(9000, () => { 287 | console.log('server is listening in 9000'); 288 | }); 289 | 290 | })() 291 | ``` 292 | 293 | 2. 运行 `node server.js` 就可以看到返回的 App.vue 模板中的内容了,如下图 294 | 295 | ![Untitled 1.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/60fba463b7cf4dcc807cecd4cc1bd44b~tplv-k3u1fbpfcp-watermark.image?) 296 | 297 | 3. 并且我们 `右键查看显示网页源代码`,也会看到渲染的正常 html 298 | 299 | ```html 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | koa2 + vite + ts + vue3 309 | 310 | 311 |
Vue logo

Hello Vue 3 + TypeScript + Vite

Recommended IDE setup: VSCode + Volar

See README.md for more information.

Vite Docs | Vue 3 Docs

Edit components/HelloWorld.vue to test hot module replacement.

312 | 313 | 314 | 315 | ``` 316 | 317 | 到这里我们就已经在 `开发环境` 已经正常的渲染了,但我们想一下,在 `生产环境` 我们应该怎么做呢,因为咱们不可能直接在 `生产环境` 运行使用 `vite` 吧! 318 | 319 | 320 | 所以咱们接下来处理如何在 `生产环境` 运行吧 321 | 322 | 323 | # 六、添加开发环境 324 | 325 | 为了将 SSR 项目可以在生产环境运行,我们需要: 326 | 1. 正常构建生成一个 `客户端构建包`; 327 | 2. 再生成一个 SSR 构建,使其通过 `require()` 直接加载,这样便无需再使用 Vite 的 `ssrLoadModule`; 328 | 3. 修改 `package.json` 329 | ```json 330 | ... 331 | 332 | { 333 | "scripts": { 334 | // 开发环境 335 | "dev": "node server-dev.js", 336 | // 生产环境 337 | "server": "node server-prod.js", 338 | // 构建 339 | "build": "pnpm build:client && pnpm build:server", 340 | "build:client": "vite build --outDir dist/client", 341 | "build:server": "vite build --ssr src/entry-server.js --outDir dist/server", 342 | }, 343 | } 344 | 345 | ... 346 | 347 | ``` 348 | 4. 修改 `server.js` 为 `server-dev.js` 349 | 5. 运行 `pnpm run build` 构建包 350 | 6. 新增 `server-prod.js` 351 | > 注意:为了处理静态资源,需要在此新增 `koa-send` 中间件: `pnpm i koa-send --save` 352 | ```js 353 | const Koa = require('koa'); 354 | const sendFile = require('koa-send'); 355 | 356 | const path = require('path'); 357 | const fs = require('fs'); 358 | 359 | const resolve = (p) => path.resolve(__dirname, p); 360 | 361 | const clientRoot = resolve('dist/client'); 362 | const template = fs.readFileSync(resolve('dist/client/index.html'), 'utf-8'); 363 | const render = require('./dist/server/entry-server.js').render; 364 | const manifest = require('./dist/client/ssr-manifest.json'); 365 | 366 | (async () => { 367 | const app = new Koa(); 368 | 369 | app.use(async (ctx) => { 370 | 371 | // 请求的是静态资源 372 | if (ctx.path.startsWith('/assets')) { 373 | await sendFile(ctx, ctx.path, { root: clientRoot }); 374 | return; 375 | } 376 | 377 | const [ appHtml ] = await render(ctx, manifest); 378 | 379 | const html = template 380 | .replace('', appHtml); 381 | 382 | ctx.type = 'text/html'; 383 | ctx.body = html; 384 | }); 385 | 386 | app.listen(8080, () => console.log('started server on http://localhost:8080')); 387 | })(); 388 | ``` 389 | 到这里,我们在 `开发环境` 和 `生成环境` 已经都可以正常访问了,那么是不是就万事无忧了呢? 390 | 391 | 为了用户的更极致的用户体验,那么 `预加载` 就必须要安排了 392 | 393 | # 七、预加载 394 | 我们知道 `vue 组件`在 html 中渲染时都是动态去生成的对应的 `js` 和 `css` 等; 395 | 396 | 那么我们要是在用户获取 `服务端模板` (也就是执行 `vite build` 后生成的 `dist/client` 目录) 的时候,直接在 html 中把对应的 `js` 和 `css` 文件预渲染了,这就是 `静态站点生成(SSG)` 的形式。 397 | 398 | 闲话少说,明白道理了之后,直接开干 ~ 399 | 400 | 1. `生成预加载指令`:在 package.json 中的 `build:client` 添加 `--ssrManifest` 标志,运行后生成 `ssr-manifest.json` 401 | ```json 402 | ... 403 | 404 | { 405 | "scripts": { 406 | ... 407 | "build:client": "vite build --ssrManifest --outDir dist/client", 408 | ... 409 | }, 410 | } 411 | 412 | ... 413 | ``` 414 | 2. 在 `entry-sercer.ts` 中添加解析生成的 `ssr-manifest.json` 方法 415 | 416 | ```ts 417 | export const render = async ( 418 | ctx: ParameterizedContext, 419 | manifest: Record 420 | ): Promise<[string, string]> => { 421 | const { app } = createApp(); 422 | console.log(ctx, manifest, ''); 423 | 424 | const renderCtx: { modules?: string[] } = {}; 425 | 426 | const renderedHtml = await renderToString(app, renderCtx); 427 | 428 | const preloadLinks = renderPreloadLinks(renderCtx.modules, manifest); 429 | 430 | return [renderedHtml, preloadLinks]; 431 | }; 432 | 433 | /** 434 | * 解析需要预加载的链接 435 | * @param modules 436 | * @param manifest 437 | * @returns string 438 | */ 439 | function renderPreloadLinks( 440 | modules: undefined | string[], 441 | manifest: Record 442 | ): string { 443 | let links = ''; 444 | const seen = new Set(); 445 | if (modules === undefined) throw new Error(); 446 | modules.forEach((id) => { 447 | const files = manifest[id]; 448 | if (files) { 449 | files.forEach((file) => { 450 | if (!seen.has(file)) { 451 | seen.add(file); 452 | links += renderPreloadLink(file); 453 | } 454 | }); 455 | } 456 | }); 457 | return links; 458 | } 459 | 460 | /** 461 | * 预加载的对应的地址 462 | * 下面的方法只针对了 js 和 css,如果需要处理其它文件,自行添加即可 463 | * @param file 464 | * @returns string 465 | */ 466 | function renderPreloadLink(file: string): string { 467 | if (file.endsWith('.js')) { 468 | return ``; 469 | } else if (file.endsWith('.css')) { 470 | return ``; 471 | } else { 472 | return ''; 473 | } 474 | } 475 | ``` 476 | 3. 给 `index.html` 添加 `` 标记 477 | 4. 改造 `server-prod.js` 478 | ```js 479 | 480 | ... 481 | 482 | (async () => { 483 | const app = new Koa(); 484 | 485 | app.use(async (ctx) => { 486 | 487 | ... 488 | 489 | const [appHtml, preloadLinks] = await render(ctx, manifest); 490 | 491 | const html = template 492 | .replace('', preloadLinks) 493 | .replace('', appHtml); 494 | 495 | // do something 496 | }); 497 | 498 | app.listen(8080, () => console.log('started server on http://localhost:8080')); 499 | })(); 500 | ``` 501 | 5. 运行 `pnpm run build && pnpm run serve` 就可正常显示了 502 | 503 | 到这里基本的渲染就完成了,因为我们是需要在浏览器上渲染的,所以 `路由 vue-router` 就必不可少了 504 | 505 | # 八、集成 vue-router 506 | 1. 安装 vue-router 507 | ```shell 508 | pnpm i vue-router --save 509 | ``` 510 | 2. 新增对应的路由页面 `index.vue` 、 `login.vue` 、 `user.vue` 511 | 3. 新增 `src/router/index.ts` 512 | ```ts 513 | import { 514 | createRouter as createVueRouter, 515 | createMemoryHistory, 516 | createWebHistory, 517 | Router 518 | } from 'vue-router'; 519 | 520 | export const createRouter = (type: 'client' | 'server'): Router => 521 | createVueRouter({ 522 | history: type === 'client' ? createWebHistory() : createMemoryHistory(), 523 | 524 | routes: [ 525 | { 526 | path: '/', 527 | name: 'index', 528 | meta: { 529 | title: '首页', 530 | keepAlive: true, 531 | requireAuth: true 532 | }, 533 | component: () => import('@/pages/index.vue') 534 | }, 535 | { 536 | path: '/login', 537 | name: 'login', 538 | meta: { 539 | title: '登录', 540 | keepAlive: true, 541 | requireAuth: false 542 | }, 543 | component: () => import('@/pages/login.vue') 544 | }, 545 | { 546 | path: '/user', 547 | name: 'user', 548 | meta: { 549 | title: '用户中心', 550 | keepAlive: true, 551 | requireAuth: true 552 | }, 553 | component: () => import('@/pages/user.vue') 554 | } 555 | ] 556 | }); 557 | ``` 558 | 4. 修改入口文件 `src/enter-client.ts` 559 | ```ts 560 | import { createApp } from './main'; 561 | 562 | import { createRouter } from './router'; 563 | const router = createRouter('client'); 564 | 565 | const { app } = createApp(); 566 | 567 | app.use(router); 568 | 569 | router.isReady().then(() => { 570 | app.mount('#app', true); 571 | }); 572 | ``` 573 | 5. 修改入口文件 `src/enter-server.ts` 574 | ```ts 575 | ... 576 | import { createRouter } from './router' 577 | const router = createRouter('client'); 578 | 579 | export const render = async ( 580 | ctx: ParameterizedContext, 581 | manifest: Record 582 | ): Promise<[string, string]> => { 583 | const { app } = createApp(); 584 | 585 | // 路由注册 586 | const router = createRouter('server'); 587 | app.use(router); 588 | await router.push(ctx.path); 589 | await router.isReady(); 590 | 591 | ... 592 | }; 593 | 594 | ... 595 | ``` 596 | 6. 运行 `pnpm run build && pnpm run serve` 就可正常显示了 597 | 598 | # 九、集成 pinia 599 | 1. 安装 600 | ```shell 601 | pnpm i pinia --save 602 | ``` 603 | 2. 新建 `src/store/user.ts` 604 | ```ts 605 | import { defineStore } from 'pinia'; 606 | 607 | export default defineStore('user', { 608 | state: () => { 609 | return { 610 | name: '张三', 611 | age: 20 612 | }; 613 | }, 614 | actions: { 615 | updateName(name: string) { 616 | this.name = name; 617 | }, 618 | updateAge(age: number) { 619 | this.age = age; 620 | } 621 | } 622 | }); 623 | 624 | ``` 625 | 3. 新建 `src/store/index.ts` 626 | ```ts 627 | import { createPinia } from 'pinia'; 628 | import useUserStore from './user'; 629 | 630 | export default () => { 631 | const pinia = createPinia(); 632 | 633 | useUserStore(pinia); 634 | 635 | return pinia; 636 | }; 637 | 638 | ``` 639 | 4. 新建 `UsePinia.vue` 使用,并且在 `pages/index.vue` 中引入 640 | ```ts 641 | 648 | 649 | 667 | 668 | ``` 669 | 5. 注入 `pinia` :修改 `src/entry-client.ts` 670 | ```ts 671 | ... 672 | 673 | import createStore from '@/store'; 674 | const pinia = createStore(); 675 | 676 | const { app } = createApp(); 677 | 678 | app.use(router); 679 | app.use(pinia); 680 | 681 | // 初始化 pini 682 | // 注意:__INITIAL_STATE__需要在 src/types/shims-global.d.ts中定义 683 | if (window.__INITIAL_STATE__) { 684 | pinia.state.value = JSON.parse(window.__INITIAL_STATE__); 685 | } 686 | 687 | ... 688 | ``` 689 | 6. 修改 `src/entry-server.ts` 690 | ```ts 691 | ... 692 | 693 | import createStore from '@/store'; 694 | 695 | export const render = () => { 696 | ... 697 | // pinia 698 | const pinia = createStore(); 699 | app.use(pinia); 700 | const state = JSON.stringify(pinia.state.value); 701 | 702 | ... 703 | 704 | return [renderedHtml, state, preloadLinks]; 705 | 706 | } 707 | ... 708 | ``` 709 | 7. 修改 `server-dev.js` 和 `server-prod.js` 710 | ```js 711 | ... 712 | 713 | const [renderedHtml, state, preloadLinks] = await render(ctx, {}); 714 | 715 | const html = template 716 | .replace('', renderedHtml) 717 | .replace('', state); 718 | // server-prod.js 719 | .replace('', preloadLinks) 720 | 721 | ... 722 | ``` 723 | 8. 给 `index.html` 添加 `` 标记 724 | ```html 725 | 728 | ``` 729 | 9. 运行 `pnpm run dev` 就可正常显示了 730 | 731 | > 备注:`集成 pinia` 这块由于注入较为`复杂且方法不一`,暂时不做详细讲解,如果大家有需要,后面会出详细解析! 732 | 733 | # 十、其它 734 | * `vueuse` 的集成:可参考 [《手把手教你用 vite+vue3+ts+pinia+vueuse 打造大厂企业级前端项目》](https://juejin.cn/post/7079785777692934174#heading-17) 735 | * `CSS 集成`:[参考如上](https://juejin.cn/post/7079785777692934174#heading-20) 736 | * 可使用:`原生 css variable 新特性`、`scss` 或者 `less` 737 | * `CSS 的 UI 库`:[参考同上](https://juejin.cn/post/7079785777692934174#heading-27) 738 | * 需要注意的是 `按需引入` 739 | * 当然还有很多需要考量的,比如 `压测`, `并发` , `负载均衡` 等,但是这些不在文章主题范围内,这里就不做详细介绍,感兴趣的可以留言,后面有时间会新开对应的专栏 740 | * 其中 `负载均衡` 这块前端同学可使用 `pm2`, 或者直接丢给运维去搞个 `docker` 741 | 742 | # 项目模板地址 743 | [传送门](https://github.com/jeddygong/vite-templates/tree/master/koa2-ssr-vite-vue3-ts-pinia) 744 | 745 | # 最后 746 | > 友情提示:目前 Vite 的 SSR 支持还处于试验阶段,可能会遇到一些未知 bug ,所以在公司的生产环境请谨慎使用,个人项目中可以滥用哟 ~ 747 | 748 | 该系列会是一个持续更新系列,关于整个[《Vite 从入门到精通》专栏](https://juejin.cn/column/7074954144817086472),我主要会从如下图几个方面讲解,请大家拭目以待吧!!! 749 | 750 | ![Untitled.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/52ee2485e3484e8e8d995fbbb7e86835~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?) 751 | 752 | `靓仔靓女们`,都看到这里了,要不点个赞再走呗 🌹🌹🌹 -------------------------------------------------------------------------------- /vite-vue3-ts-pinia/README.md: -------------------------------------------------------------------------------- 1 | # Vite + Vue3 + Typescript + Pinia + Vueuse 2 | 3 | > ## 一个大厂企业级前端项目 4 | > 5 | > ## 如果觉得项目模板不错的话,欢迎 Star 支持就好,感谢大家! 6 | 7 | 8 | # 通过这篇文章你可以学到 9 | 10 | - 如何使用使用 Vite 搭建项目 11 | - 如何在 Vite 中集成 `typescript` 12 | - 如何在 Vite 中集成 `vue-router4` 和 `pinia` 13 | - 如何使用 vue3 的伴侣 `vueuse` 14 | - 如何在项目中集成 `eslint` 和 `prettier` 保证代码质量 15 | - 如何规范化 `git` 提交信息 16 | - 如何为团队开发`专属的项目模板` 17 | 18 | # 环境依赖版本 19 | - [node](https://github.com/nodejs/node):v14.15.4 20 | - [vite](https://github.com/vitejs/vite):^2.8.0 21 | - [vue](https://github.com/vuejs/vue):^3.2.25 22 | - [typescript](https://github.com/microsoft/TypeScript):^4.5.4 23 | - [pinia](https://github.com/vuejs/pinia):^2.0.12 24 | - [vue-router](https://github.com/vuejs/router):^4.0.14 25 | - [vueuse](https://github.com/vueuse/vueuse):^8.2.0 26 | - [eslint](https://github.com/eslint/eslint):^8.12.0 27 | - [prettier](https://github.com/prettier/prettier):^2.6.1 28 | - [commitizen](https://github.com/commitizen/cz-cli):^4.2.4 29 | - [husky](https://github.com/typicode/husky):^7.0.4 30 | 31 | **长话短说,直接开干 ~** 32 | 33 | # 1. 初始化项目 34 | 35 | ## 按步骤提示初始化: 36 | 37 | 1. 使用 vite-cli 命令 38 | 39 | ```bash 40 | # pnpm 41 | pnpm create vite 42 | 43 | # npm 44 | npm init vite@latest 45 | 46 | # yarn 47 | yarn create vite 48 | ``` 49 | 50 | 2. 输入项目名: 51 | 52 | ```bash 53 | ? Project name: vite-vue3-ts-pinia 54 | ``` 55 | 56 | 3. 选择一个框架(vue) 57 | 58 | ```bash 59 | ? Select a framework: » - Use arrow-keys. Return to submit. 60 |     vanilla // 原生js 61 |  >   vue     // 默认就是 vue3 62 |     react   // react 63 |     preact // 轻量化react框架 64 |     lit     // 轻量级web组件 65 |     svelte // svelte框架 66 | ``` 67 | 68 | 4. 使用 typescript 69 | 70 | ``` 71 | ? Select a variant: › - Use arrow-keys. Return to submit. 72 | vue 73 | ❯ vue-ts 74 | ``` 75 | 76 | 5. 启动项目 77 | 78 | ```bash 79 | cd vite-vue3-ts-pinia && pnpm install && pnpm run dev 80 | ``` 81 | 82 | ## 快速初始化(建议使用): 83 | 84 | ``` 85 | # pnpm 86 | pnpm create vite project-name -- --template vue-ts 87 | 88 | # npm 6.x 89 | npm init vite@latest project-name --template vue-ts 90 |   91 | # npm 7+, 需要额外的双横线: 92 | npm init vite@latest project-name -- --template vue-ts 93 |   94 | # yarn 95 | yarn create vite project-name --template vue-ts 96 | ``` 97 | 98 | ## 集成配置 99 | 1. 为保证 node 的使用 100 | ```bash 101 | pnpm i @types/node --save-dev 102 | ``` 103 | 2. 修改 `tsconfig.json` 104 | ```json 105 | { 106 | "compilerOptions": { 107 | "typeRoots": [ 108 | "node_modules/@types", // 默认值 109 | "src/types" 110 | ], 111 | "target": "esnext", 112 | "useDefineForClassFields": true, 113 | "module": "esnext", 114 | "moduleResolution": "node", 115 | "strict": true, 116 | "jsx": "preserve", 117 | "sourceMap": true, 118 | "resolveJsonModule": true, 119 | "esModuleInterop": true, 120 | "lib": ["esnext", "dom"], 121 | "baseUrl": "./", 122 | "paths":{ 123 | "@": ["src"], 124 | "@/*": ["src/*"], 125 | } 126 | }, 127 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 128 | } 129 | 130 | ``` 131 | 3. 修改 `vite.config.ts` 132 | ```typescript 133 | import { defineConfig } from 'vite'; 134 | import vue from '@vitejs/plugin-vue'; 135 | import * as path from 'path'; 136 | 137 | // https://vitejs.dev/config/ 138 | export default defineConfig({ 139 | resolve: { 140 | //设置别名 141 | alias: { 142 | '@': path.resolve(__dirname, 'src') 143 | } 144 | }, 145 | plugins: [vue()], 146 | server: { 147 | port: 8080, //启动端口 148 | hmr: { 149 | host: '127.0.0.1', 150 | port: 8080 151 | }, 152 | // 设置 https 代理 153 | proxy: { 154 | '/api': { 155 | target: 'your https address', 156 | changeOrigin: true, 157 | rewrite: (path: string) => path.replace(/^\/api/, '') 158 | } 159 | } 160 | } 161 | }); 162 | 163 | ``` 164 | 165 | # 2. 代码质量风格的统一 166 | 167 | ## 集成 `eslint` 168 | 1. 安装 169 | ```bash 170 | pnpm i eslint eslint-plugin-vue --save-dev 171 | ``` 172 | 由于 ESLint 默认使用 [Espree](https://github.com/eslint/espree) 进行语法解析,无法识别 TypeScript 的一些语法,故我们需要安装 [`@typescript-eslint/parser`](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser) 替代掉默认的解析器 173 | ```bash 174 | pnpm install @typescript-eslint/parser --save-dev 175 | ``` 176 | 177 | 安装对应的插件 [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin) 它作为 eslint 默认规则的补充,提供了一些额外的适用于 ts 语法的规则。 178 | ```bash 179 | pnpm install @typescript-eslint/eslint-plugin --save-dev 180 | ``` 181 | 182 | 2. 创建配置文件: `.eslintrc.js` 或 `.eslintrc.json` 183 | ```javascript 184 | module.exports = { 185 | parser: 'vue-eslint-parser', 186 | 187 | parserOptions: { 188 | parser: '@typescript-eslint/parser', 189 | ecmaVersion: 2020, 190 | sourceType: 'module', 191 | ecmaFeatures: { 192 | jsx: true 193 | } 194 | }, 195 | 196 | extends: [ 197 | 'plugin:vue/vue3-recommended', 198 | 'plugin:@typescript-eslint/recommended', 199 | ], 200 | 201 | rules: { 202 | // override/add rules settings here, such as: 203 | } 204 | }; 205 | 206 | ``` 207 | 3. 创建忽略文件:`.eslintignore` 208 | ``` 209 | node_modules/ 210 | dist/ 211 | index.html 212 | ``` 213 | 4. 命令行式运行:修改 `package.json` 214 | ```json 215 | { 216 | ... 217 | "scripts": { 218 | ... 219 | "eslint:comment": "使用 ESLint 检查并自动修复 src 目录下所有扩展名为 .js 和 .vue 的文件", 220 | "eslint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src", 221 | } 222 | ... 223 | } 224 | ``` 225 | 226 | 227 | ## 集成 `prettier` 228 | 1. 安装 229 | ```bash 230 | pnpm i prettier eslint-config-prettier eslint-plugin-prettier --save-dev 231 | ``` 232 | 233 | 2. 创建配置文件: `prettier.config.js` 或 `.prettierrc.js` 234 | ``` javascript 235 | module.exports = { 236 | // 一行最多 80 字符 237 | printWidth: 80, 238 | // 使用 4 个空格缩进 239 | tabWidth: 4, 240 | // 不使用 tab 缩进,而使用空格 241 | useTabs: false, 242 | // 行尾需要有分号 243 | semi: true, 244 | // 使用单引号代替双引号 245 | singleQuote: true, 246 | // 对象的 key 仅在必要时用引号 247 | quoteProps: 'as-needed', 248 | // jsx 不使用单引号,而使用双引号 249 | jsxSingleQuote: false, 250 | // 末尾使用逗号 251 | trailingComma: 'all', 252 | // 大括号内的首尾需要空格 { foo: bar } 253 | bracketSpacing: true, 254 | // jsx 标签的反尖括号需要换行 255 | jsxBracketSameLine: false, 256 | // 箭头函数,只有一个参数的时候,也需要括号 257 | arrowParens: 'always', 258 | // 每个文件格式化的范围是文件的全部内容 259 | rangeStart: 0, 260 | rangeEnd: Infinity, 261 | // 不需要写文件开头的 @prettier 262 | requirePragma: false, 263 | // 不需要自动在文件开头插入 @prettier 264 | insertPragma: false, 265 | // 使用默认的折行标准 266 | proseWrap: 'preserve', 267 | // 根据显示样式决定 html 要不要折行 268 | htmlWhitespaceSensitivity: 'css', 269 | // 换行符使用 lf 270 | endOfLine: 'auto' 271 | } 272 | 273 | ``` 274 | 3. 修改 `.eslintrc.js` 配置 275 | ```javascript 276 | module.exports = { 277 | ... 278 | 279 | extends: [ 280 | 'plugin:vue/vue3-recommended', 281 | 'plugin:@typescript-eslint/recommended', 282 | 'prettier', 283 | 'plugin:prettier/recommended' 284 | ], 285 | 286 | ... 287 | }; 288 | ``` 289 | 4. 命令行式运行:修改 `package.json` 290 | ```json 291 | { 292 | ... 293 | "scripts": { 294 | ... 295 | "prettier:comment": "自动格式化当前目录下的所有文件", 296 | "prettier": "prettier --write" 297 | } 298 | ... 299 | } 300 | ``` 301 | 302 | # 3. 集成 `pinia` 303 | `Pinia` 读音:['piːnə],是 Vue 官方团队推荐代替`Vuex`的一款轻量级状态管理库。 304 | 305 | **Pinia 有如下特点:** 306 | 307 | - 完整的 typescript 的支持; 308 | - 足够轻量,压缩后的体积只有1.6kb; 309 | - 去除 mutations,只有 state,getters,actions(这是我最喜欢的一个特点); 310 | - actions 支持同步和异步; 311 | - 没有模块嵌套,只有 store 的概念,store 之间可以自由使用,更好的代码分割; 312 | - 无需手动添加 store,store 一旦创建便会自动添加; 313 | 314 | ## 安装 315 | 316 | ``` 317 |  pnpm i pinia --save 318 | ``` 319 | 320 | ## 使用 321 | 322 | 1. 新建 src/store 目录并在其下面创建 index.ts,导出 store 323 | 324 | ``` typescript 325 |  import { createPinia } from 'pinia' 326 | 327 |  const store = createPinia() 328 | 329 |  export default store 330 | ``` 331 | 332 | 2. 在 main.ts 中引入并使用 333 | 334 | ```typescript 335 |  import { createApp } from 'vue' 336 |  import App from './App.vue' 337 |  import store from './store' 338 |  ​ 339 |  // 创建vue实例 340 |  const app = createApp(App) 341 |  ​ 342 |  // 挂载pinia 343 |  app.use(store) 344 |  ​ 345 |  // 挂载实例 346 |  app.mount('#app'); 347 | ``` 348 | 349 | 3. **定义State:** 在 src/store 下面创建一个 user.ts 350 | 351 | ```typescript 352 |  import { defineStore } from 'pinia' 353 | 354 |  export const useUserStore = defineStore({ 355 |    id: 'user', // id必填,且需要唯一 356 |    state: () => { 357 |      return { 358 |        name: '张三' 359 |     } 360 |   }, 361 |    actions: { 362 |      updateName(name) { 363 |        this.name = name 364 |     } 365 |   } 366 |  }) 367 | ``` 368 | 369 | 4. **获取State:** 在 src/components/usePinia.vue 中使用 370 | 371 | ```typescript 372 |   375 | 376 |   381 | ``` 382 | 383 | 5. **修改State:** 384 | 385 | ```typescript 386 |  // 1. 直接修改 state (不建议) 387 |  userStore.name = '李四' 388 | 389 |  // 2. 通过 actions 去修改 390 |   396 | ``` 397 | 398 | > 更详细上手指南:[链接](https://juejin.cn/post/7049196967770980389) 官方文档:[链接](https://pinia.vuejs.org/introduction.html) 399 | 400 | # 4. 集成 `vue-router4` 401 | 402 | ## 安装 403 | 404 | ```bash 405 |  pnpm i vue-router --save 406 | ``` 407 | 408 | ## 使用 409 | 410 | 1. 新建 src/router 目录并在其下面创建 index.ts,导出 router 411 | 412 | ```typescript 413 |  import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; 414 | 415 |  const routes: Array = [ 416 |   { 417 |      path: '/login', 418 |      name: 'Login', 419 |      meta: { 420 |          title: '登录', 421 |          keepAlive: true, 422 |          requireAuth: false 423 |     }, 424 |      component: () => import('@/pages/login.vue') 425 |   }, 426 |   { 427 |        path: '/', 428 |        name: 'Index', 429 |        meta: { 430 |            title: '首页', 431 |            keepAlive: true, 432 |            requireAuth: true 433 |       }, 434 |        component: () => import('@/pages/index.vue') 435 |   } 436 |  ] 437 | 438 |  const router = createRouter({ 439 |    history: createWebHistory(), 440 |    routes 441 |  }); 442 |  export default router; 443 | ``` 444 | 445 | 2. 在 main.ts 中引入并使用 446 | 447 | ```typescript 448 |  import { createApp } from 'vue' 449 |  import App from './App.vue' 450 |  import store from './store' 451 |  import router from '@/router'; 452 | 453 |  // 创建vue实例 454 |  const app = createApp(App); 455 | 456 |  app.use(router); 457 | 458 |  // 挂载实例 459 |  app.mount('#app'); 460 | ``` 461 | 462 | 3. 修改 App.vue 463 | 464 | ```typescript 465 |   468 | ``` 469 | 470 | # 5. 集成 `vueuse` 471 | `VueUse` 是一个基于 `Composition API` 的实用函数集合。 472 | 473 | ## 安装 474 | 475 | ``` 476 |  pnpm i @vueuse/core 477 | ``` 478 | 479 | ## 使用 480 | 481 | 1. 创建一个新的 src/page/vueUse.vue 页面来做一个简单的 demo 482 | 483 | ```typescript 484 |   488 | 489 |   504 | ``` 505 | useMouse 只是 vueuse 的一个最基本的函数库,还有许多,总会有一个适合你; 506 | 507 | 更多函数官方文档:[链接](https://vueuse.org/) 508 | 509 | # 6. CSS 的集成 510 | 511 | ## 方案一:原生 css variable 新特性: 512 | 513 | 原生支持,不需要第三方插件,具体使用文档可 [查看](https://developer.mozilla.org/zh-CN/docs/Web/CSS/var) 514 | 515 | 1. 新建文件 src/styles/index.css 516 | 517 | ```css 518 |  :root { 519 |    --main-bg-color: pink; 520 |  } 521 |  ​ 522 |  body { 523 |    background-color: var(--main-bg-color); 524 |  } 525 | ``` 526 | 527 | 注:还可以增加 PostCSS 配置,(任何受 [postcss-load-config](https://github.com/postcss/postcss-load-config) 支持的格式,例如 `postcss.config.js` ),它将会自动应用于所有已导入的 CSS。 528 | 529 | ## 方案二:scss 或 less: 530 | 531 | 1. 安装 532 | 533 | ```bash 534 |  # .scss and .sass 535 |  pnpm add -D sass 536 | 537 |  # .less 538 |  pnpm add -D less 539 | ``` 540 | 541 | 2. 使用在 .vue 文件模板中 542 | 543 | ```typescript 544 | // .scss 545 |   550 |   553 | 554 | // .less 555 |   560 |   563 | ``` 564 | 565 | # 7. 集成 `axios` 566 | 567 | `axios` 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 568 | 569 | ## 安装 570 | 571 | ```bash 572 |  pnpm i axios 573 | ``` 574 | 575 | ## 使用: 576 | 577 | 1. 新建 src/utils/axios.ts 578 | 579 | ```typescript 580 |  import axios, { AxiosResponse, AxiosRequestConfig } from 'axios'; 581 | 582 |  const service = axios.create(); 583 | 584 |  // Request interceptors 585 |  service.interceptors.request.use( 586 |     (config: AxiosRequestConfig) => { 587 |          // do something 588 |          return config; 589 |     }, 590 |     (error: any) => { 591 |          Promise.reject(error); 592 |     } 593 |  ); 594 | 595 |  // Response interceptors 596 |  service.interceptors.response.use( 597 |      async (response: AxiosResponse) => { 598 |          // do something 599 |     }, 600 |     (error: any) => { 601 |          // do something 602 |          return Promise.reject(error); 603 |     } 604 |  ); 605 | 606 |  export default service; 607 | ``` 608 | 609 | 2. 在页面中使用即可 610 | ```typescript 611 | 621 | ``` 622 | 623 | ## 封装请求参数和响应数据的所有 api (可选项) 624 | 1. 新建 `src/api/index.ts` 625 | ```typescript 626 | import * as login from './module/login'; 627 | import * as index from './module/index'; 628 | 629 | export default Object.assign({}, login, index); 630 | 631 | ``` 632 | 633 | 2. 新建 `src/api/module/login.ts` 和 `src/api/module/index.ts` 634 | ```typescript 635 | import request from '@/utils/axios'; 636 | 637 | /** 638 | * 登录 639 | */ 640 | 641 | interface IResponseType

{ 642 | code?: number; 643 | status: number; 644 | msg: string; 645 | data: P; 646 | } 647 | interface ILogin { 648 | token: string; 649 | expires: number; 650 | } 651 | export const login = (username: string, password: string) => { 652 | return request>({ 653 | url: '/api/auth/login', 654 | method: 'post', 655 | data: { 656 | username, 657 | password 658 | } 659 | }); 660 | }; 661 | ``` 662 | 3. 由于使用了 typescript,所以需新增 `src/types/shims-axios.d.ts` 663 | ```typescript 664 | import { AxiosRequestConfig } from 'axios'; 665 | /** 666 | * 自定义扩展axios模块 667 | * @author Maybe 668 | */ 669 | declare module 'axios' { 670 | export interface AxiosInstance { 671 | (config: AxiosRequestConfig): Promise; 672 | request(config: AxiosRequestConfig): Promise; 673 | get(url: string, config?: AxiosRequestConfig): Promise; 674 | delete(url: string, config?: AxiosRequestConfig): Promise; 675 | head(url: string, config?: AxiosRequestConfig): Promise; 676 | post(url: string, data?: any, config?: AxiosRequestConfig): Promise; 677 | put(url: string, data?: any, config?: AxiosRequestConfig): Promise; 678 | patch(url: string, data?: any, config?: AxiosRequestConfig): Promise; 679 | } 680 | } 681 | 682 | ``` 683 | 4. 在 `src/pages/request.vue` 页面中使用 684 | ```typescript 685 | 693 | 694 | ``` 695 | # 8. css 的 UI 样式库 696 | 697 | > 可选很多,根据自己项目的需求去进行选择即可 698 | 699 | **注意:UI 库一般需要按需引入(下面以 `element-plus` 为例)** 700 | 1. 安装 `vite-plugin-style-import` 701 | ```bash 702 | pnpm i vite-plugin-style-import --save-dev 703 | ``` 704 | 2. 修改 `vite.config.ts` 705 | ```typescript 706 | ... 707 | import styleImport from 'vite-plugin-style-import' 708 | 709 | 710 | export default defineConfig({ 711 | ... 712 | plugins: [ 713 | vue(), 714 | styleImport({ 715 | libs: [ 716 | { 717 | libraryName: 'element-plus', 718 | esModule: true, 719 | resolveStyle: (name) => { 720 | return `element-plus/lib/theme-chalk/${name}.css`; 721 | }, 722 | ensureStyleFile: true // 忽略文件是否存在, 导入不存在的CSS文件时防止错误。 723 | } 724 | ] 725 | }) 726 | ], 727 | ... 728 | }) 729 | 730 | ``` 731 | 732 | # 9. 使用 [commitizen](https://github.com/commitizen/cz-cli) 规范git提交 733 | 为了使团队多人协作更加的规范,所以需要每次在 git 提交的时候,做一次硬性规范提交,规范 git 的提交信息 734 | 735 | ## 安装 `commitizen` (交互式提交 + 自定义提示文案 + Commit规范) 736 | 1. 安装 737 | ```bash 738 | pnpm install -D commitizen cz-conventional-changelog @commitlint/config-conventional @commitlint/cli commitlint-config-cz cz-customizable 739 | ``` 740 | 2. 配置 `package.json` 741 | ```json 742 | { 743 | ... 744 | "scripts": { 745 | "commit:comment": "引导设置规范化的提交信息", 746 | "commit":"git-cz", 747 | }, 748 | 749 | "config": { 750 | "commitizen": { 751 | "path": "node_modules/cz-customizable" 752 | } 753 | }, 754 | ... 755 | } 756 | ``` 757 | 3. 新增配置 `commitlint.config.js` 758 | ```javascript 759 | module.exports = { 760 | extends: ['@commitlint/config-conventional', 'cz'], 761 | rules: { 762 | 'type-enum': [ 763 | 2, 764 | 'always', 765 | [ 766 | 'feature', // 新功能(feature) 767 | 'bug', // 此项特别针对bug号,用于向测试反馈bug列表的bug修改情况 768 | 'fix', // 修补bug 769 | 'ui', // 更新 ui 770 | 'docs', // 文档(documentation) 771 | 'style', // 格式(不影响代码运行的变动) 772 | 'perf', // 性能优化 773 | 'release', // 发布 774 | 'deploy', // 部署 775 | 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动) 776 | 'test', // 增加测试 777 | 'chore', // 构建过程或辅助工具的变动 778 | 'revert', // feat(pencil): add ‘graphiteWidth’ option (撤销之前的commit) 779 | 'merge', // 合并分支, 例如: merge(前端页面): feature-xxxx修改线程地址 780 | 'build', // 打包 781 | ], 782 | ], 783 | // 格式 小写 784 | 'type-case': [2, 'always', 'lower-case'], 785 | // 不能为空 786 | 'type-empty': [2, 'never'], 787 | // 范围不能为空 788 | 'scope-empty': [2, 'never'], 789 | // 范围格式 790 | 'scope-case': [0], 791 | // 主要 message 不能为空 792 | 'subject-empty': [2, 'never'], 793 | // 以什么为结束标志,禁用 794 | 'subject-full-stop': [0, 'never'], 795 | // 格式,禁用 796 | 'subject-case': [0, 'never'], 797 | // 以空行开头 798 | 'body-leading-blank': [1, 'always'], 799 | 'header-max-length': [0, 'always', 72], 800 | }, 801 | }; 802 | 803 | ``` 804 | 4. 自定义提示则添加 `.cz-config.js` 805 | ```javascript 806 | module.exports = { 807 | types: [ 808 | {value: 'feature', name: 'feature: 增加新功能'}, 809 | {value: 'bug', name: 'bug: 测试反馈bug列表中的bug号'}, 810 | {value: 'fix', name: 'fix: 修复bug'}, 811 | {value: 'ui', name: 'ui: 更新UI'}, 812 | {value: 'docs', name: 'docs: 文档变更'}, 813 | {value: 'style', name: 'style: 代码格式(不影响代码运行的变动)'}, 814 | {value: 'perf', name: 'perf: 性能优化'}, 815 | {value: 'refactor', name: 'refactor: 重构(既不是增加feature,也不是修复bug)'}, 816 | {value: 'release', name: 'release: 发布'}, 817 | {value: 'deploy', name: 'deploy: 部署'}, 818 | {value: 'test', name: 'test: 增加测试'}, 819 | {value: 'chore', name: 'chore: 构建过程或辅助工具的变动(更改配置文件)'}, 820 | {value: 'revert', name: 'revert: 回退'}, 821 | {value: 'build', name: 'build: 打包'} 822 | ], 823 | // override the messages, defaults are as follows 824 | messages: { 825 | type: '请选择提交类型:', 826 | customScope: '请输入您修改的范围(可选):', 827 | subject: '请简要描述提交 message (必填):', 828 | body: '请输入详细描述(可选,待优化去除,跳过即可):', 829 | footer: '请输入要关闭的issue(待优化去除,跳过即可):', 830 | confirmCommit: '确认使用以上信息提交?(y/n/e/h)' 831 | }, 832 | allowCustomScopes: true, 833 | skipQuestions: ['body', 'footer'], 834 | subjectLimit: 72 835 | }; 836 | ``` 837 | 5. 交互界面测试 838 | 839 | ![carbon.png](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d2be96b13d3c427e919b11e5bc5404e4~tplv-k3u1fbpfcp-watermark.image?) 840 | 841 | - 到目前只是规范了 git 的提交信息,我们对提交前代码的检查还没有做到位,例如 ESLint、Prettier,毕竟谁都会有疏忽的时候, 842 | - 那么现在我们的 husky 就闪亮登场了 843 | 844 | ## 安装 husky 845 | 1. 安装 846 | ```bash 847 | # 1.安装 848 | pnpm i husky lint-staged -D 849 | 850 | # 2.生成 .husky 的文件夹 851 | npx husky install 852 | 853 | # 3.添加 hooks,会在 .husky 目录下生成一个 pre-commit 脚本文件 854 | npx husky add .husky/pre-commit "npx --no-install lint-staged" 855 | 856 | # 4.添加 commit-msg 857 | npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"' 858 | 859 | # 5. 使用 `git commit -m "message"` 就会看到 hook 生效了。 860 | ``` 861 | 2. 添加配置 `package.json` 862 | ```json 863 | { 864 | ... 865 | "lint-staged": { 866 | "*.{js,ts}": [ 867 | "npm run eslint", 868 | "npm run prettier" 869 | ] 870 | } 871 | ... 872 | } 873 | ``` 874 | 875 | ## 提交日志(可选) 876 | - [standard-version](https://github.com/conventional-changelog/standard-version) 或者 [conventional-changelog](https://github.com/conventional-changelog/conventional-changelog) 877 | 878 | # 最后 879 | 该系列会是一个持续更新系列,关于整个《Vite 从入门到精通》,我主要会从如下图几个方面讲解,请大家拭目以待吧!!! 880 | 881 | ![Untitled.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/52ee2485e3484e8e8d995fbbb7e86835~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?) 882 | 883 | `靓仔靓女们`,都看到这里了,要不点个赞再走呗 🌹🌹🌹 884 | 885 | 886 | --------------------------------------------------------------------------------