nyte 1.2.4 → 1.2.6
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/dist/builder.d.ts +3 -3
- package/dist/builder.js +339 -357
- package/dist/client/DefaultNotFound.js +3 -3
- package/package.json +28 -22
- package/src/builder.js +347 -372
- package/src/client/DefaultNotFound.tsx +19 -4
package/dist/builder.js
CHANGED
|
@@ -15,59 +15,23 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
const {
|
|
19
|
-
const react = require('@vitejs/plugin-react');
|
|
18
|
+
const { rollup, watch: rollupWatch } = require('rollup');
|
|
20
19
|
const path = require('path');
|
|
21
20
|
const Console = require("./api/console").default;
|
|
22
21
|
const fs = require('fs');
|
|
23
22
|
const { readdir, stat } = require("node:fs/promises");
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
// Plugins Oficiais do Rollup
|
|
24
|
+
const nodeResolve = require('@rollup/plugin-node-resolve').default;
|
|
25
|
+
const commonjs = require('@rollup/plugin-commonjs').default;
|
|
26
|
+
const replace = require('@rollup/plugin-replace').default;
|
|
27
|
+
const esbuild = require('rollup-plugin-esbuild').default;
|
|
28
|
+
// Lista de módulos nativos do Node.js
|
|
26
29
|
const nodeBuiltIns = [
|
|
27
30
|
'assert', 'buffer', 'child_process', 'cluster', 'crypto', 'dgram', 'dns',
|
|
28
31
|
'domain', 'events', 'fs', 'http', 'https', 'net', 'os', 'path', 'punycode',
|
|
29
32
|
'querystring', 'readline', 'stream', 'string_decoder', 'tls', 'tty', 'url',
|
|
30
33
|
'util', 'v8', 'vm', 'zlib', 'module', 'worker_threads', 'perf_hooks'
|
|
31
34
|
];
|
|
32
|
-
/**
|
|
33
|
-
* Plugin para replicar o comportamento de Aliases do TSConfig
|
|
34
|
-
*/
|
|
35
|
-
const customAliasPlugin = () => {
|
|
36
|
-
return {
|
|
37
|
-
name: 'custom-tsconfig-paths',
|
|
38
|
-
config(config) {
|
|
39
|
-
const projectDir = process.cwd();
|
|
40
|
-
const tsconfigPath = path.join(projectDir, 'tsconfig.json');
|
|
41
|
-
let aliasMap = {};
|
|
42
|
-
if (fs.existsSync(tsconfigPath)) {
|
|
43
|
-
try {
|
|
44
|
-
const tsconfigContent = fs.readFileSync(tsconfigPath, 'utf8');
|
|
45
|
-
const jsonContent = tsconfigContent.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, '');
|
|
46
|
-
const tsconfig = JSON.parse(jsonContent);
|
|
47
|
-
if (tsconfig.compilerOptions?.paths) {
|
|
48
|
-
const baseUrl = tsconfig.compilerOptions.baseUrl || '.';
|
|
49
|
-
const basePath = path.resolve(projectDir, baseUrl);
|
|
50
|
-
for (const [alias, paths] of Object.entries(tsconfig.compilerOptions.paths)) {
|
|
51
|
-
if (Array.isArray(paths) && paths.length > 0) {
|
|
52
|
-
const cleanAlias = alias.replace(/\/\*$/, '');
|
|
53
|
-
const cleanPath = paths[0].replace(/\/\*$/, '');
|
|
54
|
-
aliasMap[cleanAlias] = path.resolve(basePath, cleanPath);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
Console.warn('Error reading tsconfig.json for aliases:', error.message);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
resolve: {
|
|
65
|
-
alias: aliasMap
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
};
|
|
71
35
|
/**
|
|
72
36
|
* Plugin para Markdown
|
|
73
37
|
*/
|
|
@@ -85,91 +49,137 @@ const markdownPlugin = () => {
|
|
|
85
49
|
};
|
|
86
50
|
};
|
|
87
51
|
/**
|
|
88
|
-
* Plugin para CSS/PostCSS Manual (
|
|
52
|
+
* Plugin para CSS/PostCSS Manual (Smart Extraction + Tailwind Fix)
|
|
89
53
|
*/
|
|
90
|
-
const customPostCssPlugin = () => {
|
|
54
|
+
const customPostCssPlugin = (isProduction) => {
|
|
55
|
+
let cachedProcessor = null;
|
|
56
|
+
let configLoaded = false;
|
|
57
|
+
// Função auxiliar para inicializar o PostCSS apenas uma vez
|
|
58
|
+
const initPostCss = async (projectDir) => {
|
|
59
|
+
if (configLoaded)
|
|
60
|
+
return cachedProcessor;
|
|
61
|
+
// CRÍTICO: Garante que o Tailwind saiba que é produção para purgar CSS não usado
|
|
62
|
+
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
|
63
|
+
const postcssConfigPath = path.join(projectDir, 'postcss.config.js');
|
|
64
|
+
const postcssConfigMjsPath = path.join(projectDir, 'postcss.config.mjs');
|
|
65
|
+
const configPath = fs.existsSync(postcssConfigPath) ? postcssConfigPath :
|
|
66
|
+
(fs.existsSync(postcssConfigMjsPath) ? postcssConfigMjsPath : null);
|
|
67
|
+
if (configPath) {
|
|
68
|
+
try {
|
|
69
|
+
let postcss;
|
|
70
|
+
try {
|
|
71
|
+
postcss = require(path.join(projectDir, 'node_modules', 'postcss'));
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
try {
|
|
75
|
+
postcss = require('postcss');
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (postcss) {
|
|
82
|
+
delete require.cache[require.resolve(configPath)];
|
|
83
|
+
const config = require(configPath);
|
|
84
|
+
const postcssConfig = config.default || config;
|
|
85
|
+
const plugins = [];
|
|
86
|
+
if (postcssConfig.plugins) {
|
|
87
|
+
if (Array.isArray(postcssConfig.plugins)) {
|
|
88
|
+
plugins.push(...postcssConfig.plugins.map(p => {
|
|
89
|
+
if (typeof p === 'string') {
|
|
90
|
+
try {
|
|
91
|
+
const resolved = require.resolve(p, { paths: [projectDir] });
|
|
92
|
+
return require(resolved);
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return require(p);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return p;
|
|
99
|
+
}));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
for (const [name, options] of Object.entries(postcssConfig.plugins)) {
|
|
103
|
+
try {
|
|
104
|
+
const resolvedPath = require.resolve(name, { paths: [projectDir] });
|
|
105
|
+
const pluginModule = require(resolvedPath);
|
|
106
|
+
plugins.push(pluginModule(options || {}));
|
|
107
|
+
}
|
|
108
|
+
catch (e) {
|
|
109
|
+
Console.warn(`Unable to load plugin ${name}:`, e.message);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
cachedProcessor = postcss(plugins);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
Console.warn(`Error initializing PostCSS:`, e.message);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
configLoaded = true;
|
|
122
|
+
return cachedProcessor;
|
|
123
|
+
};
|
|
91
124
|
return {
|
|
92
125
|
name: 'custom-postcss-plugin',
|
|
93
|
-
enforce: 'pre',
|
|
94
126
|
async resolveId(source, importer) {
|
|
127
|
+
if (source.startsWith('\0custom-css:'))
|
|
128
|
+
return null;
|
|
95
129
|
if (source.endsWith('.css')) {
|
|
96
|
-
if (source.startsWith('\0custom-css:'))
|
|
97
|
-
return null;
|
|
98
130
|
const resolution = await this.resolve(source, importer, { skipSelf: true });
|
|
99
131
|
if (resolution && resolution.id) {
|
|
100
|
-
|
|
132
|
+
if (resolution.id.startsWith('\0custom-css:'))
|
|
133
|
+
return resolution.id;
|
|
134
|
+
return `\0custom-css:${resolution.id}`;
|
|
101
135
|
}
|
|
102
136
|
}
|
|
103
137
|
return null;
|
|
104
138
|
},
|
|
105
139
|
async load(id) {
|
|
106
140
|
if (id.startsWith('\0custom-css:')) {
|
|
107
|
-
|
|
141
|
+
let filePath = id.slice('\0custom-css:'.length);
|
|
142
|
+
while (filePath.startsWith('\0custom-css:')) {
|
|
143
|
+
filePath = filePath.slice('\0custom-css:'.length);
|
|
144
|
+
}
|
|
108
145
|
const cssContent = await fs.promises.readFile(filePath, 'utf8');
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
const postcssConfigMjsPath = path.join(projectDir, 'postcss.config.mjs');
|
|
146
|
+
// Usa o processador em cache ou inicializa se for a primeira vez
|
|
147
|
+
const processor = await initPostCss(process.cwd());
|
|
112
148
|
let processedCss = cssContent;
|
|
113
|
-
if (
|
|
149
|
+
if (processor) {
|
|
114
150
|
try {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
catch {
|
|
121
|
-
try {
|
|
122
|
-
postcss = require('postcss');
|
|
123
|
-
}
|
|
124
|
-
catch (e) {
|
|
125
|
-
Console.warn('PostCSS not found. Using raw CSS.');
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
if (postcss) {
|
|
129
|
-
const configPath = fs.existsSync(postcssConfigPath) ? postcssConfigPath : postcssConfigMjsPath;
|
|
130
|
-
delete require.cache[require.resolve(configPath)];
|
|
131
|
-
const config = require(configPath);
|
|
132
|
-
const postcssConfig = config.default || config;
|
|
133
|
-
const plugins = [];
|
|
134
|
-
if (postcssConfig.plugins) {
|
|
135
|
-
if (Array.isArray(postcssConfig.plugins)) {
|
|
136
|
-
plugins.push(...postcssConfig.plugins.map(p => {
|
|
137
|
-
if (typeof p === 'string') {
|
|
138
|
-
try {
|
|
139
|
-
const resolved = require.resolve(p, { paths: [projectDir] });
|
|
140
|
-
return require(resolved);
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
return require(p);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return p;
|
|
147
|
-
}));
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
for (const [name, options] of Object.entries(postcssConfig.plugins)) {
|
|
151
|
-
try {
|
|
152
|
-
const resolvedPath = require.resolve(name, { paths: [projectDir] });
|
|
153
|
-
const pluginModule = require(resolvedPath);
|
|
154
|
-
plugins.push(pluginModule(options || {}));
|
|
155
|
-
}
|
|
156
|
-
catch (e) {
|
|
157
|
-
Console.warn(`Unable to load plugin ${name}:`, e.message);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
const result = await postcss(plugins).process(cssContent, {
|
|
163
|
-
from: filePath,
|
|
164
|
-
to: filePath.replace(/\.css$/, '.processed.css')
|
|
165
|
-
});
|
|
166
|
-
processedCss = result.css;
|
|
167
|
-
}
|
|
151
|
+
const result = await processor.process(cssContent, {
|
|
152
|
+
from: filePath,
|
|
153
|
+
to: filePath
|
|
154
|
+
});
|
|
155
|
+
processedCss = result.css;
|
|
168
156
|
}
|
|
169
157
|
catch (e) {
|
|
170
|
-
Console.warn(`
|
|
158
|
+
Console.warn(`PostCSS process error:`, e.message);
|
|
171
159
|
}
|
|
172
160
|
}
|
|
161
|
+
// ESTRATÉGIA DE EXTRAÇÃO INTELIGENTE
|
|
162
|
+
if (isProduction) {
|
|
163
|
+
// Emite arquivo físico (Melhora Cache e Tamanho do JS)
|
|
164
|
+
const referenceId = this.emitFile({
|
|
165
|
+
type: 'asset',
|
|
166
|
+
name: path.basename(filePath),
|
|
167
|
+
source: processedCss
|
|
168
|
+
});
|
|
169
|
+
// Retorna código JS que auto-injeta o <link>
|
|
170
|
+
// Isso mantém compatibilidade (não quebra o app) mas usa arquivo externo
|
|
171
|
+
return `
|
|
172
|
+
const cssUrl = import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
173
|
+
if (typeof document !== 'undefined') {
|
|
174
|
+
const link = document.createElement('link');
|
|
175
|
+
link.rel = 'stylesheet';
|
|
176
|
+
link.href = cssUrl;
|
|
177
|
+
document.head.appendChild(link);
|
|
178
|
+
}
|
|
179
|
+
export default cssUrl;
|
|
180
|
+
`;
|
|
181
|
+
}
|
|
182
|
+
// Modo DEV (Inline para Hot Reload mais rápido)
|
|
173
183
|
return `
|
|
174
184
|
const css = ${JSON.stringify(processedCss)};
|
|
175
185
|
if (typeof document !== 'undefined') {
|
|
@@ -185,95 +195,146 @@ const customPostCssPlugin = () => {
|
|
|
185
195
|
};
|
|
186
196
|
};
|
|
187
197
|
/**
|
|
188
|
-
* Plugin para
|
|
198
|
+
* Plugin Inteligente para Assets (Substitui forceBase64Plugin)
|
|
199
|
+
* - Dev: Base64 (Rápido)
|
|
200
|
+
* - Prod: Arquivos > 4KB viram URL (Melhora LCP), < 4KB Base64 (Menos requests)
|
|
189
201
|
*/
|
|
190
|
-
const
|
|
202
|
+
const smartAssetPlugin = (isProduction) => {
|
|
203
|
+
const INLINE_LIMIT = 4096; // 4KB
|
|
191
204
|
return {
|
|
192
|
-
name: '
|
|
205
|
+
name: 'smart-asset-loader',
|
|
193
206
|
async load(id) {
|
|
194
207
|
const cleanId = id.split('?')[0];
|
|
208
|
+
if (cleanId.startsWith('\0'))
|
|
209
|
+
return null;
|
|
195
210
|
const ext = path.extname(cleanId).slice(1).toLowerCase();
|
|
196
211
|
const mimeTypes = {
|
|
197
212
|
'png': 'image/png', 'jpg': 'image/jpeg', 'jpeg': 'image/jpeg',
|
|
198
213
|
'gif': 'image/gif', 'webp': 'image/webp', 'avif': 'image/avif',
|
|
199
|
-
'ico': 'image/x-icon', 'bmp': 'image/bmp', 'tif': 'image/tiff',
|
|
200
|
-
'
|
|
201
|
-
'otf': 'font/otf', 'eot': 'application/vnd.ms-fontobject',
|
|
214
|
+
'ico': 'image/x-icon', 'bmp': 'image/bmp', 'tif': 'image/tiff',
|
|
215
|
+
'tiff': 'image/tiff', 'woff': 'font/woff', 'woff2': 'font/woff2',
|
|
216
|
+
'ttf': 'font/ttf', 'otf': 'font/otf', 'eot': 'application/vnd.ms-fontobject',
|
|
202
217
|
'mp3': 'audio/mpeg', 'wav': 'audio/wav', 'ogg': 'audio/ogg',
|
|
203
218
|
'm4a': 'audio/mp4', 'aac': 'audio/aac', 'flac': 'audio/flac',
|
|
204
|
-
'mp4': 'video/mp4', 'webm': 'video/webm', 'ogv': 'video/ogg'
|
|
219
|
+
'mp4': 'video/mp4', 'webm': 'video/webm', 'ogv': 'video/ogg',
|
|
220
|
+
'svg': 'svg', 'txt': 'txt'
|
|
205
221
|
};
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (ext === 'svg') {
|
|
222
|
+
const type = mimeTypes[ext];
|
|
223
|
+
if (!type)
|
|
224
|
+
return null;
|
|
225
|
+
// Text files always strings
|
|
226
|
+
if (type === 'txt') {
|
|
212
227
|
const content = await fs.promises.readFile(cleanId, 'utf8');
|
|
213
|
-
|
|
228
|
+
return `export default ${JSON.stringify(content)};`;
|
|
229
|
+
}
|
|
230
|
+
const buffer = await fs.promises.readFile(cleanId);
|
|
231
|
+
const size = buffer.length;
|
|
232
|
+
// MODO PRODUÇÃO: Otimização de Assets
|
|
233
|
+
if (isProduction) {
|
|
234
|
+
// SVG: Se for pequeno inlina, se grande emite arquivo
|
|
235
|
+
if (type === 'svg') {
|
|
236
|
+
if (size < INLINE_LIMIT) {
|
|
237
|
+
const content = buffer.toString('utf8');
|
|
238
|
+
const base64 = buffer.toString('base64');
|
|
239
|
+
return `
|
|
240
|
+
export default "data:image/svg+xml;base64,${base64}";
|
|
241
|
+
export const svgContent = ${JSON.stringify(content)};
|
|
242
|
+
`;
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// Emite arquivo físico
|
|
246
|
+
const referenceId = this.emitFile({
|
|
247
|
+
type: 'asset',
|
|
248
|
+
name: path.basename(cleanId),
|
|
249
|
+
source: buffer
|
|
250
|
+
});
|
|
251
|
+
const content = buffer.toString('utf8');
|
|
252
|
+
return `
|
|
253
|
+
export default import.meta.ROLLUP_FILE_URL_${referenceId};
|
|
254
|
+
export const svgContent = ${JSON.stringify(content)};
|
|
255
|
+
`;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Outros assets
|
|
259
|
+
if (size < INLINE_LIMIT) {
|
|
260
|
+
return `export default "data:${type};base64,${buffer.toString('base64')}";`;
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const referenceId = this.emitFile({
|
|
264
|
+
type: 'asset',
|
|
265
|
+
name: path.basename(cleanId),
|
|
266
|
+
source: buffer
|
|
267
|
+
});
|
|
268
|
+
return `export default import.meta.ROLLUP_FILE_URL_${referenceId};`;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// MODO DESENVOLVIMENTO: Tudo Base64 para performance de build
|
|
272
|
+
if (type === 'svg') {
|
|
273
|
+
const content = buffer.toString('utf8');
|
|
274
|
+
const base64 = buffer.toString('base64');
|
|
214
275
|
return `
|
|
215
276
|
export default "data:image/svg+xml;base64,${base64}";
|
|
216
277
|
export const svgContent = ${JSON.stringify(content)};
|
|
217
278
|
`;
|
|
218
279
|
}
|
|
219
|
-
|
|
220
|
-
const content = await fs.promises.readFile(cleanId, 'utf8');
|
|
221
|
-
return `export default ${JSON.stringify(content)};`;
|
|
222
|
-
}
|
|
280
|
+
return `export default "data:${type};base64,${buffer.toString('base64')}";`;
|
|
223
281
|
}
|
|
224
282
|
};
|
|
225
283
|
};
|
|
226
284
|
/**
|
|
227
|
-
*
|
|
285
|
+
* Gera a configuração base do Rollup
|
|
228
286
|
*/
|
|
229
|
-
function
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
logLevel: 'error',
|
|
238
|
-
clearScreen: false,
|
|
239
|
-
define: {
|
|
240
|
-
'process.env.NODE_ENV': isProduction ? '"production"' : '"development"'
|
|
241
|
-
},
|
|
242
|
-
resolve: {
|
|
243
|
-
extensions: ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json']
|
|
244
|
-
},
|
|
287
|
+
function createRollupConfig(entryPoint, outdir, isProduction) {
|
|
288
|
+
return {
|
|
289
|
+
input: entryPoint,
|
|
290
|
+
external: nodeBuiltIns,
|
|
291
|
+
// Otimização: Em prod usa 'recommended' para limpar código morto
|
|
292
|
+
treeshake: isProduction ? 'recommended' : false,
|
|
293
|
+
cache: true,
|
|
294
|
+
perf: false,
|
|
245
295
|
plugins: [
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
296
|
+
nodeResolve({
|
|
297
|
+
extensions: ['.mjs', '.js', '.json', '.node', '.jsx', '.tsx', '.ts'],
|
|
298
|
+
preferBuiltins: true,
|
|
299
|
+
browser: false,
|
|
300
|
+
dedupe: ['react', 'react-dom'] // Otimização: Evita duplicar React no bundle
|
|
301
|
+
}),
|
|
302
|
+
commonjs({
|
|
303
|
+
sourceMap: !isProduction
|
|
304
|
+
}),
|
|
249
305
|
markdownPlugin(),
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
reportCompressedSize: false,
|
|
259
|
-
chunkSizeWarningLimit: 10000,
|
|
260
|
-
commonjsOptions: {
|
|
261
|
-
transformMixedEsModules: true,
|
|
262
|
-
include: [/node_modules/, /packages/],
|
|
263
|
-
},
|
|
264
|
-
rollupOptions: {
|
|
265
|
-
input: entryPoint,
|
|
266
|
-
external: nodeBuiltIns,
|
|
267
|
-
onwarn(warning, warn) {
|
|
268
|
-
if (warning.code === 'MODULE_LEVEL_DIRECTIVE')
|
|
269
|
-
return;
|
|
270
|
-
if (warning.code === 'INVALID_ANNOTATION')
|
|
271
|
-
return;
|
|
272
|
-
warn(warning);
|
|
306
|
+
// Passamos isProduction para ativar a Extração Inteligente
|
|
307
|
+
customPostCssPlugin(isProduction),
|
|
308
|
+
// Substitui forceBase64Plugin pelo Smart
|
|
309
|
+
smartAssetPlugin(isProduction),
|
|
310
|
+
replace({
|
|
311
|
+
preventAssignment: true,
|
|
312
|
+
values: {
|
|
313
|
+
'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development')
|
|
273
314
|
}
|
|
274
|
-
}
|
|
315
|
+
}),
|
|
316
|
+
esbuild({
|
|
317
|
+
include: /\.[jt]sx?$/,
|
|
318
|
+
exclude: /node_modules/,
|
|
319
|
+
sourceMap: !isProduction,
|
|
320
|
+
minify: isProduction,
|
|
321
|
+
// Otimização: Remove comentários legais em produção
|
|
322
|
+
legalComments: isProduction ? 'none' : 'eof',
|
|
323
|
+
treeShaking: isProduction,
|
|
324
|
+
target: isProduction ? 'es2020' : 'esnext',
|
|
325
|
+
jsx: 'automatic',
|
|
326
|
+
define: { __VERSION__: '"1.0.0"' },
|
|
327
|
+
loaders: { '.json': 'json', '.js': 'jsx' }
|
|
328
|
+
})
|
|
329
|
+
],
|
|
330
|
+
onwarn(warning, warn) {
|
|
331
|
+
if (warning.code === 'MODULE_LEVEL_DIRECTIVE')
|
|
332
|
+
return;
|
|
333
|
+
if (warning.code === 'THIS_IS_UNDEFINED')
|
|
334
|
+
return;
|
|
335
|
+
warn(warning);
|
|
275
336
|
}
|
|
276
|
-
}
|
|
337
|
+
};
|
|
277
338
|
}
|
|
278
339
|
/**
|
|
279
340
|
* Builds with code splitting into multiple chunks (ESM Format) - MODO PRODUÇÃO
|
|
@@ -281,20 +342,38 @@ function createBaseConfig(entryPoint, outdir, isProduction) {
|
|
|
281
342
|
async function buildWithChunks(entryPoint, outdir, isProduction = false) {
|
|
282
343
|
await cleanDirectoryExcept(outdir, 'temp');
|
|
283
344
|
try {
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
345
|
+
const inputOptions = createRollupConfig(entryPoint, outdir, isProduction);
|
|
346
|
+
const outputOptions = {
|
|
347
|
+
dir: outdir,
|
|
287
348
|
format: 'es',
|
|
349
|
+
// Padrão de nomes mantido, mas com estrutura para vários arquivos
|
|
288
350
|
entryFileNames: isProduction ? 'main-[hash].js' : 'main.js',
|
|
289
351
|
chunkFileNames: 'chunks/[name]-[hash].js',
|
|
290
352
|
assetFileNames: 'assets/[name]-[hash][extname]',
|
|
353
|
+
sourcemap: !isProduction,
|
|
354
|
+
// OTIMIZAÇÃO: Separação granular para melhor Cache e Load Time
|
|
291
355
|
manualChunks(id) {
|
|
292
356
|
if (id.includes('node_modules')) {
|
|
357
|
+
// React Core isolado (muda pouco, cache longo)
|
|
358
|
+
if (id.includes('react') || id.includes('scheduler') || id.includes('prop-types')) {
|
|
359
|
+
return 'vendor-react';
|
|
360
|
+
}
|
|
361
|
+
// UI Libs comuns (opcional, pode ajustar conforme necessidade)
|
|
362
|
+
if (id.includes('framer-motion') || id.includes('@radix-ui')) {
|
|
363
|
+
return 'vendor-ui';
|
|
364
|
+
}
|
|
365
|
+
// Utils comuns
|
|
366
|
+
if (id.includes('lodash') || id.includes('date-fns') || id.includes('axios')) {
|
|
367
|
+
return 'vendor-utils';
|
|
368
|
+
}
|
|
369
|
+
// Resto das dependências
|
|
293
370
|
return 'vendor';
|
|
294
371
|
}
|
|
295
372
|
}
|
|
296
373
|
};
|
|
297
|
-
await
|
|
374
|
+
const bundle = await rollup(inputOptions);
|
|
375
|
+
await bundle.write(outputOptions);
|
|
376
|
+
await bundle.close();
|
|
298
377
|
}
|
|
299
378
|
catch (error) {
|
|
300
379
|
Console.error('An error occurred while building with chunks:', error);
|
|
@@ -306,18 +385,19 @@ async function buildWithChunks(entryPoint, outdir, isProduction = false) {
|
|
|
306
385
|
*/
|
|
307
386
|
async function build(entryPoint, outfile, isProduction = false) {
|
|
308
387
|
const outdir = path.dirname(outfile);
|
|
309
|
-
const filename = path.basename(outfile);
|
|
310
388
|
await cleanDirectoryExcept(outdir, 'temp');
|
|
311
389
|
try {
|
|
312
|
-
const
|
|
313
|
-
|
|
314
|
-
|
|
390
|
+
const inputOptions = createRollupConfig(entryPoint, outdir, isProduction);
|
|
391
|
+
const outputOptions = {
|
|
392
|
+
file: outfile,
|
|
315
393
|
format: 'iife',
|
|
316
394
|
name: 'HwebApp',
|
|
317
|
-
|
|
318
|
-
inlineDynamicImports: true
|
|
395
|
+
sourcemap: !isProduction,
|
|
396
|
+
inlineDynamicImports: true
|
|
319
397
|
};
|
|
320
|
-
await
|
|
398
|
+
const bundle = await rollup(inputOptions);
|
|
399
|
+
await bundle.write(outputOptions);
|
|
400
|
+
await bundle.close();
|
|
321
401
|
}
|
|
322
402
|
catch (error) {
|
|
323
403
|
Console.error('An error occurred during build:', error);
|
|
@@ -325,115 +405,74 @@ async function build(entryPoint, outfile, isProduction = false) {
|
|
|
325
405
|
}
|
|
326
406
|
}
|
|
327
407
|
/**
|
|
328
|
-
*
|
|
408
|
+
* Helper para lidar com notificações do Watcher
|
|
409
|
+
*/
|
|
410
|
+
function handleWatcherEvents(watcher, hotReloadManager, resolveFirstBuild) {
|
|
411
|
+
let hasError = false;
|
|
412
|
+
watcher.on('event', event => {
|
|
413
|
+
if (event.code === 'START')
|
|
414
|
+
hasError = false;
|
|
415
|
+
if (event.code === 'ERROR') {
|
|
416
|
+
hasError = true;
|
|
417
|
+
const errDetails = {
|
|
418
|
+
message: event.error?.message || 'Unknown build error',
|
|
419
|
+
name: event.error?.name,
|
|
420
|
+
stack: event.error?.stack,
|
|
421
|
+
id: event.error?.id,
|
|
422
|
+
loc: event.error?.loc
|
|
423
|
+
};
|
|
424
|
+
if (hotReloadManager)
|
|
425
|
+
hotReloadManager.onBuildComplete(false, errDetails);
|
|
426
|
+
else
|
|
427
|
+
Console.error("Build Error:", event.error);
|
|
428
|
+
if (resolveFirstBuild)
|
|
429
|
+
resolveFirstBuild();
|
|
430
|
+
}
|
|
431
|
+
if (event.code === 'BUNDLE_END')
|
|
432
|
+
event.result.close();
|
|
433
|
+
if (event.code === 'END') {
|
|
434
|
+
if (!hasError && hotReloadManager)
|
|
435
|
+
hotReloadManager.onBuildComplete(true);
|
|
436
|
+
if (resolveFirstBuild) {
|
|
437
|
+
resolveFirstBuild();
|
|
438
|
+
resolveFirstBuild = null;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Watches with code splitting enabled
|
|
329
445
|
*/
|
|
330
446
|
async function watchWithChunks(entryPoint, outdir, hotReloadManager = null) {
|
|
331
447
|
await cleanDirectoryExcept(outdir, 'temp');
|
|
332
448
|
try {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
// problemas de 404 com chunks e simplificar o debug.
|
|
338
|
-
// O splitting fica restrito ao build de produção.
|
|
339
|
-
config.build.cssCodeSplit = false;
|
|
340
|
-
config.build.rollupOptions.output = {
|
|
449
|
+
// DEV MODE: isProduction = false
|
|
450
|
+
const inputOptions = createRollupConfig(entryPoint, outdir, false);
|
|
451
|
+
const outputOptions = {
|
|
452
|
+
dir: outdir,
|
|
341
453
|
format: 'iife',
|
|
342
454
|
name: 'HwebApp',
|
|
343
455
|
entryFileNames: 'main.js',
|
|
344
|
-
inlineDynamicImports: true
|
|
345
|
-
|
|
456
|
+
inlineDynamicImports: true,
|
|
457
|
+
sourcemap: true
|
|
346
458
|
};
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
},
|
|
355
|
-
closeBundle() {
|
|
356
|
-
// closeBundle pode rodar em situações inesperadas; não usamos isso pra limpar erro.
|
|
357
|
-
},
|
|
358
|
-
buildEnd(error) {
|
|
359
|
-
if (error) {
|
|
360
|
-
this.__nyteCycleHadError = true;
|
|
361
|
-
if (hotReloadManager) {
|
|
362
|
-
hotReloadManager.onBuildComplete(false, {
|
|
363
|
-
message: error.message,
|
|
364
|
-
name: error.name,
|
|
365
|
-
stack: error.stack,
|
|
366
|
-
// Vite/Rollup às vezes coloca infos adicionais
|
|
367
|
-
cause: error.cause,
|
|
368
|
-
loc: error.loc,
|
|
369
|
-
frame: error.frame,
|
|
370
|
-
id: error.id,
|
|
371
|
-
plugin: error.plugin,
|
|
372
|
-
pluginCode: error.pluginCode,
|
|
373
|
-
watchFiles: error.watchFiles
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
459
|
+
const watchOptions = {
|
|
460
|
+
...inputOptions,
|
|
461
|
+
output: outputOptions,
|
|
462
|
+
watch: {
|
|
463
|
+
exclude: 'node_modules/**',
|
|
464
|
+
clearScreen: false,
|
|
465
|
+
skipWrite: false
|
|
377
466
|
}
|
|
378
|
-
}
|
|
379
|
-
const watcher =
|
|
380
|
-
|
|
381
|
-
let watcherCycleHadError = false;
|
|
382
|
-
if (watcher && typeof watcher.on === 'function') {
|
|
383
|
-
watcher.on('event', (event) => {
|
|
384
|
-
if (!event)
|
|
385
|
-
return;
|
|
386
|
-
if (event.code === 'ERROR') {
|
|
387
|
-
watcherCycleHadError = true;
|
|
388
|
-
if (hotReloadManager) {
|
|
389
|
-
hotReloadManager.onBuildComplete(false, {
|
|
390
|
-
message: event.error?.message || 'Unknown build error',
|
|
391
|
-
name: event.error?.name,
|
|
392
|
-
stack: event.error?.stack,
|
|
393
|
-
cause: event.error?.cause,
|
|
394
|
-
loc: event.error?.loc,
|
|
395
|
-
frame: event.error?.frame,
|
|
396
|
-
id: event.error?.id,
|
|
397
|
-
plugin: event.error?.plugin,
|
|
398
|
-
pluginCode: event.error?.pluginCode,
|
|
399
|
-
watchFiles: event.error?.watchFiles
|
|
400
|
-
});
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
if (event.code === 'BUNDLE_END') {
|
|
404
|
-
if (hotReloadManager) {
|
|
405
|
-
if (!watcherCycleHadError) {
|
|
406
|
-
hotReloadManager.onBuildComplete(true);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
// Próximo ciclo
|
|
410
|
-
watcherCycleHadError = false;
|
|
411
|
-
}
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
// Aguarda o primeiro build terminar
|
|
415
|
-
await new Promise((resolve) => {
|
|
416
|
-
let initialBuild = true;
|
|
417
|
-
watcher.on('event', (event) => {
|
|
418
|
-
if (event.code === 'BUNDLE_END') {
|
|
419
|
-
if (initialBuild) {
|
|
420
|
-
initialBuild = false;
|
|
421
|
-
resolve();
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
});
|
|
425
|
-
});
|
|
467
|
+
};
|
|
468
|
+
const watcher = rollupWatch(watchOptions);
|
|
469
|
+
await new Promise((resolve) => handleWatcherEvents(watcher, hotReloadManager, resolve));
|
|
426
470
|
return watcher;
|
|
427
471
|
}
|
|
428
472
|
catch (error) {
|
|
429
473
|
Console.error('Error starting watch mode with chunks:', error);
|
|
430
|
-
if (hotReloadManager)
|
|
431
|
-
hotReloadManager.onBuildComplete(false, {
|
|
432
|
-
message: error.message,
|
|
433
|
-
name: error.name,
|
|
434
|
-
stack: error.stack
|
|
435
|
-
});
|
|
436
|
-
}
|
|
474
|
+
if (hotReloadManager)
|
|
475
|
+
hotReloadManager.onBuildComplete(false, { message: error.message });
|
|
437
476
|
throw error;
|
|
438
477
|
}
|
|
439
478
|
}
|
|
@@ -442,89 +481,31 @@ async function watchWithChunks(entryPoint, outdir, hotReloadManager = null) {
|
|
|
442
481
|
*/
|
|
443
482
|
async function watch(entryPoint, outfile, hotReloadManager = null) {
|
|
444
483
|
const outdir = path.dirname(outfile);
|
|
445
|
-
const filename = path.basename(outfile);
|
|
446
484
|
try {
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
config.build.rollupOptions.output = {
|
|
485
|
+
const inputOptions = createRollupConfig(entryPoint, outdir, false);
|
|
486
|
+
const outputOptions = {
|
|
487
|
+
file: outfile,
|
|
451
488
|
format: 'iife',
|
|
452
489
|
name: 'HwebApp',
|
|
453
|
-
|
|
454
|
-
|
|
490
|
+
inlineDynamicImports: true,
|
|
491
|
+
sourcemap: true
|
|
455
492
|
};
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
// Ignorado para sinalização de sucesso
|
|
463
|
-
},
|
|
464
|
-
buildEnd(error) {
|
|
465
|
-
if (error) {
|
|
466
|
-
this.__nyteCycleHadError = true;
|
|
467
|
-
if (hotReloadManager) {
|
|
468
|
-
hotReloadManager.onBuildComplete(false, {
|
|
469
|
-
message: error.message,
|
|
470
|
-
name: error.name,
|
|
471
|
-
stack: error.stack,
|
|
472
|
-
cause: error.cause,
|
|
473
|
-
loc: error.loc,
|
|
474
|
-
frame: error.frame,
|
|
475
|
-
id: error.id,
|
|
476
|
-
plugin: error.plugin,
|
|
477
|
-
pluginCode: error.pluginCode,
|
|
478
|
-
watchFiles: error.watchFiles
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
493
|
+
const watchOptions = {
|
|
494
|
+
...inputOptions,
|
|
495
|
+
output: outputOptions,
|
|
496
|
+
watch: {
|
|
497
|
+
exclude: 'node_modules/**',
|
|
498
|
+
clearScreen: false
|
|
482
499
|
}
|
|
483
|
-
}
|
|
484
|
-
const watcher =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
watcher.on('event', (event) => {
|
|
488
|
-
if (!event)
|
|
489
|
-
return;
|
|
490
|
-
if (event.code === 'ERROR') {
|
|
491
|
-
watcherCycleHadError = true;
|
|
492
|
-
if (hotReloadManager) {
|
|
493
|
-
hotReloadManager.onBuildComplete(false, {
|
|
494
|
-
message: event.error?.message || 'Unknown build error',
|
|
495
|
-
name: event.error?.name,
|
|
496
|
-
stack: event.error?.stack,
|
|
497
|
-
cause: event.error?.cause,
|
|
498
|
-
loc: event.error?.loc,
|
|
499
|
-
frame: event.error?.frame,
|
|
500
|
-
id: event.error?.id,
|
|
501
|
-
plugin: event.error?.plugin,
|
|
502
|
-
pluginCode: event.error?.pluginCode,
|
|
503
|
-
watchFiles: event.error?.watchFiles
|
|
504
|
-
});
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
if (event.code === 'BUNDLE_END') {
|
|
508
|
-
if (hotReloadManager) {
|
|
509
|
-
if (!watcherCycleHadError) {
|
|
510
|
-
hotReloadManager.onBuildComplete(true);
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
watcherCycleHadError = false;
|
|
514
|
-
}
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
// (removido) await viteBuild(config); // já estamos em watch mode
|
|
500
|
+
};
|
|
501
|
+
const watcher = rollupWatch(watchOptions);
|
|
502
|
+
await new Promise((resolve) => handleWatcherEvents(watcher, hotReloadManager, resolve));
|
|
503
|
+
return watcher;
|
|
518
504
|
}
|
|
519
505
|
catch (error) {
|
|
520
506
|
Console.error('Error starting watch mode:', error);
|
|
521
|
-
if (hotReloadManager)
|
|
522
|
-
hotReloadManager.onBuildComplete(false, {
|
|
523
|
-
message: error.message,
|
|
524
|
-
name: error.name,
|
|
525
|
-
stack: error.stack
|
|
526
|
-
});
|
|
527
|
-
}
|
|
507
|
+
if (hotReloadManager)
|
|
508
|
+
hotReloadManager.onBuildComplete(false, { message: error.message });
|
|
528
509
|
throw error;
|
|
529
510
|
}
|
|
530
511
|
}
|
|
@@ -534,13 +515,14 @@ async function cleanDirectoryExcept(dirPath, excludeFolder) {
|
|
|
534
515
|
return;
|
|
535
516
|
const excludes = Array.isArray(excludeFolder) ? excludeFolder : [excludeFolder];
|
|
536
517
|
const items = await readdir(dirPath);
|
|
537
|
-
|
|
518
|
+
// Paraleliza a limpeza
|
|
519
|
+
await Promise.all(items.map(async (item) => {
|
|
538
520
|
if (excludes.includes(item))
|
|
539
|
-
|
|
521
|
+
return;
|
|
540
522
|
const itemPath = path.join(dirPath, item);
|
|
541
523
|
const info = await stat(itemPath);
|
|
542
|
-
|
|
543
|
-
}
|
|
524
|
+
fs.rm(itemPath, { recursive: info.isDirectory(), force: true });
|
|
525
|
+
}));
|
|
544
526
|
}
|
|
545
527
|
catch (e) {
|
|
546
528
|
Console.warn(`Warning cleaning directory: ${e.message}`);
|