@application-kit/nestjs-vite 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @application-kit/nestjs-vite
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ed011f8: `defineApplicationViteConfig({ root, appPath, clientHtml, environment, plugins, buildPlugins })` во входе `/vite-plugin`
8
+ (и в корне) — весь `vite.config` Nest-SSR-приложения объектом. Контракт выходных имён: серверные входы `[name].mjs` и
9
+ чанки `[hash].mjs` в корне `dist`, клиент — `assets/[hash].js`, ассеты — `assets/[hash][extname]`, карт нет. Серверную
10
+ сборку отличает `--ssr` в `process.argv`; порты dev-сервера и HMR — из `environment`. Плагины клиента и плагины только
11
+ сборки приходят параметрами, зависимостей у пакета не прибавилось.
12
+
3
13
  ## 0.3.0
4
14
 
5
15
  ### Minor Changes
package/README.md CHANGED
@@ -26,6 +26,49 @@ export default defineConfig({
26
26
  статическими расширениями и внутренние пути Vite уходят в Vite, остальные — в Nest; при
27
27
  горячем обновлении приложение пересоздаётся.
28
28
 
29
+ ## Vite-конфиг приложения
30
+
31
+ `defineApplicationViteConfig(options)` из `@application-kit/nestjs-vite/vite-plugin` — весь `vite.config`
32
+ Nest-SSR-приложения: dev-сервер Nest (`vitePluginNode`), серверные входы `vite build --ssr <вход>` и клиентская сборка
33
+ в один `dist`.
34
+
35
+ ```ts
36
+ // vite.config.mts
37
+ import { defineApplicationViteConfig } from '@application-kit/nestjs-vite/vite-plugin'
38
+
39
+ export default defineApplicationViteConfig({
40
+ appPath: path.resolve(import.meta.dirname, 'src/create-web-application.ts'),
41
+ buildPlugins: [cleanup()],
42
+ clientHtml: path.resolve(import.meta.dirname, 'src/client/index.html'),
43
+ environment: process.env,
44
+ plugins: [vue(), htmlMinifier({ minify: true })],
45
+ root: import.meta.dirname,
46
+ })
47
+ ```
48
+
49
+ - Конфиг — объект, а не функция: `vitest.config` приложения мержит его как объект. Серверную сборку отличает флаг
50
+ `--ssr` в `process.argv` в момент вызова.
51
+ - Пресет не знает о фреймворке клиента: его плагины, обработка HTML и script-теги модулей приходят в `plugins` (после
52
+ плагина Nest), плагины только сборки (rolldown) — в `buildPlugins`.
53
+ - Окружение: `PORT` (dev-сервер, 3000), `VITE_SERVER_HMR_PORT` и `VITE_SERVER_HMR_CLIENT_PORT` (HMR, 3001), `NODE_ENV=test`
54
+ выключает прогрев клиентского графа — в e2e браузера нет, а SSR-запросы ждали бы этот фон.
55
+ - Алиас `@` — `<root>/src`; `optimizeDeps` — `pino` без автопоиска; логгер Vite без предупреждений «Sourcemap for …» о
56
+ картах зависимостей.
57
+
58
+ Контракт выходных имён — на него опираются команды запуска, образ и раздача статики приложения:
59
+
60
+ | Что | Имя |
61
+ |---|---|
62
+ | серверный вход (`web`, `cli`, `consumer`, `tracing`, `ormconfig`, …) | `dist/[name].mjs` — без хеша, запускается по имени |
63
+ | серверный чанк | `dist/[hash].mjs` |
64
+ | клиентский вход и чанки | `dist/assets/[hash].js` |
65
+ | ассеты | `dist/assets/[hash][extname]` |
66
+ | карты `*.map` | нет |
67
+
68
+ Серверный код — `.mjs`: в `dist` нет `package.json` с `"type": "module"`, и `.js` Node прочёл бы как CommonJS. Клиент
69
+ лежит только под `assets/`: каталог отдаётся наружу с вечным кешем, имена контент-адресные, серверного кода и карт в нём
70
+ нет.
71
+
29
72
  ## SSR-страница
30
73
 
31
74
  ```ts
@@ -0,0 +1,16 @@
1
+ import type { BuildOptions, PluginOption } from 'vite';
2
+ export interface ApplicationViteConfigOptionsInterface {
3
+ appPath: string;
4
+ buildPlugins?: BuildPluginsType;
5
+ clientHtml: string;
6
+ environment: ApplicationViteEnvironmentInterface;
7
+ plugins: PluginOption[];
8
+ root: string;
9
+ }
10
+ export interface ApplicationViteEnvironmentInterface {
11
+ NODE_ENV?: string;
12
+ PORT?: string;
13
+ VITE_SERVER_HMR_CLIENT_PORT?: string;
14
+ VITE_SERVER_HMR_PORT?: string;
15
+ }
16
+ export type BuildPluginsType = NonNullable<NonNullable<BuildOptions['rolldownOptions']>['plugins']>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ import type { UserConfig } from 'vite';
2
+ import type { ApplicationViteConfigOptionsInterface } from './application-vite-config-options.interface.js';
3
+ export declare const defineApplicationViteConfig: (options: ApplicationViteConfigOptionsInterface) => UserConfig;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.defineApplicationViteConfig = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const node_process_1 = __importDefault(require("node:process"));
9
+ const vite_1 = require("vite");
10
+ const vite_plugin_node_js_1 = require("./vite-plugin-node.js");
11
+ const CLIENT_ENTRY = 'assets/main';
12
+ const DEV_SERVER_PORT = 3000;
13
+ const HMR_PORT = 3001;
14
+ const SOURCEMAP_WARNING = 'Sourcemap for';
15
+ const VENDOR_GROUP = /\/node_modules\/(?<group>[\w\-@]*)/u;
16
+ const vendorGroupName = (moduleId) => {
17
+ const match = VENDOR_GROUP.exec(moduleId);
18
+ return match?.groups ? match.groups.group : 'unknown';
19
+ };
20
+ const outputOf = (isServerBuild) => ({
21
+ assetFileNames: 'assets/[hash][extname]',
22
+ chunkFileNames: isServerBuild ? '[hash].mjs' : 'assets/[hash].js',
23
+ codeSplitting: {
24
+ groups: [
25
+ { name: 'layout', test: /layouts/u },
26
+ { maxSize: 200_000, minSize: 100_000, name: vendorGroupName, priority: 10, test: /node_modules/u },
27
+ ],
28
+ },
29
+ comments: false,
30
+ dir: './dist',
31
+ entryFileNames: (chunk) => (chunk.name === CLIENT_ENTRY ? 'assets/[hash].js' : '[name].mjs'),
32
+ format: 'esm',
33
+ hashCharacters: 'base36',
34
+ minifyInternalExports: false,
35
+ });
36
+ const buildOf = (options, isServerBuild) => ({
37
+ chunkSizeWarningLimit: 400,
38
+ emptyOutDir: false,
39
+ manifest: true,
40
+ minify: false,
41
+ rolldownOptions: {
42
+ input: { [CLIENT_ENTRY]: options.clientHtml },
43
+ output: outputOf(isServerBuild),
44
+ plugins: options.buildPlugins ?? [],
45
+ },
46
+ sourcemap: false,
47
+ });
48
+ const portOf = (value, fallback) => Number(value) || fallback;
49
+ const serverOf = (environment) => ({
50
+ allowedHosts: true,
51
+ hmr: {
52
+ clientPort: portOf(environment.VITE_SERVER_HMR_CLIENT_PORT, HMR_PORT),
53
+ port: portOf(environment.VITE_SERVER_HMR_PORT, HMR_PORT),
54
+ },
55
+ host: '0.0.0.0',
56
+ middlewareMode: false,
57
+ port: portOf(environment.PORT, DEV_SERVER_PORT),
58
+ preTransformRequests: environment.NODE_ENV !== 'test',
59
+ strictPort: true,
60
+ watch: {
61
+ ignored: ['**/*.gql', 'reports/**/*'],
62
+ interval: 400,
63
+ usePolling: true,
64
+ },
65
+ });
66
+ const createApplicationLogger = () => {
67
+ const logger = (0, vite_1.createLogger)();
68
+ const warnOnce = logger.warnOnce.bind(logger);
69
+ logger.warnOnce = (message, options) => {
70
+ if (!message.includes(SOURCEMAP_WARNING)) {
71
+ warnOnce(message, options);
72
+ }
73
+ };
74
+ return logger;
75
+ };
76
+ const defineApplicationViteConfig = (options) => {
77
+ const isServerBuild = node_process_1.default.argv.includes('--ssr');
78
+ return {
79
+ appType: 'custom',
80
+ build: buildOf(options, isServerBuild),
81
+ customLogger: createApplicationLogger(),
82
+ optimizeDeps: { include: ['pino'], noDiscovery: true },
83
+ plugins: [...(0, vite_plugin_node_js_1.vitePluginNode)({ appPath: options.appPath }), ...options.plugins],
84
+ resolve: { alias: { '@': node_path_1.default.resolve(options.root, 'src') } },
85
+ root: node_path_1.default.resolve(options.root),
86
+ server: serverOf(options.environment),
87
+ };
88
+ };
89
+ exports.defineApplicationViteConfig = defineApplicationViteConfig;
@@ -1,4 +1,6 @@
1
+ export * from './application-vite-config-options.interface.js';
1
2
  export * from './create-middleware.js';
3
+ export * from './define-application-vite-config.js';
2
4
  export * from './nest-handler.js';
3
5
  export * from './plugin-config.interface.js';
4
6
  export * from './vite-plugin-node.js';
@@ -14,7 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./application-vite-config-options.interface.js"), exports);
17
18
  __exportStar(require("./create-middleware.js"), exports);
19
+ __exportStar(require("./define-application-vite-config.js"), exports);
18
20
  __exportStar(require("./nest-handler.js"), exports);
19
21
  __exportStar(require("./plugin-config.interface.js"), exports);
20
22
  __exportStar(require("./vite-plugin-node.js"), exports);
@@ -0,0 +1,16 @@
1
+ import type { BuildOptions, PluginOption } from 'vite';
2
+ export interface ApplicationViteConfigOptionsInterface {
3
+ appPath: string;
4
+ buildPlugins?: BuildPluginsType;
5
+ clientHtml: string;
6
+ environment: ApplicationViteEnvironmentInterface;
7
+ plugins: PluginOption[];
8
+ root: string;
9
+ }
10
+ export interface ApplicationViteEnvironmentInterface {
11
+ NODE_ENV?: string;
12
+ PORT?: string;
13
+ VITE_SERVER_HMR_CLIENT_PORT?: string;
14
+ VITE_SERVER_HMR_PORT?: string;
15
+ }
16
+ export type BuildPluginsType = NonNullable<NonNullable<BuildOptions['rolldownOptions']>['plugins']>;
@@ -0,0 +1,3 @@
1
+ import type { UserConfig } from 'vite';
2
+ import type { ApplicationViteConfigOptionsInterface } from './application-vite-config-options.interface.js';
3
+ export declare const defineApplicationViteConfig: (options: ApplicationViteConfigOptionsInterface) => UserConfig;
@@ -0,0 +1,82 @@
1
+ import path from 'node:path';
2
+ import process from 'node:process';
3
+ import { createLogger } from 'vite';
4
+ import { vitePluginNode } from './vite-plugin-node.js';
5
+ const CLIENT_ENTRY = 'assets/main';
6
+ const DEV_SERVER_PORT = 3000;
7
+ const HMR_PORT = 3001;
8
+ const SOURCEMAP_WARNING = 'Sourcemap for';
9
+ const VENDOR_GROUP = /\/node_modules\/(?<group>[\w\-@]*)/u;
10
+ const vendorGroupName = (moduleId) => {
11
+ const match = VENDOR_GROUP.exec(moduleId);
12
+ return match?.groups ? match.groups.group : 'unknown';
13
+ };
14
+ const outputOf = (isServerBuild) => ({
15
+ assetFileNames: 'assets/[hash][extname]',
16
+ chunkFileNames: isServerBuild ? '[hash].mjs' : 'assets/[hash].js',
17
+ codeSplitting: {
18
+ groups: [
19
+ { name: 'layout', test: /layouts/u },
20
+ { maxSize: 200_000, minSize: 100_000, name: vendorGroupName, priority: 10, test: /node_modules/u },
21
+ ],
22
+ },
23
+ comments: false,
24
+ dir: './dist',
25
+ entryFileNames: (chunk) => (chunk.name === CLIENT_ENTRY ? 'assets/[hash].js' : '[name].mjs'),
26
+ format: 'esm',
27
+ hashCharacters: 'base36',
28
+ minifyInternalExports: false,
29
+ });
30
+ const buildOf = (options, isServerBuild) => ({
31
+ chunkSizeWarningLimit: 400,
32
+ emptyOutDir: false,
33
+ manifest: true,
34
+ minify: false,
35
+ rolldownOptions: {
36
+ input: { [CLIENT_ENTRY]: options.clientHtml },
37
+ output: outputOf(isServerBuild),
38
+ plugins: options.buildPlugins ?? [],
39
+ },
40
+ sourcemap: false,
41
+ });
42
+ const portOf = (value, fallback) => Number(value) || fallback;
43
+ const serverOf = (environment) => ({
44
+ allowedHosts: true,
45
+ hmr: {
46
+ clientPort: portOf(environment.VITE_SERVER_HMR_CLIENT_PORT, HMR_PORT),
47
+ port: portOf(environment.VITE_SERVER_HMR_PORT, HMR_PORT),
48
+ },
49
+ host: '0.0.0.0',
50
+ middlewareMode: false,
51
+ port: portOf(environment.PORT, DEV_SERVER_PORT),
52
+ preTransformRequests: environment.NODE_ENV !== 'test',
53
+ strictPort: true,
54
+ watch: {
55
+ ignored: ['**/*.gql', 'reports/**/*'],
56
+ interval: 400,
57
+ usePolling: true,
58
+ },
59
+ });
60
+ const createApplicationLogger = () => {
61
+ const logger = createLogger();
62
+ const warnOnce = logger.warnOnce.bind(logger);
63
+ logger.warnOnce = (message, options) => {
64
+ if (!message.includes(SOURCEMAP_WARNING)) {
65
+ warnOnce(message, options);
66
+ }
67
+ };
68
+ return logger;
69
+ };
70
+ export const defineApplicationViteConfig = (options) => {
71
+ const isServerBuild = process.argv.includes('--ssr');
72
+ return {
73
+ appType: 'custom',
74
+ build: buildOf(options, isServerBuild),
75
+ customLogger: createApplicationLogger(),
76
+ optimizeDeps: { include: ['pino'], noDiscovery: true },
77
+ plugins: [...vitePluginNode({ appPath: options.appPath }), ...options.plugins],
78
+ resolve: { alias: { '@': path.resolve(options.root, 'src') } },
79
+ root: path.resolve(options.root),
80
+ server: serverOf(options.environment),
81
+ };
82
+ };
@@ -1,4 +1,6 @@
1
+ export * from './application-vite-config-options.interface.js';
1
2
  export * from './create-middleware.js';
3
+ export * from './define-application-vite-config.js';
2
4
  export * from './nest-handler.js';
3
5
  export * from './plugin-config.interface.js';
4
6
  export * from './vite-plugin-node.js';
@@ -1,4 +1,6 @@
1
+ export * from './application-vite-config-options.interface.js';
1
2
  export * from './create-middleware.js';
3
+ export * from './define-application-vite-config.js';
2
4
  export * from './nest-handler.js';
3
5
  export * from './plugin-config.interface.js';
4
6
  export * from './vite-plugin-node.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@application-kit/nestjs-vite",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Мост Vite ↔ NestJS для SSR: dev-обвязка, загрузка HTML и ssr-entry",
5
5
  "keywords": [
6
6
  "nestjs",