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