refactor(project): @vben/vite-connect is reconfigured to support synchronization

This commit is contained in:
vben 2024-07-13 21:00:31 +08:00
parent c81ac5684c
commit e441d14fa2
20 changed files with 175 additions and 126 deletions

View File

@ -26,6 +26,7 @@
"cross-env": "^7.0.3",
"joi": "^17.13.3",
"js-yaml": "^4.1.0",
"mockjs": "^1.1.0",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
@ -36,6 +37,7 @@
"@nestjs/cli": "^10.4.2",
"@nestjs/schematics": "^10.1.2",
"@types/express": "^4.17.21",
"@types/mockjs": "^1.0.10",
"@types/node": "^20.14.10",
"nodemon": "^3.1.4",
"ts-node": "^10.9.2",

View File

@ -1,3 +1,5 @@
VITE_PORT = 5555
# spa-title
VITE_GLOB_APP_TITLE = Vben Admin Pro

View File

@ -1,12 +1,12 @@
{
"name": "@vben/web-antd",
"version": "5.0.0",
"homepage": "https://github.com/vbenjs/vue-vben-admin",
"homepage": "https://vben.pro",
"bugs": "https://github.com/vbenjs/vue-vben-admin/issues",
"repository": {
"type": "git",
"url": "git+https://github.com/vbenjs/vue-vben-admin.git",
"directory": "apps/vben-admin"
"directory": "apps/web-antd"
},
"license": "MIT",
"author": {

View File

@ -1,59 +1,33 @@
import { defineConfig, loadAndConvertEnv } from '@vben/vite-config';
import {
defaultImportmapOptions,
defineConfig,
getDefaultPwaOptions,
loadAndConvertEnv,
} from '@vben/vite-config';
export default defineConfig({
application: async ({ mode }) => {
const envConfig = await loadAndConvertEnv();
return {
export default defineConfig(async () => {
const { appTitle, port, ...envConfig } = await loadAndConvertEnv();
return {
application: {
...envConfig,
importmap: false,
importmapOptions: {
// 通过 Importmap CDN 方式引入,
// 目前只有esm.sh源兼容性好一点jspm.io对于 esm 入口要求高
defaultProvider: 'esm.sh',
importmap: [
{ name: 'vue' },
{ name: 'pinia' },
{ name: 'vue-router' },
{ name: 'vue-i18n' },
{ name: 'dayjs' },
{ name: 'vue-demi' },
],
},
importmapOptions: defaultImportmapOptions,
pwa: false,
pwaOptions: {
manifest: {
description:
'Vben Admin Pro is a modern admin dashboard template based on Vue 3. ',
icons: [
{
sizes: '192x192',
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-192.png',
type: 'image/png',
},
{
sizes: '512x512',
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-512.png',
type: 'image/png',
},
],
name: `Vben Admin Pro ${mode}`,
short_name: `Vben Admin Pro ${mode}`,
},
},
};
},
vite: {
server: {
proxy: {
'/api': {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
// 代理目标地址 - backend-mock 项目
target: 'http://localhost:5320/api',
ws: true,
pwaOptions: getDefaultPwaOptions(appTitle),
},
vite: {
server: {
port,
proxy: {
'/api': {
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
// 代理目标地址 - backend-mock 项目
target: 'http://localhost:5320/api',
ws: true,
},
},
},
},
},
};
});

View File

@ -7,10 +7,11 @@ import { defineConfig, loadEnv, mergeConfig } from 'vite';
import { loadApplicationPlugins } from '../plugins';
import { getCommonConfig } from './common';
function defineApplicationConfig(options: DefineApplicationOptions = {}) {
function defineApplicationConfig(userConfigPromise: DefineApplicationOptions) {
return defineConfig(async (config) => {
const options = await userConfigPromise?.(config);
const { command, mode } = config;
const { application = {}, vite = {} } = options;
const { application = {}, vite = {} } = options || {};
const root = process.cwd();
const isBuild = command === 'build';
const env = loadEnv(mode, root);
@ -30,9 +31,7 @@ function defineApplicationConfig(options: DefineApplicationOptions = {}) {
mode,
pwa: true,
turboConsole: false,
...(typeof application === 'function'
? await application(config)
: application),
...application,
});
const applicationConfig: UserConfig = {
@ -69,10 +68,7 @@ function defineApplicationConfig(options: DefineApplicationOptions = {}) {
await getCommonConfig(),
applicationConfig,
);
return mergeConfig(
mergedConfig,
typeof vite === 'function' ? await vite(config) : vite,
);
return mergeConfig(mergedConfig, vite);
});
}

View File

@ -9,9 +9,10 @@ import { defineLibraryConfig } from './library';
export * from './application';
export * from './library';
function defineConfig(options: DefineConfig = {}) {
const { type = 'auto', ...defineOptions } = options;
function defineConfig(
userConfigPromise?: DefineConfig,
type: 'application' | 'auto' | 'library' = 'auto',
) {
let projectType = type;
// 根据包是否存在 index.html,自动判断类型
@ -22,10 +23,10 @@ function defineConfig(options: DefineConfig = {}) {
switch (projectType) {
case 'application': {
return defineApplicationConfig(defineOptions);
return defineApplicationConfig(userConfigPromise);
}
case 'library': {
return defineLibraryConfig(defineOptions);
return defineLibraryConfig(userConfigPromise);
}
default: {
throw new Error(`Unsupported project type: ${projectType}`);

View File

@ -1,4 +1,4 @@
import type { UserConfig } from 'vite';
import type { ConfigEnv, UserConfig } from 'vite';
import type { DefineLibraryOptions } from '../typing';
@ -9,11 +9,12 @@ import { defineConfig, mergeConfig } from 'vite';
import { loadLibraryPlugins } from '../plugins';
import { getCommonConfig } from './common';
function defineLibraryConfig(options: DefineLibraryOptions = {}) {
return defineConfig(async (config) => {
function defineLibraryConfig(userConfigPromise: DefineLibraryOptions) {
return defineConfig(async (config: ConfigEnv) => {
const options = await userConfigPromise?.(config);
const { command, mode } = config;
const root = process.cwd();
const { library = {}, vite = {} } = options;
const { library = {}, vite = {} } = options || {};
const isBuild = command === 'build';
const plugins = await loadLibraryPlugins({
@ -22,7 +23,7 @@ function defineLibraryConfig(options: DefineLibraryOptions = {}) {
injectMetadata: true,
isBuild,
mode,
...(typeof library === 'function' ? await library(config) : library),
...library,
});
const { dependencies = {}, peerDependencies = {} } =
@ -52,10 +53,7 @@ function defineLibraryConfig(options: DefineLibraryOptions = {}) {
};
const commonConfig = await getCommonConfig();
const mergedConfig = mergeConfig(commonConfig, packageConfig);
return mergeConfig(
mergedConfig,
typeof vite === 'function' ? await vite(config) : vite,
);
return mergeConfig(mergedConfig, vite);
});
}

View File

@ -1,3 +1,4 @@
export * from './config';
export * from './options';
export * from './plugins';
export { loadAndConvertEnv } from './utils/env';

View File

@ -0,0 +1,42 @@
import type { Options as PwaPluginOptions } from 'vite-plugin-pwa';
import type { ImportmapPluginOptions } from './typing';
const isDevelopment = process.env.NODE_ENV === 'development';
const getDefaultPwaOptions = (name: string): Partial<PwaPluginOptions> => ({
manifest: {
description:
'Vben Admin Pro is a modern admin dashboard template based on Vue 3. ',
icons: [
{
sizes: '192x192',
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-192.png',
type: 'image/png',
},
{
sizes: '512x512',
src: 'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/pwa-icon-512.png',
type: 'image/png',
},
],
name: `${name}o${isDevelopment ? ' dev' : ''}`,
short_name: `${name}${isDevelopment ? ' dev' : ''}`,
},
});
const defaultImportmapOptions: ImportmapPluginOptions = {
// 通过 Importmap CDN 方式引入,
// 目前只有esm.sh源兼容性好一点jspm.io对于 esm 入口要求高
defaultProvider: 'esm.sh',
importmap: [
{ name: 'vue' },
{ name: 'pinia' },
{ name: 'vue-router' },
{ name: 'vue-i18n' },
{ name: 'dayjs' },
{ name: 'vue-demi' },
],
};
export { defaultImportmapOptions, getDefaultPwaOptions };

View File

@ -44,7 +44,7 @@ async function resolveMonorepoDependencies() {
async function viteMetadataPlugin(
root = process.cwd(),
): Promise<PluginOption | undefined> {
const { author, description, homepage, license, repository, version } =
const { author, description, homepage, license, version } =
await readPackageJSON(root);
const buildTime = dateUtil().format('YYYY-MM-DD HH:mm:ss');
@ -53,8 +53,6 @@ async function viteMetadataPlugin(
async config() {
const { dependencies, devDependencies } =
await resolveMonorepoDependencies();
const repositoryUrl =
typeof repository === 'object' ? repository.url : repository;
const isAuthorObject = typeof author === 'object';
const authorName = isAuthorObject ? author.name : author;
@ -73,7 +71,6 @@ async function viteMetadataPlugin(
devDependencies,
homepage,
license,
repositoryUrl,
version,
}),
},

View File

@ -91,22 +91,17 @@ interface ApplicationOptions extends ApplicationPluginOptions {}
interface LibraryOptions extends LibraryPluginOptions {}
interface DefineApplicationOptions {
application?:
| ((config: ConfigEnv) => Promise<ApplicationOptions>)
| ApplicationOptions;
vite?: ((config: ConfigEnv) => Promise<UserConfig>) | UserConfig;
}
type DefineApplicationOptions = (config?: ConfigEnv) => Promise<{
application?: ApplicationOptions;
vite?: UserConfig;
}>;
interface DefineLibraryOptions {
library?: ((config: ConfigEnv) => Promise<LibraryOptions>) | LibraryOptions;
vite?: ((config: ConfigEnv) => Promise<UserConfig>) | UserConfig;
}
type DefineLibraryOptions = (config?: ConfigEnv) => Promise<{
library?: LibraryOptions;
vite?: UserConfig;
}>;
type DefineConfig = {
type?: 'application' | 'auto' | 'library';
} & DefineApplicationOptions &
DefineLibraryOptions;
type DefineConfig = DefineApplicationOptions | DefineLibraryOptions;
export type {
ApplicationPluginOptions,

View File

@ -54,7 +54,9 @@ async function loadEnv<T = Record<string, string>>(
async function loadAndConvertEnv(
match = 'VITE_',
confFiles = getConfFiles(),
): Promise<Partial<ApplicationPluginOptions>> {
): Promise<
{ appTitle: string; port: number } & Partial<ApplicationPluginOptions>
> {
const envConfig = await loadEnv(match, confFiles);
const visualizer = envConfig.visualizer || '';
const pwa = envConfig.pwa || '';
@ -63,8 +65,10 @@ async function loadAndConvertEnv(
.split(',')
.filter((item) => ['brotli', 'gzip'].includes(item));
return {
appTitle: envConfig?.VITE_GLOB_APP_TITLE ?? 'Vben Admin Pro',
compress: !!compress,
compressTypes: compressTypes as ('brotli' | 'gzip')[],
port: Number(envConfig.VITE_PORT) || 5173,
pwa: !!pwa,
visualizer: !!visualizer,
};

View File

@ -1,3 +1,7 @@
# @vben-core/forward
该目录内的包可直接被app所引用
该目录内的包可直接被app所引用其是项目基础功能的一层抽象。允许轻微的副作用耦合如`locales`的集成。
## 注意事项
- `forward` 内的包不允许相互引用,有相互引用的情况请考虑是否放到`packages/effects`下

View File

@ -4,6 +4,8 @@ import {
type InternalAxiosRequestConfig,
} from 'axios';
const errorHandler = (res: Error) => Promise.reject(res);
class InterceptorManager {
private axiosInstance: AxiosInstance;
@ -19,7 +21,7 @@ class InterceptorManager {
) {
this.axiosInstance.interceptors.request.use(
fulfilled,
rejected || ((res) => Promise.reject(res)),
rejected || errorHandler,
);
}
@ -31,7 +33,7 @@ class InterceptorManager {
) {
this.axiosInstance.interceptors.response.use(
fulfilled,
rejected || ((res) => Promise.reject(res)),
rejected || errorHandler,
);
}
}

View File

@ -3,10 +3,20 @@
*/
const VBEN_GITHUB_URL = 'https://github.com/vbenjs/vue-vben-admin';
/**
* @zh_CN
*/
const VBEN_DOC_URL = 'https://doc.vben.pro';
/**
* @zh_CN Vben Logo
*/
const VBEN_LOGO_URL =
'https://cdn.jsdelivr.net/npm/@vbenjs/static-source@0.1.3/source/logo-v1.webp';
export { VBEN_GITHUB_URL, VBEN_LOGO_URL };
/**
* @zh_CN Vben Admin
*/
const VBEN_PREVIEW_URL = 'https://vben.pro';
export { VBEN_DOC_URL, VBEN_GITHUB_URL, VBEN_LOGO_URL, VBEN_PREVIEW_URL };

View File

@ -1,7 +1,9 @@
import { defineConfig } from '@vben/vite-config';
export default defineConfig({
vite: {
publicDir: 'src/scss-bem',
},
export default defineConfig(async () => {
return {
vite: {
publicDir: 'src/scss-bem',
},
};
});

View File

@ -2,7 +2,7 @@
`effects` 目录专门用于存放与副作用相关的代码和逻辑。如果你的包具有以下特点,建议将其放置在 `effects` 目录下:
- 使用状态管理框架 Pinia并包含处理副作用如异步操作、API 调用)的部分。
- 使用状态管理框架 `pinia`并包含处理副作用如异步操作、API 调用)的部分。
- 使用 `@vben-core/preferences` 处理用户偏好设置,涉及本地存储或浏览器缓存逻辑(如使用 `localStorage`)。
- 处理导航、页面跳转等场景,需要管理路由变化的逻辑。
- 包含与特定组件库紧密耦合或依赖大型仓库的部分。

View File

@ -3,6 +3,11 @@ import type { AboutProps, DescriptionItem } from './about';
import { h } from 'vue';
import {
VBEN_DOC_URL,
VBEN_GITHUB_URL,
VBEN_PREVIEW_URL,
} from '@vben/constants';
import { VbenLink, VbenRenderContent } from '@vben-core/shadcn-ui';
interface Props extends AboutProps {}
@ -27,7 +32,6 @@ const {
devDependencies = {},
homepage,
license,
repositoryUrl,
version,
// vite inject-metadata
// eslint-disable-next-line no-undef
@ -47,24 +51,17 @@ const vbenDescriptionItems: DescriptionItem[] = [
title: '最后构建时间',
},
{
// TODO:
content: h(VbenLink, { href: homepage }, { default: () => '点击查看' }),
title: '主页',
},
{
// TODO:
content: h(
VbenLink,
{ href: repositoryUrl },
{ default: () => '点击查看' },
),
content: h(VbenLink, { href: VBEN_DOC_URL }, { default: () => '点击查看' }),
title: '文档地址',
},
{
// TODO:
content: h(
VbenLink,
{ href: repositoryUrl },
{ href: VBEN_PREVIEW_URL },
{ default: () => '点击查看' },
),
title: '预览地址',
@ -72,7 +69,7 @@ const vbenDescriptionItems: DescriptionItem[] = [
{
content: h(
VbenLink,
{ href: repositoryUrl },
{ href: VBEN_GITHUB_URL },
{ default: () => '点击查看' },
),
title: 'Github',
@ -113,7 +110,7 @@ const devDependenciesItems = Object.keys(devDependencies).map((key) => ({
{{ title }}
</h3>
<p class="text-foreground/80 mt-3 text-sm leading-6">
<VbenLink :href="repositoryUrl">
<VbenLink :href="VBEN_GITHUB_URL">
{{ name }}
</VbenLink>
{{ description }}

View File

@ -1,16 +1,18 @@
import { defineConfig } from '@vben/vite-config';
export default defineConfig({
vite: {
build: {
lib: {
entry: {
antd: 'src/antd/index.ts',
index: 'src/index.ts',
export default defineConfig(async () => {
return {
vite: {
build: {
lib: {
entry: {
antd: 'src/antd/index.ts',
index: 'src/index.ts',
},
fileName: (_format, name) => `${name}.mjs`,
},
fileName: (_format, name) => `${name}.mjs`,
},
publicDir: 'src/bem',
},
publicDir: 'src/bem',
},
};
});

View File

@ -137,6 +137,9 @@ importers:
js-yaml:
specifier: ^4.1.0
version: 4.1.0
mockjs:
specifier: ^1.1.0
version: 1.1.0
passport:
specifier: ^0.7.0
version: 0.7.0
@ -162,6 +165,9 @@ importers:
'@types/express':
specifier: ^4.17.21
version: 4.17.21
'@types/mockjs':
specifier: ^1.0.10
version: 1.0.10
'@types/node':
specifier: ^20.14.10
version: 20.14.10
@ -3002,6 +3008,7 @@ packages:
'@ls-lint/ls-lint@2.2.3':
resolution: {integrity: sha512-ekM12jNm/7O2I/hsRv9HvYkRdfrHpiV1epVuI2NP+eTIcEgdIdKkKCs9KgQydu/8R5YXTov9aHdOgplmCHLupw==}
cpu: [x64, arm64, s390x]
os: [darwin, linux, win32]
hasBin: true
@ -3530,6 +3537,9 @@ packages:
'@types/minimist@1.2.5':
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
'@types/mockjs@1.0.10':
resolution: {integrity: sha512-SXgrhajHG7boLv6oU93CcmdDm0HYRiceuz6b+7z+/2lCJPTWDv0V5YiwFHT2ejE4bQqgSXQiVPQYPWv7LGsK1g==}
'@types/node@12.20.55':
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
@ -6710,6 +6720,10 @@ packages:
mlly@1.7.1:
resolution: {integrity: sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==}
mockjs@1.1.0:
resolution: {integrity: sha512-eQsKcWzIaZzEZ07NuEyO4Nw65g0hdWAyurVol1IPl1gahRwY+svqzfgfey8U8dahLwG44d6/RwEzuK52rSa/JQ==}
hasBin: true
modern-normalize@2.0.0:
resolution: {integrity: sha512-CxBoEVKh5U4DH3XuNbc5ONLF6dQBc8dSc7pdZ1957FGbIO5JBqGqqchhET9dTexri8/pk9xBL6+5ceOtCIp1QA==}
engines: {node: '>=6'}
@ -12254,6 +12268,8 @@ snapshots:
'@types/minimist@1.2.5': {}
'@types/mockjs@1.0.10': {}
'@types/node@12.20.55': {}
'@types/node@18.19.39':
@ -15922,6 +15938,10 @@ snapshots:
pkg-types: 1.1.3
ufo: 1.5.3
mockjs@1.1.0:
dependencies:
commander: 12.1.0
modern-normalize@2.0.0: {}
mri@1.2.0: {}