├── .eslintignore
├── .env.production
├── .env.development
├── .env
├── .env.qa
├── .prettierignore
├── .gitignore
├── .editorconfig
├── src
├── stores
│ ├── index.ts
│ ├── common.ts
│ └── counter.ts
├── pages
│ ├── home
│ │ ├── index.module.less
│ │ └── index.tsx
│ ├── h5
│ │ └── index.tsx
│ └── hybird
│ │ └── index.tsx
├── main.tsx
├── styles
│ ├── global.less
│ └── reset.less
├── routes
│ └── index.ts
├── hooks
│ └── index.ts
├── layouts
│ └── index.tsx
└── assets
│ └── logo.svg
├── README.md
├── .prettierrc
├── index.html
├── .vscode
└── settings.json
├── .eslintrc
├── tsconfig.json
├── LICENSE
├── package.json
└── vite.config.ts
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | src/lib/*
3 | typings
4 |
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | # 表示生产环境
2 | #NODE_ENV=production
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | VITE_STATIC_CDN=http://localhost:5000/
2 |
3 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | VITE_STATIC_CDN=http://heaven-blog-1255884785.file.myqcloud.com/
2 |
--------------------------------------------------------------------------------
/.env.qa:
--------------------------------------------------------------------------------
1 | NODE_ENV=production
2 | VITE_STATIC_CDN=http://localhost:5000/
3 |
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | **/*.md
2 | **/*.svg
3 | **/*.ejs
4 | **/*.html
5 | src/lib/*
6 | node_modules
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 | stats.html
7 | .eslintcache
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/src/stores/index.ts:
--------------------------------------------------------------------------------
1 | import counterStore from './counter'
2 | import commonStore from './common'
3 |
4 | const _store = {
5 | counterStore,
6 | commonStore
7 | }
8 |
9 | export type StoreType = typeof _store
10 |
11 | export default _store
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 项目介绍
2 | 基于 Vite + Typescript + React 打造的前端单页应用模板
3 |
4 | # 拥有特性
5 | 1. 路由动态加载
6 | 2. 代码构建压缩优化
7 | 3. less 支持
8 | 4. vw,vh 适配移动端方案
9 | 5. mobx 状态管理方案
10 |
11 | # 使用说明
12 |
13 | [详细介绍](https://heavenru.com/post/Vite-with-React-%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5)
14 |
--------------------------------------------------------------------------------
/src/pages/home/index.module.less:
--------------------------------------------------------------------------------
1 | .title {
2 | font-size: 36px;
3 | font-weight: bold;
4 | text-align: center;
5 | margin: 20px;
6 | }
7 |
8 | .row {
9 | padding: 10px 0;
10 | font-size: 24px;
11 | }
12 |
13 | .result {
14 | font-size: 24px;
15 | color: red;
16 | padding: 10px;
17 | }
18 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "tabWidth": 2,
4 | "bracketSpacing": true,
5 | "trailingComma": "none",
6 | "printWidth": 100,
7 | "semi": false,
8 | "overrides": [
9 | {
10 | "files": ".prettierrc",
11 | "options": { "parser": "typescript" }
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/src/stores/common.ts:
--------------------------------------------------------------------------------
1 | import { makeAutoObservable, observable } from 'mobx'
2 |
3 | class CommonStore {
4 | title = ''
5 | theme = 'default'
6 |
7 | constructor() {
8 | makeAutoObservable(this)
9 | }
10 |
11 | setTheme(theme: string) {
12 | this.theme = theme
13 | }
14 |
15 | setTitle(title: string) {
16 | this.title = title
17 | }
18 | }
19 |
20 | export default new CommonStore()
21 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Vite App
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/stores/counter.ts:
--------------------------------------------------------------------------------
1 | import { observable } from 'mobx'
2 |
3 | export interface CounterStore {
4 | counter: number
5 | increment: () => void
6 | decrement: () => void
7 | incrementAsync: () => void
8 | }
9 |
10 | const counterStore: CounterStore = observable({
11 | counter: 0,
12 | increment() {
13 | this.counter++
14 | },
15 | decrement() {
16 | this.counter--
17 | },
18 | incrementAsync() {
19 | setTimeout(() => {
20 | this.counter++
21 | }, 1000)
22 | }
23 | })
24 |
25 | export default counterStore
26 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import { BrowserRouter } from 'react-router-dom'
4 | import { Provider } from 'mobx-react'
5 | import '@/styles/global.less'
6 | import { renderRoutes } from 'react-router-config'
7 | import routes from './routes'
8 | import stores from '@/stores'
9 |
10 | ReactDOM.render(
11 |
12 |
13 | {renderRoutes(routes)}
14 |
15 | ,
16 | document.getElementById('root')
17 | )
18 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.formatOnSave": true,
3 | "editor.codeActionsOnSave": {
4 | "source.fixAll.tslint": true
5 | },
6 | "editor.defaultFormatter": "esbenp.prettier-vscode",
7 | "[javascript]": {
8 | "editor.formatOnSave": true,
9 | "editor.defaultFormatter": "esbenp.prettier-vscode"
10 | },
11 | "[typescript]": {
12 | "editor.defaultFormatter": "esbenp.prettier-vscode"
13 | },
14 | "typescript.tsdk": "node_modules/typescript/lib",
15 | "[typescriptreact]": {
16 | "editor.defaultFormatter": "esbenp.prettier-vscode"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/styles/global.less:
--------------------------------------------------------------------------------
1 | @import './reset.less';
2 | body {
3 | margin: 0;
4 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu',
5 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 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', monospace;
12 | }
13 |
14 | .safe-area {
15 | padding-bottom: constant(safe-area-inset-bottom);
16 | padding-bottom: env(safe-area-inset-bottom);
17 | }
18 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["alloy", "alloy/react", "alloy/typescript"],
3 | "env": {
4 | // Your environments (which contains several predefined global variables)
5 | //
6 | "browser": true,
7 | "node": true
8 | // mocha: true,
9 | // jest: true,
10 | // jquery: true
11 | },
12 | "globals": {
13 | // Your global variables (setting to false means it"s not allowed to be reassigned)
14 | //
15 | // myGlobal: false
16 | },
17 | "rules": {
18 | // Customize your rules
19 | "@typescript-eslint/explicit-member-accessibility": "off"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/pages/h5/index.tsx:
--------------------------------------------------------------------------------
1 | import { useStores } from '@/hooks'
2 | import { observer } from 'mobx-react'
3 | import React from 'react'
4 |
5 | const H5Home: React.FC = observer((props) => {
6 | const counterStore = useStores('counterStore')
7 | return (
8 | <>
9 | Welcome H5 Home
10 | store counter: {counterStore.counter}
11 |
14 |
17 | >
18 | )
19 | })
20 |
21 | export default H5Home
22 |
--------------------------------------------------------------------------------
/src/pages/hybird/index.tsx:
--------------------------------------------------------------------------------
1 | import { useStores } from '@/hooks'
2 | import { observer } from 'mobx-react'
3 | import React from 'react'
4 |
5 | const HybirdHome: React.FC = observer((props) => {
6 | const commonStore = useStores('commonStore')
7 |
8 | return (
9 | <>
10 | Welcome Hybird Home
11 | current theme: {commonStore.theme}
12 |
15 |
18 | >
19 | )
20 | })
21 |
22 | export default HybirdHome
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "experimentalDecorators": true,
4 | "target": "ESNext",
5 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
6 | "types": ["vite/client"],
7 | "allowJs": false,
8 | "skipLibCheck": false,
9 | "esModuleInterop": false,
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "module": "ESNext",
14 | "moduleResolution": "Node",
15 | "resolveJsonModule": true,
16 | "isolatedModules": true,
17 | "noEmit": true,
18 | "jsx": "react",
19 | "baseUrl": "./",
20 | "paths": {
21 | "@/*": ["./src/*"]
22 | },
23 | "typeRoots": ["./typings/", "./node_modules/@types/"]
24 | },
25 | "include": ["./src", "./typings", "./vite.config.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------
/src/routes/index.ts:
--------------------------------------------------------------------------------
1 | import loadable from '@loadable/component'
2 | import Layout, { H5Layout } from '@/layouts'
3 | import { RouteConfig } from 'react-router-config'
4 | import Home from '@/pages/home'
5 |
6 | const routesConfig: RouteConfig[] = [
7 | {
8 | path: '/',
9 | exact: true,
10 | component: Home
11 | },
12 | // APP 路由
13 | {
14 | path: '/hybird',
15 | exact: true,
16 | component: Layout,
17 | routes: [
18 | {
19 | path: '/',
20 | exact: false,
21 | component: loadable(() => import('@/pages/hybird'))
22 | }
23 | ]
24 | },
25 | // H5 相关路由
26 | {
27 | path: '/h5',
28 | exact: false,
29 | component: H5Layout,
30 | routes: [
31 | {
32 | path: '/',
33 | exact: false,
34 | component: loadable(() => import('@/pages/h5'))
35 | }
36 | ]
37 | }
38 | ]
39 |
40 | export default routesConfig
41 |
--------------------------------------------------------------------------------
/src/pages/home/index.tsx:
--------------------------------------------------------------------------------
1 | import { useStores } from '@/hooks'
2 | import { observer } from 'mobx-react'
3 | import React from 'react'
4 | import { Link } from 'react-router-dom'
5 | import styles from './index.module.less'
6 |
7 | interface IHomeProps {
8 | title: string
9 | backurl?: string
10 | }
11 |
12 | const Home: React.FC = observer((props) => {
13 | const { backurl, title } = props
14 |
15 | const counterStore = useStores('counterStore')
16 | const commonStore = useStores('commonStore')
17 |
18 | return (
19 | <>
20 | Welcome Home {title}
21 | current counter:{counterStore.counter}
22 | current theme:{commonStore.theme}
23 |
24 | H5 模块
25 |
26 |
27 | hybird 模块
28 |
29 | >
30 | )
31 | })
32 |
33 | export default Home
34 |
--------------------------------------------------------------------------------
/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { useLocation } from 'react-router-dom'
3 | import { MobXProviderContext } from 'mobx-react'
4 | import { StoreType } from '@/stores'
5 |
6 | // 获取浏览器 ?后面的参数
7 | export function useQuery() {
8 | const query: { [x: string]: string } = {}
9 | const search = useLocation().search
10 | const params = new URLSearchParams(search)
11 | params.forEach((val, key) => {
12 | query[key] = val
13 | })
14 | return query
15 | }
16 | interface ContextType {
17 | stores: StoreType
18 | }
19 |
20 | // 函数声明,重载
21 | function useStores(): StoreType
22 | function useStores(storeName: T): StoreType[T]
23 |
24 | /**
25 | * 获取根 store 或者指定 store 名称数据
26 | * @param storeName 指定子 store 名称
27 | * @returns typeof StoreType[storeName]
28 | */
29 | function useStores(storeName?: T) {
30 | const rootStore = React.useContext(MobXProviderContext)
31 | const { stores } = rootStore as ContextType
32 | return storeName ? stores[storeName] : stores
33 | }
34 |
35 | export { useStores }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Heaven
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 |
--------------------------------------------------------------------------------
/src/layouts/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { RouteConfigComponentProps, renderRoutes } from 'react-router-config'
3 |
4 | /**
5 | *
6 | {routes.map((route, i) => (
7 |
13 | route.render ? (
14 | route.render({ ...props, ...extraProps, route: route })
15 | ) : (
16 |
17 | )
18 | }
19 | />
20 | ))}
21 |
22 | */
23 | const Layout: React.FC = React.memo(function Layout(props) {
24 | // const history = useHistory()
25 | const { route } = props
26 | console.log('hybird layout')
27 | return renderRoutes(route?.routes)
28 | })
29 |
30 | export const H5Layout: React.FC = React.memo(function H5Layout(props) {
31 | const { route } = props
32 | // const history = useHistory()
33 | // TODO 判断是否是微信环境,跳转到错误提示页
34 | // history.push('/wx-page-error')
35 | console.log('h5 layout')
36 | return <>{renderRoutes(route?.routes)}>
37 | })
38 |
39 | export default Layout
40 |
--------------------------------------------------------------------------------
/src/styles/reset.less:
--------------------------------------------------------------------------------
1 | html,
2 | body,
3 | div,
4 | span,
5 | applet,
6 | object,
7 | iframe,
8 | h1,
9 | h2,
10 | h3,
11 | h4,
12 | h5,
13 | h6,
14 | p,
15 | blockquote,
16 | pre,
17 | a,
18 | abbr,
19 | acronym,
20 | address,
21 | big,
22 | cite,
23 | code,
24 | del,
25 | dfn,
26 | em,
27 | img,
28 | ins,
29 | kbd,
30 | q,
31 | s,
32 | samp,
33 | small,
34 | strike,
35 | strong,
36 | sub,
37 | sup,
38 | tt,
39 | var,
40 | b,
41 | u,
42 | i,
43 | center,
44 | dl,
45 | dt,
46 | dd,
47 | ol,
48 | ul,
49 | li,
50 | fieldset,
51 | form,
52 | label,
53 | legend,
54 | table,
55 | caption,
56 | tbody,
57 | tfoot,
58 | thead,
59 | tr,
60 | th,
61 | td,
62 | article,
63 | aside,
64 | canvas,
65 | details,
66 | embed,
67 | figure,
68 | figcaption,
69 | footer,
70 | header,
71 | hgroup,
72 | menu,
73 | nav,
74 | output,
75 | ruby,
76 | section,
77 | summary,
78 | time,
79 | mark,
80 | audio,
81 | video {
82 | margin: 0;
83 | padding: 0;
84 | border: 0;
85 | font-size: 100%;
86 | font: inherit;
87 | vertical-align: baseline;
88 | box-sizing: border-box;
89 | }
90 | /* HTML5 display-role reset for older browsers */
91 | article,
92 | aside,
93 | details,
94 | figcaption,
95 | figure,
96 | footer,
97 | header,
98 | hgroup,
99 | menu,
100 | nav,
101 | section {
102 | display: block;
103 | }
104 | body {
105 | line-height: 1;
106 | }
107 | ol,
108 | ul {
109 | list-style: none;
110 | }
111 | blockquote,
112 | q {
113 | quotes: none;
114 | }
115 | blockquote:before,
116 | blockquote:after,
117 | q:before,
118 | q:after {
119 | content: '';
120 | content: none;
121 | }
122 | table {
123 | border-collapse: collapse;
124 | border-spacing: 0;
125 | }
126 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fe-project-base",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "dev": "vite",
6 | "build": "tsc && vite build",
7 | "build:dev": "tsc && vite build -m qa",
8 | "serve": "vite preview"
9 | },
10 | "husky": {
11 | "hooks": {
12 | "pre-commit": "lint-staged"
13 | }
14 | },
15 | "lint-staged": {
16 | "src/**/*.{ts,tsx}": [
17 | "eslint --cache --fix",
18 | "git add"
19 | ],
20 | "src/**/*.{js,jsx}": [
21 | "eslint --cache --fix",
22 | "git add"
23 | ]
24 | },
25 | "dependencies": {
26 | "@loadable/component": "^5.14.1",
27 | "@vitejs/plugin-legacy": "^1.3.2",
28 | "classnames": "^2.2.6",
29 | "indexof": "^0.0.1",
30 | "js-cookie": "^2.2.1",
31 | "mobx": "^6.1.7",
32 | "mobx-persist": "^0.4.1",
33 | "mobx-react": "^7.1.0",
34 | "react": "^17.0.0",
35 | "react-dom": "^17.0.0",
36 | "react-router": "^5.2.0",
37 | "react-router-config": "^5.1.1",
38 | "react-router-dom": "^5.2.0"
39 | },
40 | "devDependencies": {
41 | "@types/babel__core": "^7.1.14",
42 | "@types/ejs": "^3.0.6",
43 | "@types/html-minifier-terser": "^5.1.1",
44 | "@types/loadable__component": "^5.13.3",
45 | "@types/node": "^14.14.35",
46 | "@types/react": "^17.0.0",
47 | "@types/react-dom": "^17.0.0",
48 | "@types/react-router-config": "^5.0.2",
49 | "@types/react-router-dom": "^5.1.7",
50 | "@typescript-eslint/eslint-plugin": "^4.18.0",
51 | "@typescript-eslint/parser": "^4.18.0",
52 | "@vitejs/plugin-react-refresh": "^1.3.1",
53 | "babel-eslint": "^10.1.0",
54 | "dotenv": "^8.2.0",
55 | "eslint": "^7.22.0",
56 | "eslint-config-alloy": "^3.10.0",
57 | "eslint-plugin-react": "^7.22.0",
58 | "husky": "^4.3.8",
59 | "less": "^4.1.1",
60 | "lint-staged": "^10.5.4",
61 | "postcss": "^8.2.8",
62 | "postcss-focus": "^5.0.1",
63 | "rollup-plugin-visualizer": "^5.3.6",
64 | "typescript": "^4.2.3",
65 | "vite": "^2.1.5",
66 | "vite-plugin-html": "^2.0.3",
67 | "vite-plugin-imp": "^2.0.7"
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { ConfigEnv, UserConfigExport, Plugin, optimizeDeps } from 'vite'
2 | import reactRefresh from '@vitejs/plugin-react-refresh'
3 | import legacy from '@vitejs/plugin-legacy'
4 | import vitePluginImp from 'vite-plugin-imp'
5 | import visualizer from 'rollup-plugin-visualizer'
6 | import path from 'path'
7 | import fs from 'fs'
8 | import dotenv from 'dotenv'
9 | import { minifyHtml } from 'vite-plugin-html'
10 |
11 | const config: UserConfigExport = {
12 | plugins: [
13 | reactRefresh(),
14 | legacy({
15 | targets: ['Android >= 39', 'Chrome >= 39', 'Safari >= 10.1', 'iOS >= 10', '> 0.5%'],
16 | polyfills: ['es.promise', 'regenerator-runtime']
17 | }),
18 | vitePluginImp({
19 | libList: [
20 | {
21 | libName: 'antd-mobile',
22 | style: (name) => `antd-mobile/es/${name}/style`,
23 | libDirectory: 'es'
24 | }
25 | ]
26 | })
27 | ],
28 | resolve: {
29 | alias: [
30 | {
31 | find: /@\//,
32 | replacement: path.join(__dirname, './src/')
33 | }
34 | ]
35 | },
36 | css: {
37 | preprocessorOptions: {
38 | less: {
39 | // 支持内联 JavaScript
40 | javascriptEnabled: true,
41 | // antd 定制主题样式
42 | modifyVars: {
43 | '@fill-body': '#fff'
44 | }
45 | }
46 | },
47 | modules: {
48 | localsConvention: 'camelCase'
49 | }
50 | }
51 | }
52 |
53 | export default ({ command, mode }: ConfigEnv) => {
54 | const envFiles = [
55 | /** mode local file */ `.env.${mode}.local`,
56 | /** mode file */ `.env.${mode}`,
57 | /** local file */ `.env.local`,
58 | /** default file */ `.env`
59 | ]
60 | const { plugins = [], build = {} } = config
61 | const { rollupOptions = {} } = build
62 |
63 | for (const file of envFiles) {
64 | try {
65 | fs.accessSync(file, fs.constants.F_OK)
66 | const envConfig = dotenv.parse(fs.readFileSync(file))
67 | for (const k in envConfig) {
68 | if (Object.prototype.hasOwnProperty.call(envConfig, k)) {
69 | process.env[k] = envConfig[k]
70 | }
71 | }
72 | } catch (error) {
73 | console.log('配置文件不存在,忽略')
74 | }
75 | }
76 |
77 | const isBuild = command === 'build'
78 | // const base = isBuild ? process.env.VITE_STATIC_CDN : '//localhost:3000/'
79 |
80 | config.base = process.env.VITE_STATIC_CDN
81 |
82 | if (isBuild) {
83 | // 压缩 Html 插件
84 | config.plugins = [...plugins, minifyHtml()]
85 | config.define = {
86 | 'process.env.NODE_ENV': '"production"'
87 | }
88 | }
89 |
90 | if (process.env.VISUALIZER) {
91 | const { plugins = [] } = rollupOptions
92 | rollupOptions.plugins = [
93 | ...plugins,
94 | visualizer({
95 | open: true,
96 | gzipSize: true,
97 | brotliSize: true
98 | })
99 | ]
100 | }
101 |
102 | // 在这里无法使用 import.meta.env 变量
103 | if (command === 'serve') {
104 | config.server = {
105 | host: '0.0.0.0',
106 | // 反向代理
107 | proxy: {
108 | api: {
109 | target: process.env.VITE_API_HOST,
110 | changeOrigin: true,
111 | rewrite: (path: any) => path.replace(/^\/api/, '')
112 | }
113 | }
114 | }
115 | }
116 | return config
117 | }
118 |
--------------------------------------------------------------------------------