@olenbetong/appframe-vite 4.1.4 → 4.1.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/lib/devServer.js +90 -65
- package/package.json +3 -7
package/lib/devServer.js
CHANGED
|
@@ -54,66 +54,85 @@ export function getProxyRoutes() {
|
|
|
54
54
|
* - Add the hostname to links with absolute paths (they are not part of the application, and will fail without host)
|
|
55
55
|
* @returns
|
|
56
56
|
*/
|
|
57
|
+
async function transformArticleHtml(html) {
|
|
58
|
+
let entry;
|
|
59
|
+
if (await exists(resolve(process.cwd(), "./src/index.tsx"))) {
|
|
60
|
+
entry = "/src/index.tsx";
|
|
61
|
+
}
|
|
62
|
+
else if (await exists(resolve(process.cwd(), "./src/index.ts"))) {
|
|
63
|
+
entry = "/src/index.ts";
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
entry = "/src/index.js";
|
|
67
|
+
}
|
|
68
|
+
let article = appframe.article?.id;
|
|
69
|
+
let { hostname } = await getLoginInfo();
|
|
70
|
+
let dom = new JSDOM(html);
|
|
71
|
+
let nodesToRemove = [];
|
|
72
|
+
let mainScriptAdded = false;
|
|
73
|
+
dom.window.document.querySelectorAll("script").forEach((script) => {
|
|
74
|
+
if (script.src?.startsWith(`/file/article/script/${article}/main`)) {
|
|
75
|
+
let mainScript = dom.window.document.createElement("script");
|
|
76
|
+
mainScript.type = "module";
|
|
77
|
+
mainScript.src = entry;
|
|
78
|
+
script.insertAdjacentElement("beforebegin", mainScript);
|
|
79
|
+
nodesToRemove.push(script);
|
|
80
|
+
mainScriptAdded = true;
|
|
81
|
+
}
|
|
82
|
+
else if (script.src?.includes("bugsnag")) {
|
|
83
|
+
nodesToRemove.push(script);
|
|
84
|
+
}
|
|
85
|
+
else if (script.textContent?.includes("bugsnagOptions") ||
|
|
86
|
+
script.textContent?.includes("web-vitals") ||
|
|
87
|
+
script.textContent?.includes("serviceWorker.register")) {
|
|
88
|
+
nodesToRemove.push(script);
|
|
89
|
+
}
|
|
90
|
+
else if (script.textContent?.includes("af.article.i18n")) {
|
|
91
|
+
// There will be lots of strings that will be translated in dev, but not in production (e.g. grid localization for apps without grid),
|
|
92
|
+
// which means the strings will not be in the base strings. Since the dev server runs on HTTP 1, this causes lots
|
|
93
|
+
// of slow HTTP requests. To fix this, we cache them locally, and inject them here.
|
|
94
|
+
let cachedStrings = getStringCache();
|
|
95
|
+
let localizeScript = dom.window.document.createElement("script");
|
|
96
|
+
localizeScript.textContent = `Object.assign(af.article.i18n, ${JSON.stringify(cachedStrings)})`;
|
|
97
|
+
script.insertAdjacentElement("afterend", localizeScript);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
if (!mainScriptAdded) {
|
|
101
|
+
let mainScript = dom.window.document.createElement("script");
|
|
102
|
+
mainScript.type = "module";
|
|
103
|
+
mainScript.src = entry;
|
|
104
|
+
dom.window.document.body.appendChild(mainScript);
|
|
105
|
+
}
|
|
106
|
+
dom.window.document.querySelectorAll("link").forEach((link) => {
|
|
107
|
+
if (link.rel === "stylesheet" && link.href?.startsWith(`/file/article/style/${article}`)) {
|
|
108
|
+
nodesToRemove.push(link);
|
|
109
|
+
}
|
|
110
|
+
else if (link.rel === "prefetch" && link.href?.startsWith(`/file/article`)) {
|
|
111
|
+
nodesToRemove.push(link);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
nodesToRemove.forEach((node) => node.remove());
|
|
115
|
+
dom.window.document.querySelectorAll("a").forEach((anchor) => {
|
|
116
|
+
if (anchor.href?.startsWith("/") && !anchor.href?.startsWith(`/${article}`)) {
|
|
117
|
+
anchor.href = `https://${hostname}${anchor.href}`;
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return dom.serialize();
|
|
121
|
+
}
|
|
57
122
|
async function getArticleHtml() {
|
|
58
123
|
let { hostname, username, password } = await getLoginInfo();
|
|
59
124
|
let article = appframe.article?.id;
|
|
125
|
+
console.log(hostname);
|
|
60
126
|
let client = new Client(hostname);
|
|
61
|
-
|
|
127
|
+
console.log(article);
|
|
128
|
+
let re = await client.login(username, password);
|
|
129
|
+
console.log("login", username, password, re);
|
|
62
130
|
let response = await client.afFetch(`/${article}`, {
|
|
63
131
|
timeout: 30000,
|
|
64
132
|
});
|
|
133
|
+
console.log("afFetch", response.status);
|
|
65
134
|
if (response.ok) {
|
|
66
|
-
|
|
67
|
-
let entry;
|
|
68
|
-
if (await exists(resolve(process.cwd(), "./src/index.tsx"))) {
|
|
69
|
-
entry = "/src/index.tsx";
|
|
70
|
-
}
|
|
71
|
-
else if (await exists(resolve(process.cwd(), "./src/index.ts"))) {
|
|
72
|
-
entry = "/src/index.ts";
|
|
73
|
-
}
|
|
74
|
-
else if (await exists(resolve(process.cwd(), "./src/index.js"))) {
|
|
75
|
-
entry = "/src/index.js";
|
|
76
|
-
}
|
|
77
|
-
let dom = new JSDOM(html);
|
|
78
|
-
let nodesToRemove = [];
|
|
79
|
-
dom.window.document.querySelectorAll("script").forEach((script) => {
|
|
80
|
-
if (script.src?.startsWith(`/file/article/script/${article}/main`)) {
|
|
81
|
-
let mainScript = dom.window.document.createElement("script");
|
|
82
|
-
mainScript.type = "module";
|
|
83
|
-
mainScript.src = entry;
|
|
84
|
-
script.insertAdjacentElement("beforebegin", mainScript);
|
|
85
|
-
nodesToRemove.push(script);
|
|
86
|
-
}
|
|
87
|
-
else if (script.src?.includes("bugsnag")) {
|
|
88
|
-
nodesToRemove.push(script);
|
|
89
|
-
}
|
|
90
|
-
else if (script.textContent?.includes("bugsnagOptions") ||
|
|
91
|
-
script.textContent?.includes("web-vitals") ||
|
|
92
|
-
script.textContent?.includes("serviceWorker.register")) {
|
|
93
|
-
nodesToRemove.push(script);
|
|
94
|
-
}
|
|
95
|
-
else if (script.textContent?.includes("af.article.i18n")) {
|
|
96
|
-
let cachedStrings = getStringCache();
|
|
97
|
-
let localizeScript = dom.window.document.createElement("script");
|
|
98
|
-
localizeScript.textContent = `Object.assign(af.article.i18n, ${JSON.stringify(cachedStrings)})`;
|
|
99
|
-
script.insertAdjacentElement("afterend", localizeScript);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
dom.window.document.querySelectorAll("link").forEach((link) => {
|
|
103
|
-
if (link.rel === "stylesheet" && link.href?.startsWith(`/file/article/style/${article}`)) {
|
|
104
|
-
nodesToRemove.push(link);
|
|
105
|
-
}
|
|
106
|
-
else if (link.rel === "prefetch" && link.href?.startsWith(`/file/article`)) {
|
|
107
|
-
nodesToRemove.push(link);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
nodesToRemove.forEach((node) => node.remove());
|
|
111
|
-
dom.window.document.querySelectorAll("a").forEach((anchor) => {
|
|
112
|
-
if (anchor.href?.startsWith("/") && !anchor.href?.startsWith(`/${article}`)) {
|
|
113
|
-
anchor.href = `https://${hostname}${anchor.href}`;
|
|
114
|
-
}
|
|
115
|
-
});
|
|
116
|
-
return dom.serialize();
|
|
135
|
+
return await response.text();
|
|
117
136
|
}
|
|
118
137
|
throw Error(`Failed to get article '${article}' from '${hostname}': ${response.status} ${response.statusText}`);
|
|
119
138
|
}
|
|
@@ -134,6 +153,22 @@ async function getCachedHtml(age) {
|
|
|
134
153
|
}
|
|
135
154
|
return "";
|
|
136
155
|
}
|
|
156
|
+
async function getCachedOrArticleHtml(skipCache = false) {
|
|
157
|
+
let html = "";
|
|
158
|
+
let age = Math.round(await getCacheAge());
|
|
159
|
+
if (!skipCache && age > 0) {
|
|
160
|
+
html = await getCachedHtml(age);
|
|
161
|
+
}
|
|
162
|
+
if (!html) {
|
|
163
|
+
html = await getArticleHtml();
|
|
164
|
+
if (!(await exists(cacheFile))) {
|
|
165
|
+
await mkdir(cachePath, { recursive: true });
|
|
166
|
+
}
|
|
167
|
+
await writeFile(cacheFile, html, { encoding: "utf-8" });
|
|
168
|
+
age = 0;
|
|
169
|
+
}
|
|
170
|
+
return { age, html };
|
|
171
|
+
}
|
|
137
172
|
export function createDevMiddleware(vite) {
|
|
138
173
|
return async (req, res, next) => {
|
|
139
174
|
const url = req.originalUrl;
|
|
@@ -147,19 +182,9 @@ export function createDevMiddleware(vite) {
|
|
|
147
182
|
// Unless the browser is explicitly disabling cache by setting the Cache-Control header
|
|
148
183
|
// to "no-cache", we cache the generated HTML for up to 3 hours
|
|
149
184
|
let cacheControl = req.headers["cache-control"];
|
|
150
|
-
let html = "";
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
html = await getCachedHtml(age);
|
|
154
|
-
}
|
|
155
|
-
if (!html) {
|
|
156
|
-
html = await getArticleHtml();
|
|
157
|
-
html = await vite.transformIndexHtml(url ?? "", html);
|
|
158
|
-
if (!(await exists(cacheFile))) {
|
|
159
|
-
await mkdir(cachePath, { recursive: true });
|
|
160
|
-
}
|
|
161
|
-
await writeFile(cacheFile, html, { encoding: "utf-8" });
|
|
162
|
-
}
|
|
185
|
+
let { age, html } = await getCachedOrArticleHtml(cacheControl === "no-cache");
|
|
186
|
+
html = await transformArticleHtml(html);
|
|
187
|
+
html = await vite.transformIndexHtml(url ?? "", html);
|
|
163
188
|
res.statusCode = 200;
|
|
164
189
|
res.setHeader("Content-Type", "text/html");
|
|
165
190
|
res.setHeader("Cache-Control", "max-age=10800000");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olenbetong/appframe-vite",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.6",
|
|
4
4
|
"description": "Tools to use and deploy Vite applications to Appframe",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"author": "Bjørnar Vister Hansen <bvh@olenbetong.no>",
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@olenbetong/appframe-data": "0.9.
|
|
22
|
+
"@olenbetong/appframe-data": "0.9.3",
|
|
23
23
|
"body-parser": "^1.20.2",
|
|
24
24
|
"chalk": "^5.3.0",
|
|
25
25
|
"chokidar": "^3.5.3",
|
|
@@ -33,16 +33,12 @@
|
|
|
33
33
|
"typescript": "^5.1.6"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"express": "^4.18.2",
|
|
37
36
|
"vite": "^4.4.9"
|
|
38
37
|
},
|
|
39
38
|
"optionalDependencies": {
|
|
40
|
-
"@types/express": "^4.17.17",
|
|
41
|
-
"@types/express-http-proxy": "^1.6.3",
|
|
42
39
|
"@types/tcp-port-used": "^1.0.1",
|
|
43
|
-
"express-http-proxy": "^1.6.3",
|
|
44
40
|
"open": "^9.1.0",
|
|
45
41
|
"tcp-port-used": "^1.0.2"
|
|
46
42
|
},
|
|
47
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "54e7bf8d61f5f3ada6a635175d6c6fa564b2e62b"
|
|
48
44
|
}
|