ezfw-core 1.0.98 → 1.0.99
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/package.json +1 -1
- package/template/vite.config.ts +34 -31
package/package.json
CHANGED
package/template/vite.config.ts
CHANGED
|
@@ -1,20 +1,38 @@
|
|
|
1
|
-
// vite.config.ts - Ez Framework
|
|
1
|
+
// vite.config.ts - Ez Framework
|
|
2
2
|
import { defineConfig, Plugin } from 'vite';
|
|
3
|
-
import { ezIslands } from '
|
|
3
|
+
import { ezEntry, ezIslands, ezJsx } from 'ezfw-core/vite';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
|
|
7
|
-
// Plugin to
|
|
7
|
+
// Plugin to inline critical CSS and make other CSS non-render-blocking
|
|
8
8
|
function asyncCssPlugin(): Plugin {
|
|
9
9
|
return {
|
|
10
10
|
name: 'async-css',
|
|
11
11
|
enforce: 'post',
|
|
12
12
|
transformIndexHtml(html) {
|
|
13
|
-
//
|
|
14
|
-
|
|
13
|
+
// Read and inline global.css (critical reset styles)
|
|
14
|
+
const globalCssPath = path.resolve(__dirname, 'public/global.css');
|
|
15
|
+
if (fs.existsSync(globalCssPath)) {
|
|
16
|
+
const globalCss = fs.readFileSync(globalCssPath, 'utf-8')
|
|
17
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
18
|
+
.replace(/\s+/g, ' ')
|
|
19
|
+
.trim();
|
|
20
|
+
html = html.replace(
|
|
21
|
+
/<!-- INLINE_GLOBAL_CSS -->/,
|
|
22
|
+
`<style>${globalCss}</style>`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
// Make main CSS async (ez.styles bundle)
|
|
26
|
+
html = html.replace(
|
|
27
|
+
/<link rel="stylesheet" crossorigin href="(\/assets\/ez\.styles[^"]+\.css)">/g,
|
|
28
|
+
'<link rel="stylesheet" href="$1" media="print" onload="this.media=\'all\'" crossorigin><noscript><link rel="stylesheet" href="$1" crossorigin></noscript>'
|
|
29
|
+
);
|
|
30
|
+
// Transform CSS links for non-critical component stylesheets
|
|
31
|
+
html = html.replace(
|
|
15
32
|
/<link rel="stylesheet" crossorigin href="(\/assets\/(EzToast|EzMask|EzTooltip|EzDialog|EzDrawer)[^"]+\.css)">/g,
|
|
16
33
|
'<link rel="stylesheet" href="$1" media="print" onload="this.media=\'all\'">'
|
|
17
34
|
);
|
|
35
|
+
return html;
|
|
18
36
|
}
|
|
19
37
|
};
|
|
20
38
|
}
|
|
@@ -26,16 +44,12 @@ function ssrPreviewPlugin(): Plugin {
|
|
|
26
44
|
configurePreviewServer(server) {
|
|
27
45
|
server.middlewares.use((req, res, next) => {
|
|
28
46
|
const url = req.url || '/';
|
|
29
|
-
// Skip assets and files with extensions
|
|
30
47
|
if (url.startsWith('/assets/') || url.includes('.')) {
|
|
31
48
|
return next();
|
|
32
49
|
}
|
|
33
50
|
|
|
34
|
-
// Try to find index.html in the subdirectory
|
|
35
51
|
const distPath = path.resolve(__dirname, 'dist');
|
|
36
52
|
let htmlPath = path.join(distPath, url, 'index.html');
|
|
37
|
-
|
|
38
|
-
// Normalize path for Windows
|
|
39
53
|
htmlPath = path.normalize(htmlPath);
|
|
40
54
|
|
|
41
55
|
if (fs.existsSync(htmlPath)) {
|
|
@@ -56,15 +70,21 @@ export default defineConfig({
|
|
|
56
70
|
root: '.',
|
|
57
71
|
appType: 'mpa',
|
|
58
72
|
resolve: {
|
|
59
|
-
extensions: ['.ts', '.js', '.mjs', '.json']
|
|
73
|
+
extensions: ['.tsx', '.ts', '.jsx', '.js', '.mjs', '.json']
|
|
60
74
|
},
|
|
61
75
|
css: {
|
|
62
76
|
modules: {
|
|
63
|
-
// Don't hash class names - SSR needs predictable names
|
|
64
77
|
generateScopedName: '[local]'
|
|
78
|
+
},
|
|
79
|
+
preprocessorOptions: {
|
|
80
|
+
scss: {
|
|
81
|
+
api: 'modern-compiler'
|
|
82
|
+
}
|
|
65
83
|
}
|
|
66
84
|
},
|
|
67
85
|
plugins: [
|
|
86
|
+
ezEntry(),
|
|
87
|
+
ezJsx(),
|
|
68
88
|
asyncCssPlugin(),
|
|
69
89
|
ssrPreviewPlugin(),
|
|
70
90
|
ezIslands({
|
|
@@ -77,15 +97,15 @@ export default defineConfig({
|
|
|
77
97
|
target: 'esnext',
|
|
78
98
|
minify: 'esbuild',
|
|
79
99
|
cssMinify: true,
|
|
100
|
+
outDir: 'dist',
|
|
80
101
|
rollupOptions: {
|
|
81
102
|
input: {
|
|
82
103
|
main: '/index.html',
|
|
83
104
|
hydrate: '/hydrate.js',
|
|
84
|
-
'islands-runtime': '/
|
|
105
|
+
'islands-runtime': 'ezfw-core/islands/runtime'
|
|
85
106
|
},
|
|
86
107
|
output: {
|
|
87
108
|
entryFileNames: (chunkInfo) => {
|
|
88
|
-
// Keep hydrate and islands-runtime without hash for SSR pages
|
|
89
109
|
if (chunkInfo.name === 'hydrate' || chunkInfo.name === 'islands-runtime') {
|
|
90
110
|
return `assets/${chunkInfo.name}.js`;
|
|
91
111
|
}
|
|
@@ -97,29 +117,16 @@ export default defineConfig({
|
|
|
97
117
|
preview: {
|
|
98
118
|
headers: {
|
|
99
119
|
'Cache-Control': 'no-store',
|
|
100
|
-
// Security headers for Best Practices
|
|
101
120
|
'X-Frame-Options': 'SAMEORIGIN',
|
|
102
121
|
'X-Content-Type-Options': 'nosniff',
|
|
103
122
|
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
|
104
123
|
'Cross-Origin-Opener-Policy': 'same-origin-allow-popups',
|
|
105
124
|
'Cross-Origin-Embedder-Policy': 'credentialless',
|
|
106
|
-
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()'
|
|
107
|
-
'Content-Security-Policy': [
|
|
108
|
-
"default-src 'self'",
|
|
109
|
-
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://apis.google.com https://*.firebaseapp.com https://*.googleapis.com",
|
|
110
|
-
"style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com https://fonts.googleapis.com",
|
|
111
|
-
"font-src 'self' https://cdnjs.cloudflare.com https://fonts.gstatic.com",
|
|
112
|
-
"img-src 'self' data: https: blob:",
|
|
113
|
-
"connect-src 'self' https://*.googleapis.com https://*.firebaseio.com https://*.firebaseapp.com wss://*.firebaseio.com https://identitytoolkit.googleapis.com https://securetoken.googleapis.com",
|
|
114
|
-
"frame-src 'self' https://*.firebaseapp.com https://accounts.google.com",
|
|
115
|
-
"object-src 'none'",
|
|
116
|
-
"base-uri 'self'"
|
|
117
|
-
].join('; ')
|
|
125
|
+
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()'
|
|
118
126
|
}
|
|
119
127
|
},
|
|
120
128
|
server: {
|
|
121
129
|
headers: {
|
|
122
|
-
// Same headers for dev server
|
|
123
130
|
'X-Frame-Options': 'SAMEORIGIN',
|
|
124
131
|
'X-Content-Type-Options': 'nosniff',
|
|
125
132
|
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
|
@@ -127,7 +134,3 @@ export default defineConfig({
|
|
|
127
134
|
}
|
|
128
135
|
}
|
|
129
136
|
});
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|