- Vite-based
- Vue3-compatible
- File-based routing
- Layout system
- Mock support
- Auto import APIs
- Auto import components
- Auto import icons
- VueUse support
- TypeScript-friendly
- UnoCss integration
- Dark mode support
- SWR request support
- Pinia state management
- pnpm package manager
- Progress bar for navigation
- Devtools panel support
- Plugin auto-loading support
- Vitest unit testing support
- Markdown rendering support
- Path aliases support
- Command line auto creation and deletion
- i18n internationalization support
- Beautiful 404 page support
- TSX support
- Gzip resource compression support
- Environment variable configuration support
- Unified code style and formatting support
- Production environment automatically removes development logs
- defineOptions support
- Echarts integration
- Global toast notifications
- Global axios request wrapping
- Auto generate type declarations for environment variables
renovate
automatic dependency updates- Auto version update and generate
CHANGELOG
- Fastest and smallest
dockerfile
for staticgo
service with minimal configuration base
secure path resolutionlightningcss
support- Vite configuration layer support (experimental)
- Github
git clone git@github.com:dishait/tov-template.git
- Gitee
git clone git@gitee.com:dishait/tov-template.git
- degit
npx degit https://github.com/dishait/tov-template#main
- New
Github
repository 👉 Use this template
Since this template is fully geared towards modern development, it is
recommended to use the current long-term maintenance version of node
, which is
v20
.
This template only supports the pnpm
package manager. 👉
Installation guide
- Install dependencies
pnpm install
- Development
pnpm dev
# Open host
pnpm dev:host
# Auto-open browser
pnpm dev:open
- Preview
pnpm preview
# Open host
pnpm preview:host
# Auto-open browser
pnpm preview:open
- Build
pnpm build
pnpm build:debug
- Unit testing
pnpm test
- Unit test report generation
pnpm coverage
- Type checking
pnpm typecheck
- Auto creation
pnpm auto:create
- Auto removal
pnpm auto:remove
- Dependency updates
# Update dependency version
pnpm deps:fresh
# The above commands only write to the package information file package.json, and need to re-execute the package installation command.
pnpm i
- Code style checking
pnpm lint
# Fix errors during linting
pnpm lint:fix
- Safe Init
pnpm safe:init
Why did we create this template?
- Save time on configuration for future development projects.
- Integrate modern development architecture with mainstream plugins to improve development efficiency.
When should you use this template?
- Don't want to waste time on project configuration.
- Want to try developing web applications in a more modern way and improve development efficiency.
This template is inspired by vitesse. If you have an SSR scenario, we recommend that you use vitesse.
Welcome to follow dishait
This template uses Vite as the build tool. You can
configure the project's build in vite.config.ts
at the root directory.
For the introduction of many mainstream plugins and complex configurations, they have been integrated into the presets under the root directory. In most cases, you do not need to reconfigure them.
The directory structure is the route.
For example:
src/pages/index.vue
=>/
src/pages/about.vue
=>/about
src/pages/users/index.vue
=>/users
src/pages/users/profile.vue
=>/users/profile
src/pages/users/[id].vue
=>/users/:id
src/pages/[user]/settings.vue
=>/:user/settings
src/pages/[...notFound].vue
=> 404 route
For more details, please refer to unplugin-vue-router.
src/layouts/default.vue
will be used as the default layout.
<!-- src/layouts/default.vue -->
<template>
default
<router-view />
<!-- Page view outlet -->
</template>
At this point, src/pages/index.vue
:
<!-- src/pages/index.vue -->
<template>
<div>home</div>
</template>
When routing to /
, the page will render:
default home
Now, src/pages/about.vue
:
<!-- src/pages/about.vue -->
<template>
<div>about</div>
</template>
When routing to /about
, the page will render:
default about
Create a src/layouts/custom.vue
randomly:
<!-- src/layouts/custom.vue -->
<template>
custom
<router-view />
<!-- Page view outlet -->
</template>
At this point, in src/pages/index.vue
:
<!-- src/pages/index.vue -->
<template>
<div>home</div>
</template>
<!-- Add custom block 👇 -->
<route lang="json">
{
"meta": {
"layout": "custom"
}
}
</route>
When routing to /
, the page will render:
custom home
See specifically 👉 vite-plugin-vue-meta-layouts
In the mock
directory under the root directory, you can export default api
resources in modules.
For example, export from mock/test.ts
:
import { MockMethod } from "vite-plugin-mock";
export default [
{
url: "/api/mock/get",
method: "get",
response: () => {
return {
code: 0,
data: {
name: "vben",
},
};
},
},
] as MockMethod[];
You can then make mock requests in the src
directory.
<template>
<div>data: {{data}}</div>
<div>loading: {{loading}}</div>
<div>error: {{error}}</div>
</template>
Here we use vue-request to make requests, but since
this mock
intercepts an entire interface, it is also possible to use request
libraries such as axios
.
The original vue
api
needs to be manually import
ed.
import { computed, ref } from "vue";
const count = ref(0);
const doubled = computed(() => count.value * 2);
Now it can be directly used.
const count = ref(0);
const doubled = computed(() => count.value * 2);
And the above api
is automatically imported on demand.
Currently, the template supports automatic import of libraries that support
auto-importing api
.
vue
vuex
pinia
vue-i18n
vue-router
@vueuse/core
@vueuse/head
@vueuse/math
Just make sure to install the dependencies and see the specific details here 👉 vite-auto-import-resolvers,
Of course, there are also automatic imports in projects, just need to meet the following specifications.
- The export from
src/composables
will be automatically imported as needed.
For example, there is a src/composables/foo.ts
file:
// default export
export default 1000;
- No need for
import
at this point.
<script setup lang="ts">
console.log(foo) // output 1000
</script>
<template>
<div @click="store.inc()">{{store.counter}}</div>
</template>
- The export from
src/stores
will be automatically imported as needed.
For example, there is a src/stores/counterStore.ts
file:
// default export
export default defineStore("counter", {
state() {
return {
counter: 1,
};
},
actions: {
inc() {
this.counter++;
},
},
});
At this point, there is no need for import
anymore.
<script setup lang="ts">
const store = counterStore()
</script>
<template>
<div @click="store.inc()">{{store.counter}}</div>
</template>
src/api
is also automatically imported on demand, similar to the above.
You can see more details in the unplugin-auto-import documentation.
It turns out that import
is required.
<!-- src/pages/index.vue -->
<script setup lang="ts">
import Hello from '../components/Hello.vue'
</script>
<template>
<Hello />
</template>
Now, any components defined in the src/components
directory will be
automatically imported on demand, meaning that import
statements are not
required.
<!-- src/pages/index.vue -->
<template>
<Hello />
</template>
Of course, it also supports nested components, such as
src/components/foo/bar.vue
👇
<!-- src/pages/index.vue -->
<template>
<FooBar />
</template>
Automatic importing of popular component libraries is also supported, such as
Naive ui
.
You only need to install the dependency.
pnpm add naive-ui
Then you can use it in your templates.
<!-- src/pages/index.vue -->
<template>
<n-button type="success">Success</n-button>
</template>
Currently supported component libraries are:
- vant
- idux
- devui
- quasar
- varlet
- inkline
- vuetify
- naive-ui
- primevue
- layui-vue
- view-design
- arco-design
- element-plus
- ant-design-vue
- @headlessui/vue
- tdesign-vue-next
- @vueuse/components
Please refer to 👉 unplugin-vue-components
You can go to icones and click on any icon library you like.
Then click on one of the icons you like.
Copy its name.
In the template, you can use it directly through the class
method, remember to
add the prefix i-
.
<template>
<div class="i-mdi:account-box-multiple"></div>
</template>
After saving, wait for the automatic download of theAfter saving, wait for the automatic download of the icon library and you can see the corresponding icon in the page.
I also recommend using the vscode
plugin
Iconify IntelliSense.
This plugin displays a preview of the icons in the template.
Of course, dynamic loading of icons is also supported:
<script>
const icon = ref("i-ep:arrow-left")
// Change to another icon after two seconds.
setTimeout(() => {
icon.value = 'i-icon-park-outline:arrow-circle-down'
}, 2000)
</script>
<template>
<div :class="icon"></div>
</template>
Please note that for dynamic icons, make sure to test all the icons in the development environment.
For more information, please refer to unocss/presets/icons.
VueUse
is a powerful hooks
library. For example, if you want to get the
mouse position, you only need to do this:
<script setup lang="ts">
// The `useMouse` hook is automatically imported on demand, so thereThe `useMouse` hook is automatically imported on demand, so there's no need for an `import` statement.
const { x, y } = useMouse()
</script>
<template>
<div>x {{x}}</div>
<div>y {{y}}</div>
</template>
Please refer to 👉 VueUse
You don't need to reconfigure, just write it in ts
directly.
unocss
is a faster development atomic CSS
library.
You can use it directly in the template, no configuration is needed.
<template>
<div class="bg-red-500 text-white">I am white text on a red background.</div>
</template>
The above template will render white text on a red background.
It also supports attribute mode, which means you can use shorthand notation.
<template>
<div text="white" bg="red-500">I am white text on a red background.</div>
</template>
This can reduce the amount of code when adjusting margin sizes, among other things.
For more information, please refer to unocss.
Dark mode is implemented by vue-dark-switch.
<script setup>
import { SwitchIcon } from "vue-dark-swicth"
</script>
<template>
<!-- Dark switch, one-click to switch to dark mode. -->
<SwitchIcon />
</template>
Please refer to 👉 vue-dark-switch
SWR is a more modern way of making requests, for more information please refer to the article 👉 SWR.
And vue-request is a Vue version request library for SWR.
You can use it like this, for example, to request /api/test
<script setup lang="ts">
import { useRequest } from 'vue-request'
const { data, loading, error } = useRequest('/api/test')
</script>
<template>
<div>data: {{data}}</div>
<div>error: {{error}}</div>
<div>loading: {{loading}}</div>
</template>
All the basic data, state, and caching are handled for you, so there's no need to re-wrap things.
For more information, please refer to vue-request.
Pinia
is the next-generation state management library, which is simpler than
Vuex
and has better TypeScript support.
You can define your states in the src/stores
directory.
For example, create a src/stores/counter.ts
file:
// src/stores/counter.ts
import { defineStore } from "pinia";
export const useCounterStore = defineStore("counter", {
state() {
return { count: 0 };
},
actions: {
inc() {
this.count++;
},
},
});
After defining it, you can use it directly in the setup
.
<!-- src/pages/index.vue -->
<script setup lang="ts">
const Counter = useCounterStore()
<script>
<template>
<div @click="Counter.inc">{{Counter.count}}</div>
</template>
For more specific usage, please refer to Pinia.
pnpm
is an excellent package manager that is faster, more space-efficient, and
more reasonable.
For more information, please refer to pnpm.
The jumping progress bar is implemented by nprogress
, and you can adjust the
color scheme in src/styles/main.css
.
/** src/styles/main.css **/
/** Omit other styles. **/
#nprogress .bar {
@apply bg-blue-700 bg-opacity-75; /** color **/
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
About @apply
, it is implemented by
@unocss/transformer-directives.
For more information, please refer to 👉 nprogress.
This panel allows you to understand various aspects of the project during development, and it is currently only effective in the development environment.
For more information, please refer to vite-plugin-vue-devtools.
You only need to export the default function in the module located in
src/plugins
.
For example, with pinia
, you only need to do this:
// src/plugins/pinia.ts
// Export the default interface
export default createPinia(); // pinia will be automatically installed
Or with vue-router
:
// src/plugins/router.ts
// Omit various configurations
// Export the default interface
export default router; // The router will be automatically installed
Of course, pinia
and vue-router
are already preset, so you don't need to
worry about them again.
For more information, please refer to vite-plugin-use-modules.
You can write unit tests in the src/test
directory.
import { assert, describe, expect, it } from "vitest";
describe("suite name", () => {
it("foo", () => {
expect(1 + 1).toEqual(2);
expect(true).to.be.true;
});
it("bar", () => {
assert.equal(Math.sqrt(4), 2);
});
it("snapshot", () => {
expect({ foo: "bar" }).toMatchSnapshot();
});
});
Then you can run the tests by entering the following command in the terminal:
pnpm test
Or generate a report:
pnpm coverage
For more information, please refer to Vitest.
Markdown rendering can be used to write some simple instructions.
You only need to change the file extension of pages in the src/pages
directory
from .vue
to .md
, and then modify it to use markdown syntax.
For example, src/pages/about.md
:
## About Page
> The page is a markdown file
When you route to /about
, you can see the corresponding markdown rendering.
Of course, it also supports embedding Vue components in markdown.
For more information, please refer to unplugin-vue-markdown.
The ~
or @
path will be directed to the src
directory of the project,
while providing better type hinting.
<!-- src/pages/index.vue -->
<script lang="ts" setup>
import { useDarks } from '~/composables/dark'
// Is equivalent to
// import { useDarks } from "../composables/dark"
</script>
To create a standard page or component just enter 👇,
pnpm auto:create
Of course, you can also delete 👇,
pnpm auto:remove
In daily business, there may be some scenarios that require
internationalization. Then you only need to define different languages' yml
in
the locales
directory at the root level to achieve out-of-the-box
internationalization support in the project.
For example, locales/en.yml
is used to define the English content that
requires internationalization support.
# locales/en.yml
# English
index: index
about: about
not-found: Notfound
For example, locales/简体中文.yml
is used to define the Chinese content that
requires internationalization support.
# locales/简体中文.yml
# 中文
index: 主页
about: 关于
not-found: 未找到页面
You can use it in components like this at this time 👇
<script setup>
// This API is globally imported on demand, so it can be used directly.
// t is used to bind specific language blocks.
const { t, locale } = useI18n()
const toggleLocale = () => {
// locale.value is used to represent the current language, and it can be modified for language switching.
locale.value = locale.value === '简体中文' ? 'en' : '简体中文'
}
</script>
<template>
<div m="6" cursor="pointer" @click="toggleLocale()">
language: {{ t('index') }} click me!!
</div>
</template>
For more detailed instructions, please refer to the @intlify/vite-plugin-vue-i18n and vue-i18n.
In addition, yml
is a popular configuration file format in frontend
development, and you can find its syntax in Mr. Ruan Yifeng's tutorial:
YAML Language Tutorial.
Here are some recommended VS Code plugins:
- Multifunctional
i18n
support: i18n Ally
For more detailed instructions, please refer to the @intlify/vite-plugin-vue-i18n and vue-i18n.
In addition, yml
is a popular configuration file format in frontend
development, and you can find its syntax in Mr. Ruan Yifeng's tutorial:
YAML Language Tutorial.
Here are some recommended VS Code plugins:
Multifunctional i18n
support:
i18n Ally
In daily business, when a user visits a non-existent page, they should be given
an information prompt that the page does not exist, and this prompt page is the
404
page.
You can visit any non-existent page at random, for example /bucunzai
Of course, there is also dark mode adaptation.
It also supports simple responsive adaptation. For example, it will display correctly on mobile browsers.
If the cover of this 404
page does not meet your taste, you can modify the
src
attribute of the img
tag in pages/[...notFound].vue
. The default is
32.svg
, supporting 1 ~ 33
svg
.
For example, the default is:
<!-- Omitting various codes -->
<template>
<img src="/notFound/32.svg" class="cover" alt="page not found" />
</template>
To change the cover to /notFound/33.svg
, modify it as follows:
<!-- Omitting various codes-->
<template>
<img src="/notFound/33.svg" class="cover" alt="page not found" />
</template>
This will switch the cover to:
25. tsx
Support
You only need to place the .tsx
file under src/components
, and you can
directly use it in the template.
For example, if you have a src/components/foo.tsx
file, you can directly use
it in the template.
// src/components/foo.tsx
export default defineComponent({
render() {
return <div>Test</div>;
},
});
<template>
<foo />
</template>
For more details, please refer to: @vitejs/plugin-vue-jsx
Out-of-the-box gzip
resource compression in production environment, no
configuration required.
For more details, please refer to: vite-plugin-compression
The .env
file in the root directory is used to configure environment variables
for the project.
Code style verification provided by eslint and code standardization using prettier.
Provided by husky +
lint-staged during commit
verification.
In the production environment, logs such as console.log
, console.warn
, and
console.error
will be automatically removed to avoid the leakage of
development logs.
For more details, please refer to: vite-plugin-removelog
<script setup lang="ts">
// Define additional options
defineOptions({
name: 'Foo',
})
</script>
31. Echarts Support
A simple integration with vue-echarts, please refer to the documentation of echarts and vue-echarts.
Integrated with vue-toastification,
you can use it in all files under the src
directory:
// Any file under the `src` directory is available.
toast.info("info");
toast.error("error");
toast.warning("warning");
toast.success("success");
For more details, please refer to: Global Toast Notification
The axios is wrapped, and you can use it in all
files under the src
directory:
// Available in any file under src
http.get("...");
http.post("...", { name: "张三", age: 20 });
// ... and so on
The above http
is an instance created separately by axios
, with simple error
prompts and response data conversion. For more details, please refer to
src/composables/http.ts
.
If you prefer a reactive style and swr
, you can use it together with
vue-request.
import { useRequest } from "vue-request";
const { data, error, loading } = useRequest(() => http.get("..."));
loading.value; // loading
error.value; // error
data.value; // data
The http
instance's baseURL
takes the value from the environment variable
file .env
for VITE_API_BASE_URL
, defaulting to /api
, which can be changed
according to your needs.
For more details, please refer to 👉 axios.
In Vite projects, we can set environment variables in .env
and use them in the
frontend source code through import.meta.env
, but the type hinting is poor.
This feature can automatically generate type declarations to achieve real-time
type hinting, so you don't need to worry about and manage them manually.
For more details, please refer to: vite-plugin-env-types.
The renovate bot on GitHub will
periodically check dependencies on GitHub and raise a pr
to update the
repository, with the update strategy available at:
unjs/renovate-config.
Of course, you can also manually execute it to update:
pnpm deps:fresh
For more details, please refer to: renovate
When we execute pnpm run release
, it will automatically update the version and
update the CHANGELOG.md
file.
For more details, please refer to: unjs/changelogen.
The dockerfile
in the root directory configures the smallest and fastest
container for a static go
service, making it more convenient for cloud
container services.
For more details, please refer to: PierreZ/goStatic.
In Vite, if we change the base
in vite.config.ts
, it causes the resource
paths and route paths to become invalid. Using safeResolve
can ensure that the
same base
is used in both development and production environments.
<script setup lang="ts">
const path = safeResolve("your route path")
</script>
<template>
<!-- Applications in templates are also allowed. -->
<img :src="safeResolve('/notFound/32.svg')"/>
</template>
Now it will automatically detect whether the current project supports lightningcss and enable it intelligently.
Now in tov-template
, we can use the form of vite.config.[mode].ts
to support
configuration files for different environments.
- Only vite.config.ts is selected when there is no specific mode.
- When both vite.config.ts and vite.config.dev.ts exist, their configurations are merged during development, with the configuration in vite.config.dev.ts having higher priority.
- When both vite.config.ts and vite.config.prod.ts exist, their configurations are merged during production, with the configuration in vite.config.prod.ts having higher priority.
This feature is supported by vite-layers.
Made with markthree
Published under MIT License.