vite.config.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import type { IncomingHttpHeaders } from 'node:http';
  2. import { fileURLToPath, URL } from 'node:url';
  3. import type { Connect, Plugin } from 'vite';
  4. import { defineConfig } from 'vite';
  5. import vue from '@vitejs/plugin-vue';
  6. import { mockRoutes } from './src/mock/routes';
  7. interface MockContext {
  8. body: unknown;
  9. headers: IncomingHttpHeaders;
  10. method: string;
  11. query: Record<string, string>;
  12. url: string;
  13. }
  14. const createMockMiddleware = (): Connect.NextHandleFunction => {
  15. return async (req, res, next) => {
  16. if (!req.url || !req.method) {
  17. next();
  18. return;
  19. }
  20. const method = req.method.toUpperCase();
  21. const requestUrl = new URL(req.url, 'http://localhost');
  22. const route = mockRoutes.find((item) => {
  23. const methodMatched = item.method === method;
  24. const pathMatched =
  25. typeof item.path === 'string' ? item.path === requestUrl.pathname : item.path.test(requestUrl.pathname);
  26. return methodMatched && pathMatched;
  27. });
  28. if (!route) {
  29. next();
  30. return;
  31. }
  32. const body = await new Promise<string>((resolve, reject) => {
  33. if (method === 'GET') {
  34. resolve('');
  35. return;
  36. }
  37. let raw = '';
  38. req.on('data', (chunk: Buffer) => {
  39. raw += chunk.toString();
  40. });
  41. req.on('end', () => resolve(raw));
  42. req.on('error', reject);
  43. });
  44. let parsedBody: unknown = {};
  45. if (body) {
  46. try {
  47. parsedBody = JSON.parse(body);
  48. } catch {
  49. parsedBody = body;
  50. }
  51. }
  52. const payload = await route.handler({
  53. body: parsedBody,
  54. headers: req.headers,
  55. method,
  56. query: Object.fromEntries(requestUrl.searchParams.entries()),
  57. url: requestUrl.pathname
  58. } as MockContext);
  59. res.statusCode = 200;
  60. res.setHeader('Content-Type', 'application/json; charset=utf-8');
  61. res.end(JSON.stringify(payload));
  62. };
  63. };
  64. const mockApiPlugin = (): Plugin => {
  65. const middleware = createMockMiddleware();
  66. return {
  67. name: 'crossborder-os-mock-api',
  68. configureServer(server) {
  69. server.middlewares.use(middleware);
  70. },
  71. configurePreviewServer(server) {
  72. server.middlewares.use(middleware);
  73. }
  74. };
  75. };
  76. export default defineConfig({
  77. plugins: [vue(), mockApiPlugin()],
  78. resolve: {
  79. alias: {
  80. '@': fileURLToPath(new URL('./src', import.meta.url))
  81. }
  82. },
  83. server: {
  84. host: '0.0.0.0',
  85. port: 5173
  86. },
  87. build: {
  88. rollupOptions: {
  89. output: {
  90. manualChunks(id) {
  91. if (id.includes('node_modules/element-plus') || id.includes('@element-plus')) {
  92. return 'element-plus';
  93. }
  94. if (id.includes('node_modules/vue') || id.includes('node_modules/pinia') || id.includes('node_modules/vue-router')) {
  95. return 'vue-vendor';
  96. }
  97. }
  98. }
  99. }
  100. }
  101. });