mdt-module-builder 1.0.4 → 2.0.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 +35 -0
- package/README.md +22 -9
- package/package.json +2 -2
- package/src/index.mjs +39 -52
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Все заметные изменения пакета документируются в этом файле.
|
|
4
|
+
|
|
5
|
+
Формат — [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/), версии — [Semantic Versioning](https://semver.org/lang/ru/).
|
|
6
|
+
Правила major/minor/patch для этого пакета — см. README, раздел «Версионирование»: изменения
|
|
7
|
+
контракта (имя глобала, `SHARED_EXACT`, мажор React, источник Tailwind-классов модуля) — всегда
|
|
8
|
+
major, т.к. потребители фиксируют зависимость через `^1.x` и автоматически подхватят любой minor/patch.
|
|
9
|
+
|
|
10
|
+
## [Unreleased]
|
|
11
|
+
|
|
12
|
+
### Removed
|
|
13
|
+
|
|
14
|
+
- Билдер больше не собирает Tailwind CSS модуля (`generateModuleTailwindCss`, `loadIcsPreset` —
|
|
15
|
+
удалены из пакета). Модуль перестаёт вести собственную, независимую Tailwind-сборку — источник
|
|
16
|
+
Tailwind-классов теперь один: курируемый safelist core-сборки MDT (`ui/tailwind-safelist.mjs`).
|
|
17
|
+
Причина — MP-16147: две независимые Tailwind-сборки ломали гарантию порядка CSS-правил
|
|
18
|
+
(`base` перед `variant`), из-за чего голая утилита модуля могла перебить адаптивный вариант
|
|
19
|
+
ui-kit (`.h-10` модуля поверх `.lg:h-9` из `ics-ui-kit`).
|
|
20
|
+
- Зависимость `tailwindcss` убрана из `package.json` — больше не используется пакетом.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Ломающее изменение контракта.** Модуль, собранный этой версией, требует MDT с уже подключённым
|
|
25
|
+
курируемым Tailwind-safelist (`safelist` в core-сборке). Классы, которых нет в safelist,
|
|
26
|
+
физически не применятся в рантайме модуля — добавляются в MDT по мере реальной потребности
|
|
27
|
+
(см. `ui/build_tools/tailwind-inventory.md`).
|
|
28
|
+
- Модуль-специфичная стилизация — только обычный CSS (`import "./x.css"`, без изменений в этой
|
|
29
|
+
части — `postcss-nested` + `autoprefixer` как и раньше), не Tailwind-утилиты.
|
|
30
|
+
|
|
31
|
+
## Версии до 2.0.0
|
|
32
|
+
|
|
33
|
+
Пакет публиковался (`npm run release`, без git-тега) без чейнджлога — история 1.0.0…1.0.4 не
|
|
34
|
+
восстановлена задним числом (нет надёжного источника: релизы не коммитятся в git). Ведение
|
|
35
|
+
чейнджлога начинается с этой версии.
|
package/README.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
модуля, выдавая **тот же по контракту артефакт**: один `dist/index.js` (IIFE), который при загрузке
|
|
5
5
|
через `<script>` самовыполняется и зовёт `window.MDT.registerModule`.
|
|
6
6
|
|
|
7
|
+
История изменений — [CHANGELOG.md](./CHANGELOG.md).
|
|
8
|
+
|
|
7
9
|
## Использование
|
|
8
10
|
|
|
9
11
|
В `package.json` модуля:
|
|
@@ -45,11 +47,15 @@ devtool/builder вызывают `npm run build` в репе модуля — м
|
|
|
45
47
|
тянет только used-иконки (единицы, ~КБ). Пара дублей по модулям несравнимо дешевле, чем вся lucide в MDT.
|
|
46
48
|
- **CSS** инлайнится в `index.js` (рантайм-инъекция `<style>`), как старый style-loader —
|
|
47
49
|
оверлей копирует только `index.js`, отдельного `.css` нет.
|
|
48
|
-
- **Tailwind
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
- **Tailwind модуль больше не собирает** (с версии 2.0.0, MP-16147). Раньше билдер сам генерил
|
|
51
|
+
утилиты Tailwind из `src` модуля второй, независимой сборкой — это ломало гарантию порядка
|
|
52
|
+
правил (`base` перед `variant`), на которой держится mobile-first: голая утилита модуля могла
|
|
53
|
+
перебить вариант ui-kit (`.h-10` модуля поверх `.lg:h-9` из `ics-ui-kit`). Теперь Tailwind-классы
|
|
54
|
+
модулю даёт единственная, core-сборка MDT — по курируемому `tailwind-safelist.mjs`
|
|
55
|
+
(собран из реально используемых модулями классов, см. `tailwind-inventory.mjs`). Класс, которого
|
|
56
|
+
нет в safelist, физически не применится в рантайме — не задача сборки, а несовпадение safelist;
|
|
57
|
+
добавляется в MDT по мере реальной потребности. Модуль-специфичная стилизация — обычный CSS
|
|
58
|
+
(`import "./x.css"`, см. ниже), не Tailwind.
|
|
53
59
|
|
|
54
60
|
## Совместимость исходников модуля (webpack → Vite)
|
|
55
61
|
|
|
@@ -61,7 +67,7 @@ devtool/builder вызывают `npm run build` в репе модуля — м
|
|
|
61
67
|
маппинга; `prefix/*` → wildcard с захватом хвоста, точный ключ → строковый алиас.
|
|
62
68
|
- **CSS-вложенность.** Компонентный CSS модуля (`import "./x.css"`) прогоняется через
|
|
63
69
|
`postcss-nested` (Sass-подобный `&`) + `autoprefixer` — та же семантика, что у старого
|
|
64
|
-
`postcss-loader`. Native CSS nesting не задействуется.
|
|
70
|
+
`postcss-loader`. Native CSS nesting не задействуется.
|
|
65
71
|
- **`.svg` как строка.** SVG импортится встроенным Vite-суффиксом `?raw`
|
|
66
72
|
(`import logo from "./logo.svg?raw"`) → строка с разметкой, инлайнится, без отдельного ассет-файла.
|
|
67
73
|
Байт-в-байт как старый `svg-inline-loader`. Билдер SVG специально не обрабатывает: **bare**-импорт
|
|
@@ -116,18 +122,25 @@ MDT-сторона контракта — `ui/vite-app/src/legacy/config-global.
|
|
|
116
122
|
SemVer пакета относительно платформы:
|
|
117
123
|
|
|
118
124
|
- **major** — смена контракта: имя глобала, набор `SHARED_EXACT`, **мажор React** (обновляются
|
|
119
|
-
`SHARED_NAMES`)
|
|
125
|
+
`SHARED_NAMES`), или изменение источника Tailwind-классов модуля. Модули осознанно поднимают
|
|
126
|
+
`mdt-module-builder` и проверяют совместимость.
|
|
120
127
|
- **minor/patch** — внутренние правки сборки; выходной артефакт остаётся совместимым.
|
|
121
128
|
|
|
122
129
|
| mdt-module-builder | React | Платформа MDT |
|
|
123
130
|
|---|---|---|
|
|
124
131
|
| 1.x | 19 | (заполнить при первом релизе) |
|
|
132
|
+
| 2.x | 19 | требует MDT с курируемым Tailwind-safelist (`ui/tailwind-safelist.mjs` в `safelist` core-сборки, MP-16147) — модуль больше не собирает свой Tailwind |
|
|
125
133
|
|
|
126
134
|
## Публикация
|
|
127
135
|
|
|
128
136
|
Публикуется **вручную** в публичный npm (как `mdt-client`), автопубликации в CI нет.
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
|
|
138
|
+
Перед любым релизом — перенеси `## [Unreleased]` в [CHANGELOG.md](./CHANGELOG.md) в датированную
|
|
139
|
+
секцию `## [x.y.z] - YYYY-MM-DD` (формат [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/)),
|
|
140
|
+
оставив пустой `## [Unreleased]` сверху для следующих изменений.
|
|
141
|
+
|
|
142
|
+
Версию руками в `package.json` не правим для patch — скрипт `release` сам поднимает patch (без
|
|
143
|
+
git-тега) и публикует:
|
|
131
144
|
|
|
132
145
|
```
|
|
133
146
|
cd ui/module-builder
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdt-module-builder",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Сборщик внешних UI-модулей MDT (Vite).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"src",
|
|
18
18
|
"bin",
|
|
19
19
|
"README.md",
|
|
20
|
+
"CHANGELOG.md",
|
|
20
21
|
"SHARED-DEPENDENCIES.md"
|
|
21
22
|
],
|
|
22
23
|
"engines": {
|
|
@@ -26,7 +27,6 @@
|
|
|
26
27
|
"autoprefixer": "^10.4.0",
|
|
27
28
|
"postcss": "^8.4.0",
|
|
28
29
|
"postcss-nested": "^6.2.0",
|
|
29
|
-
"tailwindcss": "^3.4.0",
|
|
30
30
|
"vite": "^6.0.0"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
package/src/index.mjs
CHANGED
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
import * as fs from "node:fs";
|
|
13
13
|
import * as os from "node:os";
|
|
14
14
|
import * as path from "node:path";
|
|
15
|
-
import { createRequire } from "node:module";
|
|
16
|
-
import { pathToFileURL } from "node:url";
|
|
17
15
|
// postcss-плагины для компонентного CSS модуля (см. css.postcss в moduleViteConfig). Оба —
|
|
18
16
|
// прямые зависимости пакета, поэтому импортим статически (нужны только при реальной сборке).
|
|
19
17
|
import autoprefixer from "autoprefixer";
|
|
@@ -57,10 +55,9 @@ export const SHARED_NAMES = {
|
|
|
57
55
|
react: "Activity,Children,Component,Fragment,Profiler,PureComponent,StrictMode,Suspense,act,cache,cacheSignal,captureOwnerStack,cloneElement,createContext,createElement,createRef,forwardRef,isValidElement,lazy,memo,startTransition,use,useActionState,useCallback,useContext,useDebugValue,useDeferredValue,useEffect,useEffectEvent,useId,useImperativeHandle,useInsertionEffect,useLayoutEffect,useMemo,useOptimistic,useReducer,useRef,useState,useSyncExternalStore,useTransition,version".split(
|
|
58
56
|
","
|
|
59
57
|
),
|
|
60
|
-
"react-dom":
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
),
|
|
58
|
+
"react-dom": "createPortal,flushSync,preconnect,prefetchDNS,preinit,preinitModule,preload,preloadModule,requestFormReset,unstable_batchedUpdates,useFormState,useFormStatus,version".split(
|
|
59
|
+
","
|
|
60
|
+
),
|
|
64
61
|
"react-dom/client": ["createRoot", "hydrateRoot", "version"],
|
|
65
62
|
"react/jsx-runtime": ["Fragment", "jsx", "jsxs"],
|
|
66
63
|
"react/jsx-dev-runtime": ["Fragment", "jsxDEV"]
|
|
@@ -96,7 +93,9 @@ function sharedAliases(shimDir) {
|
|
|
96
93
|
// Толерантный парсер tsconfig (JSONC): вырезаем // и /* */ комментарии (не трогая их внутри строк)
|
|
97
94
|
// и висячие запятые, затем JSON.parse.
|
|
98
95
|
function parseJsonc(text) {
|
|
99
|
-
const noComments = text.replace(/("(?:\\.|[^"\\])*")|\/\/[^\n\r]*|\/\*[\s\S]*?\*\//g, (_m, str) =>
|
|
96
|
+
const noComments = text.replace(/("(?:\\.|[^"\\])*")|\/\/[^\n\r]*|\/\*[\s\S]*?\*\//g, (_m, str) =>
|
|
97
|
+
str ? str : ""
|
|
98
|
+
);
|
|
100
99
|
return JSON.parse(noComments.replace(/,(\s*[}\]])/g, "$1"));
|
|
101
100
|
}
|
|
102
101
|
|
|
@@ -124,7 +123,10 @@ function tsconfigAliases(root) {
|
|
|
124
123
|
if (!target) continue;
|
|
125
124
|
if (pattern.endsWith("/*") && target.endsWith("/*")) {
|
|
126
125
|
const replBase = path.resolve(baseDir, target.slice(0, -2)).replace(/\\/g, "/");
|
|
127
|
-
aliases.push({
|
|
126
|
+
aliases.push({
|
|
127
|
+
find: new RegExp(`^${escapeRegExp(pattern.slice(0, -2))}/(.*)$`),
|
|
128
|
+
replacement: `${replBase}/$1`
|
|
129
|
+
});
|
|
128
130
|
} else {
|
|
129
131
|
aliases.push({ find: pattern, replacement: path.resolve(baseDir, target) });
|
|
130
132
|
}
|
|
@@ -145,45 +147,16 @@ function globalRef(id) {
|
|
|
145
147
|
: `globalThis.__mdtShared[${JSON.stringify(id)}]`;
|
|
146
148
|
}
|
|
147
149
|
|
|
148
|
-
// Tailwind для модуля (вариант A): билдер сам генерит утилиты ТОЛЬКО из исходников модуля.
|
|
149
|
-
// preflight и токены даёт MDT глобально, поэтому здесь preflight выключен и эмитятся лишь
|
|
150
|
-
// `@tailwind utilities`. Пресет берём из ics-ui-kit самого модуля (фолбэк — ics-ui-kit билдера,
|
|
151
|
-
// чтобы dev-стенд работал даже до npm install в модуле) → те же утилиты/токены, что в MDT.
|
|
152
|
-
async function loadIcsPreset(root) {
|
|
153
|
-
for (const base of [path.join(root, "package.json"), import.meta.url]) {
|
|
154
|
-
try {
|
|
155
|
-
const resolved = createRequire(base).resolve("ics-ui-kit/tailwind.preset");
|
|
156
|
-
const mod = await import(pathToFileURL(resolved).href);
|
|
157
|
-
return mod.default ?? mod;
|
|
158
|
-
} catch {
|
|
159
|
-
// пробуем следующий источник
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return undefined;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Генерит CSS утилит Tailwind, найденных в исходниках модуля. Зависимости подключаем лениво:
|
|
166
|
-
// они есть у MDT (dev) и у mdt-module-builder (CI модуля), но не нужны для `--list`/импорта ядра.
|
|
167
|
-
async function generateModuleTailwindCss(root) {
|
|
168
|
-
const [{ default: postcss }, { default: tailwindcss }, { default: autoprefixer }] = await Promise.all([
|
|
169
|
-
import("postcss"),
|
|
170
|
-
import("tailwindcss"),
|
|
171
|
-
import("autoprefixer")
|
|
172
|
-
]);
|
|
173
|
-
const content = path.join(root, "src").replace(/\\/g, "/") + "/**/*.{ts,tsx,js,jsx,html}";
|
|
174
|
-
const preset = await loadIcsPreset(root);
|
|
175
|
-
const config = { presets: preset ? [preset] : [], content: [content], corePlugins: { preflight: false } };
|
|
176
|
-
const { css } = await postcss([tailwindcss(config), autoprefixer()]).process("@tailwind utilities;\n", { from: undefined });
|
|
177
|
-
return css;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
150
|
// Инлайнит собранный CSS в JS-чанк (рантайм-инъекция <style>) — как старый webpack/style-loader:
|
|
181
|
-
// оверлей копирует только index.js, отдельного css-файла нет.
|
|
182
|
-
|
|
151
|
+
// оверлей копирует только index.js, отдельного css-файла нет. Модуль больше не собирает свой
|
|
152
|
+
// Tailwind (MP-16147, Шаг 3): здесь только компонентный CSS модуля (import "./x.css",
|
|
153
|
+
// postcss-nested + autoprefixer, см. css.postcss в moduleViteConfig). Tailwind-утилиты модулю
|
|
154
|
+
// больше не нужны — они приходят из курируемого safelist core-сборки MDT (ui/tailwind-safelist.mjs).
|
|
155
|
+
function cssInjectPlugin() {
|
|
183
156
|
return {
|
|
184
157
|
name: "mdt-css-inject",
|
|
185
158
|
enforce: "post",
|
|
186
|
-
|
|
159
|
+
generateBundle(_opts, bundle) {
|
|
187
160
|
let css = "";
|
|
188
161
|
for (const [file, chunk] of Object.entries(bundle)) {
|
|
189
162
|
if (chunk.type === "asset" && file.endsWith(".css")) {
|
|
@@ -191,7 +164,6 @@ function cssInjectPlugin(root) {
|
|
|
191
164
|
delete bundle[file];
|
|
192
165
|
}
|
|
193
166
|
}
|
|
194
|
-
css += await generateModuleTailwindCss(root);
|
|
195
167
|
if (!css) return;
|
|
196
168
|
const inject = `(function(){try{var s=document.createElement("style");s.textContent=${JSON.stringify(
|
|
197
169
|
css
|
|
@@ -214,12 +186,27 @@ export function moduleViteConfig({ root, entry, outDir, watch = false, name = "_
|
|
|
214
186
|
configFile: false,
|
|
215
187
|
root,
|
|
216
188
|
logLevel: "warn",
|
|
189
|
+
// Библиотеки, которые бандлятся ВНУТРЬ модуля (react-virtual и др.), метят dev-ветки через
|
|
190
|
+
// `process.env.NODE_ENV` — де-факто стандарт npm (так же устроен entry самого React). Это
|
|
191
|
+
// маркер для сборщика, а не рантайм-чтение: он должен подставить литерал и стрипнуть ветку.
|
|
192
|
+
// В lib-режиме Vite такую подстановку сознательно пропускает (`isBuildLib`,
|
|
193
|
+
// src/node/plugins/define.ts) — рассчитывает, что артефакт дособерёт бандлер потребителя.
|
|
194
|
+
// У нас его нет: MDT грузит index.js как <script>, а `process` в браузере не существует →
|
|
195
|
+
// ReferenceError в момент первого исполнения dev-ветки (сам модуль при этом грузится
|
|
196
|
+
// нормально — проверки лежат внутри функций). Делаем подстановку явно: NODE_ENV="production" (стрипает
|
|
197
|
+
// dev-ветки), плюс `process.env` → {} как фолбэк для прочих `process.env.X`.
|
|
198
|
+
// Ключи Vite матчит по длине (NODE_ENV раньше env).
|
|
199
|
+
define: {
|
|
200
|
+
"process.env.NODE_ENV": JSON.stringify("production"),
|
|
201
|
+
"process.env": "{}"
|
|
202
|
+
},
|
|
217
203
|
// react/*-шимы + tsconfig `paths` модуля (напр. "_core/*") — иначе Vite их не резолвит.
|
|
218
204
|
resolve: { alias: [...sharedAliases(shimDir), ...tsconfigAliases(root)] },
|
|
219
|
-
plugins: [cssInjectPlugin(
|
|
205
|
+
plugins: [cssInjectPlugin()],
|
|
220
206
|
// Компонентный CSS модуля (import "./x.css") гоняем через postcss-nested (Sass-подобная
|
|
221
207
|
// вложенность `&`, как старый webpack builder) + autoprefixer. Инлайн-инъекцию делает
|
|
222
|
-
// cssInjectPlugin
|
|
208
|
+
// cssInjectPlugin. Tailwind-утилиты модуль больше не собирает (MP-16147, Шаг 3) — приходят
|
|
209
|
+
// из курируемого safelist core-сборки MDT.
|
|
223
210
|
css: { postcss: { plugins: [postcssNested(), autoprefixer()] } },
|
|
224
211
|
build: {
|
|
225
212
|
outDir,
|
|
@@ -230,12 +217,12 @@ export function moduleViteConfig({ root, entry, outDir, watch = false, name = "_
|
|
|
230
217
|
// externalize (инстанс даёт MDT через globalThis.__mdtShared, в модуль НЕ бандлятся): SHARED_GLOBALS
|
|
231
218
|
// (точные спецификаторы) + ics-ui-kit с сабпасами (SHARED_PREFIXES). react/* — alias-шимы; lucide бандлится.
|
|
232
219
|
external: (id) => SHARED_GLOBALS.includes(id) || isSharedPrefix(id) || id.startsWith(MDT_SDK_PREFIX),
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
220
|
+
// host кладёт значения в __mdtShared/__mdtSdk с флагом __esModule, поэтому
|
|
221
|
+
// interop берёт `.default` для default-импорта. rolldown (dev) делает это сам (__toESM),
|
|
222
|
+
// а Rollup (Vite 6, CI модуля) — только с output.interop:"auto"; без него default-импорт
|
|
223
|
+
// биндится ко всему объекту-неймспейсу вместо .default (MDT.Navigation === undefined,
|
|
224
|
+
// echarts-for-react → «Element type is invalid … got: object»).
|
|
225
|
+
output: { globals: globalRef, interop: "auto" }
|
|
239
226
|
},
|
|
240
227
|
lib: {
|
|
241
228
|
entry,
|