feat: reduce firebase blocking time
- use esm format - defer loading with type="module" - upgrade from v8.10.0 to v9.23.0 - allow homepage/taxonomy/term log
This commit is contained in:
@@ -1,4 +0,0 @@
|
|||||||
document.getElementById("button_likes") &&
|
|
||||||
document.getElementById("button_likes").addEventListener("click", () => {
|
|
||||||
process_article();
|
|
||||||
});
|
|
||||||
+148
-202
@@ -1,208 +1,154 @@
|
|||||||
const pageScriptElement = document.currentScript;
|
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.23.0/firebase-app.js";
|
||||||
const configEl = document.getElementById("firebase-config");
|
import {
|
||||||
|
getFirestore,
|
||||||
|
doc,
|
||||||
|
getDoc,
|
||||||
|
setDoc,
|
||||||
|
updateDoc,
|
||||||
|
increment,
|
||||||
|
onSnapshot,
|
||||||
|
} from "https://www.gstatic.com/firebasejs/9.23.0/firebase-firestore.js";
|
||||||
|
import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/9.23.0/firebase-auth.js";
|
||||||
|
|
||||||
|
let app, db, auth, oids;
|
||||||
|
try {
|
||||||
|
const configEl = document.getElementById("firebase-config");
|
||||||
|
if (!configEl?.textContent) {
|
||||||
|
throw new Error("Firebase config element not found");
|
||||||
|
}
|
||||||
|
|
||||||
if (!configEl?.textContent) {
|
|
||||||
console.error("Firebase config element not found");
|
|
||||||
document
|
|
||||||
.querySelectorAll(
|
|
||||||
'[id^="views_"], [id^="likes_"], #button_likes_heart, #button_likes_emtpty_heart, #button_likes_text',
|
|
||||||
)
|
|
||||||
.forEach((el) => el.remove());
|
|
||||||
} else {
|
|
||||||
const data = JSON.parse(configEl.textContent);
|
const data = JSON.parse(configEl.textContent);
|
||||||
const oid = data.oids?.views;
|
app = initializeApp(data.config);
|
||||||
const oid_likes = data.oids?.likes;
|
|
||||||
|
|
||||||
let liked_page = false;
|
oids = {
|
||||||
const id = oid ? oid.replaceAll("/", "-") : oid;
|
views: configEl.getAttribute("data-views"),
|
||||||
const id_likes = oid_likes ? oid_likes.replaceAll("/", "-") : oid_likes;
|
likes: configEl.getAttribute("data-likes"),
|
||||||
|
|
||||||
function numberWithCommas(x) {
|
|
||||||
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleLoaders(node) {
|
|
||||||
var classesString = node.className;
|
|
||||||
if (classesString == "") return;
|
|
||||||
var classes = classesString.split(" ");
|
|
||||||
for (var i in classes) {
|
|
||||||
node.classList.toggle(classes[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var update_views = function (node, id) {
|
|
||||||
db.collection("views")
|
|
||||||
.doc(id)
|
|
||||||
.onSnapshot((doc) => {
|
|
||||||
var data = doc.data();
|
|
||||||
if (data) {
|
|
||||||
node.innerText = numberWithCommas(data.views);
|
|
||||||
} else {
|
|
||||||
node.innerText = 0;
|
|
||||||
}
|
|
||||||
toggleLoaders(node);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var update_likes = function (node, id) {
|
db = getFirestore(app);
|
||||||
db.collection("likes")
|
auth = getAuth(app);
|
||||||
.doc(id)
|
} catch (e) {
|
||||||
.onSnapshot((doc) => {
|
console.error("Firebase initialization failed:", e.message);
|
||||||
var data = doc.data();
|
throw e;
|
||||||
if (data) {
|
|
||||||
node.innerText = numberWithCommas(data.likes);
|
|
||||||
} else {
|
|
||||||
node.innerText = 0;
|
|
||||||
}
|
|
||||||
toggleLoaders(node);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof auth !== "undefined") {
|
|
||||||
const viewed = localStorage.getItem(id);
|
|
||||||
|
|
||||||
if (!viewed && id) {
|
|
||||||
auth
|
|
||||||
.signInAnonymously()
|
|
||||||
.then(() => {
|
|
||||||
const docRef = db.collection("views").doc(id);
|
|
||||||
localStorage.setItem(id, true);
|
|
||||||
docRef
|
|
||||||
.get()
|
|
||||||
.then((doc) => {
|
|
||||||
if (doc.exists) {
|
|
||||||
db.collection("views")
|
|
||||||
.doc(id)
|
|
||||||
.update({
|
|
||||||
views: firebase.firestore.FieldValue.increment(1),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
db.collection("views").doc(id).set({ views: 1 });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log("Error getting document:", error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
const errorCode = error.code;
|
|
||||||
const errorMessage = error.message;
|
|
||||||
console.error(errorCode, errorMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const liked = localStorage.getItem(id_likes);
|
|
||||||
|
|
||||||
if (liked) {
|
|
||||||
liked_page = true;
|
|
||||||
document.querySelectorAll("span[id='button_likes_heart']")[0].style.display = "";
|
|
||||||
document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display = "none";
|
|
||||||
document.querySelectorAll("span[id='button_likes_text']")[0].innerText = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
auth
|
|
||||||
.signInAnonymously()
|
|
||||||
.then(() => {
|
|
||||||
var views_nodes = document.querySelectorAll("span[id^='views_']");
|
|
||||||
|
|
||||||
for (var i in views_nodes) {
|
|
||||||
var node = views_nodes[i];
|
|
||||||
var id = node.id ? node.id.replaceAll("/", "-") : node.id;
|
|
||||||
if (id) {
|
|
||||||
update_views(node, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var likes_nodes = document.querySelectorAll("span[id^='likes_']");
|
|
||||||
|
|
||||||
for (var i in likes_nodes) {
|
|
||||||
var node = likes_nodes[i];
|
|
||||||
var id = node.id ? node.id.replaceAll("/", "-") : node.id;
|
|
||||||
if (id) {
|
|
||||||
update_likes(node, id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
var errorCode = error.code;
|
|
||||||
var errorMessage = error.message;
|
|
||||||
console.error(errorCode, errorMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function like_article(id_likes) {
|
|
||||||
auth
|
|
||||||
.signInAnonymously()
|
|
||||||
.then(() => {
|
|
||||||
const docRef = db.collection("likes").doc(id_likes);
|
|
||||||
docRef
|
|
||||||
.get()
|
|
||||||
.then((doc) => {
|
|
||||||
liked_page = true;
|
|
||||||
localStorage.setItem(id_likes, true);
|
|
||||||
document.querySelectorAll("span[id='button_likes_heart']")[0].style.display = "";
|
|
||||||
document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display = "none";
|
|
||||||
document.querySelectorAll("span[id='button_likes_text']")[0].innerText = "";
|
|
||||||
if (doc.exists) {
|
|
||||||
db.collection("likes")
|
|
||||||
.doc(id_likes)
|
|
||||||
.update({
|
|
||||||
likes: firebase.firestore.FieldValue.increment(1),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
db.collection("likes").doc(id_likes).set({ likes: 1 });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log("Error getting document:", error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
const errorCode = error.code;
|
|
||||||
const errorMessage = error.message;
|
|
||||||
console.error(errorCode, errorMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove_like_article(id_likes) {
|
|
||||||
auth
|
|
||||||
.signInAnonymously()
|
|
||||||
.then(() => {
|
|
||||||
const docRef = db.collection("likes").doc(id_likes);
|
|
||||||
docRef
|
|
||||||
.get()
|
|
||||||
.then((doc) => {
|
|
||||||
liked_page = false;
|
|
||||||
localStorage.removeItem(id_likes);
|
|
||||||
document.querySelectorAll("span[id='button_likes_heart']")[0].style.display = "none";
|
|
||||||
document.querySelectorAll("span[id='button_likes_emtpty_heart']")[0].style.display = "";
|
|
||||||
document.querySelectorAll("span[id='button_likes_text']")[0].innerText = "\xa0Like";
|
|
||||||
if (doc.exists) {
|
|
||||||
db.collection("likes")
|
|
||||||
.doc(id_likes)
|
|
||||||
.update({
|
|
||||||
likes: firebase.firestore.FieldValue.increment(-1),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
db.collection("likes").doc(id_likes).set({ likes: 0 });
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.log("Error getting document:", error);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
const errorCode = error.code;
|
|
||||||
const errorMessage = error.message;
|
|
||||||
console.error(errorCode, errorMessage);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.process_article = function () {
|
|
||||||
if (!liked_page) {
|
|
||||||
like_article(id_likes);
|
|
||||||
} else {
|
|
||||||
remove_like_article(id_likes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const id = oids?.views?.replaceAll("/", "-");
|
||||||
|
const id_likes = oids?.likes?.replaceAll("/", "-");
|
||||||
|
let liked = false;
|
||||||
|
let authReady = false;
|
||||||
|
|
||||||
|
function formatNumber(n) {
|
||||||
|
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleLoaders(node) {
|
||||||
|
var classesString = node.className;
|
||||||
|
if (classesString == "") return;
|
||||||
|
var classes = classesString.split(" ");
|
||||||
|
for (var i in classes) {
|
||||||
|
node.classList.toggle(classes[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDisplay(collection, nodeId) {
|
||||||
|
const node = document.getElementById(nodeId);
|
||||||
|
if (!node) return;
|
||||||
|
|
||||||
|
const docId = nodeId.replaceAll("/", "-");
|
||||||
|
onSnapshot(
|
||||||
|
doc(db, collection, docId),
|
||||||
|
(snapshot) => {
|
||||||
|
node.innerText = snapshot.exists() ? formatNumber(snapshot.data()[collection]) : 0;
|
||||||
|
toggleLoaders(node);
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
console.error("Firebase snapshot update failed:", error);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function recordView(id) {
|
||||||
|
if (!id || localStorage.getItem(id)) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const ref = doc(db, "views", id);
|
||||||
|
const snap = await getDoc(ref);
|
||||||
|
|
||||||
|
snap.exists() ? await updateDoc(ref, { views: increment(1) }) : await setDoc(ref, { views: 1 });
|
||||||
|
|
||||||
|
localStorage.setItem(id, true);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Record view operation failed:", e.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateButton(isLiked) {
|
||||||
|
const hearts = document.querySelectorAll("span[id='button_likes_heart']");
|
||||||
|
const empties = document.querySelectorAll("span[id='button_likes_emtpty_heart']");
|
||||||
|
const texts = document.querySelectorAll("span[id='button_likes_text']");
|
||||||
|
|
||||||
|
hearts.forEach((el) => {
|
||||||
|
el.style.display = isLiked ? "" : "none";
|
||||||
|
});
|
||||||
|
empties.forEach((el) => {
|
||||||
|
el.style.display = isLiked ? "none" : "";
|
||||||
|
});
|
||||||
|
texts.forEach((el) => {
|
||||||
|
el.innerText = isLiked ? "" : "\xa0Like";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function toggleLike(add) {
|
||||||
|
if (!id_likes || !authReady) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const ref = doc(db, "likes", id_likes);
|
||||||
|
const snap = await getDoc(ref);
|
||||||
|
|
||||||
|
liked = add;
|
||||||
|
add ? localStorage.setItem(id_likes, true) : localStorage.removeItem(id_likes);
|
||||||
|
updateButton(add);
|
||||||
|
|
||||||
|
snap.exists()
|
||||||
|
? await updateDoc(ref, { likes: increment(add ? 1 : -1) })
|
||||||
|
: await setDoc(ref, { likes: add ? 1 : 0 });
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Like operation failed:", e.message);
|
||||||
|
liked = !add;
|
||||||
|
add ? localStorage.removeItem(id_likes) : localStorage.setItem(id_likes, true);
|
||||||
|
updateButton(!add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signInAnonymously(auth)
|
||||||
|
.then(() => {
|
||||||
|
authReady = true;
|
||||||
|
|
||||||
|
document.querySelectorAll("span[id^='views_']").forEach((node) => {
|
||||||
|
if (node.id) updateDisplay("views", node.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll("span[id^='likes_']").forEach((node) => {
|
||||||
|
if (node.id) updateDisplay("likes", node.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
recordView(id);
|
||||||
|
|
||||||
|
if (id_likes && localStorage.getItem(id_likes)) {
|
||||||
|
liked = true;
|
||||||
|
updateButton(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const likeButton = document.getElementById("button_likes");
|
||||||
|
if (likeButton) {
|
||||||
|
likeButton.addEventListener("click", () => {
|
||||||
|
toggleLike(!liked);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Firebase anonymous sign-in failed:", error.message);
|
||||||
|
authReady = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.process_article = () => toggleLike(!liked);
|
||||||
|
|||||||
@@ -154,7 +154,6 @@
|
|||||||
{{ if .Site.Params.rtl | default false }}
|
{{ if .Site.Params.rtl | default false }}
|
||||||
{{ $jsResources = $jsResources | append (resources.Get "js/rtl.js") }}
|
{{ $jsResources = $jsResources | append (resources.Get "js/rtl.js") }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ $jsResources = $jsResources | append (resources.Get "js/button-likes.js") }}
|
|
||||||
{{ $jsResources = $jsResources | append (resources.Get "js/katex-render.js") }}
|
{{ $jsResources = $jsResources | append (resources.Get "js/katex-render.js") }}
|
||||||
{{ $jsResources = $jsResources | append (resources.Get "js/print-support.js") }}
|
{{ $jsResources = $jsResources | append (resources.Get "js/print-support.js") }}
|
||||||
{{ if $jsResources }}
|
{{ if $jsResources }}
|
||||||
|
|||||||
@@ -154,7 +154,12 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
{{/* Firebase */}}
|
||||||
{{ if site.Params.firebase.apiKey }}
|
{{ if site.Params.firebase.apiKey }}
|
||||||
|
{{ $firebase := resources.Get "js/firebase.js" }}
|
||||||
|
{{ $firebase = $firebase | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
|
||||||
|
<script type="module" src="{{ $firebase.RelPermalink }}" integrity="{{ $firebase.Data.Integrity }}"></script>
|
||||||
|
|
||||||
{{ if in (slice "page" "section") .Kind }}
|
{{ if in (slice "page" "section") .Kind }}
|
||||||
{{ $translations := .AllTranslations }}
|
{{ $translations := .AllTranslations }}
|
||||||
{{ with .File }}
|
{{ with .File }}
|
||||||
@@ -169,48 +174,26 @@
|
|||||||
{{ else if eq .Kind "taxonomy" }}
|
{{ else if eq .Kind "taxonomy" }}
|
||||||
{{ partial "inline/firebase-config.html" (dict "views" (printf "views_taxonomy_%s" .Data.Plural) "likes" (printf "likes_taxonomy_%s" .Data.Plural)) }}
|
{{ partial "inline/firebase-config.html" (dict "views" (printf "views_taxonomy_%s" .Data.Plural) "likes" (printf "likes_taxonomy_%s" .Data.Plural)) }}
|
||||||
{{ else if eq .Kind "home" }}
|
{{ else if eq .Kind "home" }}
|
||||||
{{ partial "inline/firebase-config.html" (dict "views" (printf "views_home") "likes" (printf "likes_home")) }}
|
{{ partial "inline/firebase-config.html" (dict "views" "views_home" "likes" "likes_home") }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
|
|
||||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-firestore.js"></script>
|
|
||||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script>
|
|
||||||
<script>
|
|
||||||
const firebaseConfig = {
|
|
||||||
apiKey: {{ site.Params.firebase.apiKey }},
|
|
||||||
authDomain: {{ site.Params.firebase.authDomain }},
|
|
||||||
projectId: {{ site.Params.firebase.projectId }},
|
|
||||||
storageBucket: {{ site.Params.firebase.storageBucket }},
|
|
||||||
messagingSenderId: {{ site.Params.firebase.messagingSenderId }},
|
|
||||||
appId: {{ site.Params.firebase.appId }},
|
|
||||||
measurementId: {{ site.Params.firebase.measurementId }}
|
|
||||||
};
|
|
||||||
var app = firebase.initializeApp(firebaseConfig);
|
|
||||||
var db = firebase.firestore();
|
|
||||||
var auth = firebase.auth();
|
|
||||||
</script> {{/* */}}
|
|
||||||
{{ $firebase := resources.Get "js/firebase.js" }}
|
|
||||||
{{ $firebase = $firebase | resources.Minify | resources.Fingerprint (site.Params.fingerprintAlgorithm | default "sha512") }}
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
src="{{ $firebase.RelPermalink }}"
|
|
||||||
integrity="{{ $firebase.Data.Integrity }}"></script>
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ define "partials/inline/firebase-config.html" }}
|
{{ define "_partials/inline/firebase-config.html" }}
|
||||||
<script id="firebase-config" type="application/json">
|
<script id="firebase-config"
|
||||||
{
|
type="application/json"
|
||||||
"config": {
|
data-views="{{ .views }}"
|
||||||
"apiKey": "{{ site.Params.firebase.apiKey }}",
|
data-likes="{{ .likes }}">
|
||||||
"authDomain": "{{ site.Params.firebase.authDomain }}",
|
{
|
||||||
"projectId": "{{ site.Params.firebase.projectId }}",
|
"config": {
|
||||||
"storageBucket": "{{ site.Params.firebase.storageBucket }}",
|
"apiKey": "{{ site.Params.firebase.apiKey }}",
|
||||||
"messagingSenderId": "{{ site.Params.firebase.messagingSenderId }}",
|
"authDomain": "{{ site.Params.firebase.authDomain }}",
|
||||||
"appId": "{{ site.Params.firebase.appId }}",
|
"projectId": "{{ site.Params.firebase.projectId }}",
|
||||||
"measurementId": "{{ site.Params.firebase.measurementId }}"
|
"storageBucket": "{{ site.Params.firebase.storageBucket }}",
|
||||||
},
|
"messagingSenderId": "{{ site.Params.firebase.messagingSenderId }}",
|
||||||
"oids": {{ . | jsonify | safeJS }}
|
"appId": "{{ site.Params.firebase.appId }}",
|
||||||
|
"measurementId": "{{ site.Params.firebase.measurementId }}"
|
||||||
}
|
}
|
||||||
</script>
|
}
|
||||||
|
</script>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|||||||
Reference in New Issue
Block a user