├── 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 |
2 | This is Vue2
3 |
--------------------------------------------------------------------------------
/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 |
2 | This is Vue2
3 |
--------------------------------------------------------------------------------
/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 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/vite-nuxt3-app/src/layouts/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
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 |
2 |
3 |
这里是易师傅的 NuxtLayout 默认模板,可以添加在所有页面,也可单独添加
4 |
5 |
6 |
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:'MyButton '
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 |
2 |
3 |
欢迎来到易师傅的第一个页面
4 |
5 | 进入列表页
6 |
7 |
8 |
9 |
10 | 进入管理员 id 为 111 的用户中心
11 |
12 |
13 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
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 |
2 |
3 |
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 |
2 |
3 |
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 |
2 |
3 |
4 |
5 |
15 |
--------------------------------------------------------------------------------
/vite-vue3-admin/src/views/home/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
欢迎进入XX管理平台
4 |
5 |
6 |
15 |
16 |
--------------------------------------------------------------------------------
/koa2-ssr-vite-vue3-ts-pinia/src/pages/login.vue:
--------------------------------------------------------------------------------
1 |
2 | 这里是登录页面
3 |
4 | 点击跳转至首页
5 |
6 | 点击跳转至user页面
7 |
8 |
14 |
--------------------------------------------------------------------------------
/koa2-ssr-vite-vue3-ts-pinia/src/pages/user.vue:
--------------------------------------------------------------------------------
1 |
2 | 这里是用户中心页面
3 |
4 | 点击跳转至首页
5 |
6 | 点击跳转至login
7 |
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 |
2 | 这里是登录页面
3 |
4 | 点击跳转至首页
5 |
6 | 点击跳转至vueUse页面
7 |
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 |
2 | 这里是登录页面
3 |
4 | 点击跳转至首页
5 |
6 | 点击跳转至vueUse页面
7 |
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 |
2 |
3 |
欢迎来到易师傅的列表页面
4 |
5 |
6 |
7 |
focus
8 |
9 |
10 | 姓名:{{ userInfo.userName }}
11 | 性别:{{ userInfo.sex }}
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/vite-nuxt3-app/src/pages/[id]/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
易师傅的详细页面
5 |
6 |
title 1
7 |
8 |
内容 1
9 |
10 |
title 2
11 |
12 |
内容 2
13 |
14 |
title 3
15 |
16 |
内容 3
17 |
18 |
title 4
19 |
20 |
内容 4
21 |
22 |
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 |
2 |
3 |
4 |
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 |
2 |
3 |
4 |
用户中心
5 |
当前用户所属的群组:{{ route.params.group }}
6 |
当前用户的id:{{ route.params.id }}
7 |
8 |
9 | 坐标: {{x}}, {{y}}
10 |
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 |
2 |
3 |
4 | 111
5 |
6 |
7 | 222
8 |
9 |
10 | 333
11 |
12 |
13 | 444
14 |
15 |
16 | 555
17 |
18 |
19 | 666
20 |
21 |
22 |
--------------------------------------------------------------------------------
/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 |
2 | 欢迎使用vite+vue3+ts+pinia+vue-router4
3 | {{ userStore.name }}
4 |
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 |
2 | 欢迎使用vite+vue3+ts+pinia+vue-router4
3 | {{ userStore.name }}
4 |
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 |
2 | 测试 vueUse 的鼠标坐标
3 | Mouse: {{ x }} x {{ y }}
4 | 点击跳转至首页
5 |
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 |
2 | 测试 vueUse 的鼠标坐标
3 | Mouse: {{ x }} x {{ y }}
4 | 点击跳转至首页
5 |
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 |
2 | 测试 vueUse 的鼠标坐标
3 | Mouse: {{ x }} x {{ y }}
4 |
5 |
6 | 点击跳转至首页
7 |
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 |
8 |
9 |
10 |
11 |
12 |
22 |
--------------------------------------------------------------------------------
/koa2-ssr-vite-vue3-ts-pinia/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 点击跳转至login
6 |
7 | 点击跳转至user页面
8 |
9 | 点击跳转至vueuse页面
10 |
11 |
12 |
23 |
--------------------------------------------------------------------------------
/vite-vue3-ts-pinia/src/pages/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 点击跳转至login
6 |
7 | 点击跳转至vueUse页面
8 |
9 | 点击跳转至request请求页面
10 |
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 |
2 |
3 |
4 |
5 | 点击跳转至login
6 |
7 | 点击跳转至vueUse页面
8 |
9 | 点击跳转至request请求页面
10 |
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 |
2 | 欢迎使用vite+vue3+ts+pinia+vue-router4
3 | {{ userStore.name }}的年龄: {{ userStore.age }}
5 | 点击给{{ userStore.name }}的年龄增加一岁
6 |
7 |
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 |
2 | 这里是request请求页面
3 |
4 | 点击跳转至首页
5 |
6 |
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 |
10 | {{ msg }}
11 |
12 |
13 | Recommended IDE setup:
14 | VSCode
15 | +
16 | Volar
17 |
18 |
19 | See README.md for more information.
20 |
21 |
22 |
23 | Vite Docs
24 |
25 | |
26 | Vue 3 Docs
27 |
28 |
29 | count is: {{ count }}
30 |
31 | Edit
32 | components/HelloWorld.vue to test hot module replacement.
33 |
34 |
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 |
12 | Hello Vite + React!
13 |
14 | setCount((count) => count + 1)}>
15 | count is: {count}
16 |
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 |
12 | Hello Vite + React!
13 |
14 | setCount((count) => count + 1)}>
15 | count is: {count}
16 |
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 |
2 |
21 |
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 |
2 |
3 |
4 |
5 |
6 |
11 |
test
15 |
18 |
20 |
21 |
22 |
23 |
24 |
53 |
95 |
--------------------------------------------------------------------------------
/vite-vue3-admin/src/views/login/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 登 录
5 |
6 |
10 |
14 |
15 |
19 |
25 |
26 |
27 | 登录
30 |
31 |
32 |
33 |
34 |
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 | 
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 | 
296 |
297 | 3. 并且我们 `右键查看显示网页源代码`,也会看到渲染的正常 html
298 |
299 | ```html
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 | koa2 + vite + ts + vue3
309 |
310 |
311 | Hello Vue 3 + TypeScript + Vite Recommended IDE setup: VSCode + Volar
See README.md for more information.
Vite Docs | Vue 3 Docs
count is: 0 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 |
642 | 欢迎使用vite+vue3+ts+pinia+vue-router4
643 | {{ userStore.name }}的年龄: {{ userStore.age }}
645 | 点击给{{ userStore.name }}的年龄增加一岁
646 |
647 |
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 | 
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 |
373 | {{ userStore.name }}
374 |
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 |
466 |
467 |
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 |
485 | 测试 vueUse 的鼠标坐标
486 | Mouse: {{x}} x {{y}}
487 |
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 |
546 |
547 |
欢迎使用 scss
548 |
549 |
550 |
553 |
554 | // .less
555 |
556 |
557 |
欢迎使用 less
558 |
559 |
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 | 
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 | 
882 |
883 | `靓仔靓女们`,都看到这里了,要不点个赞再走呗 🌹🌹🌹
884 |
885 |
886 |
--------------------------------------------------------------------------------