fix: add better perf marks / logging system
This commit is contained in:
parent
9ffe091598
commit
51040b3d96
|
@ -6,9 +6,9 @@
|
|||
"module": "index.js",
|
||||
"type": "module",
|
||||
"files": [
|
||||
"database.js",
|
||||
"index.js",
|
||||
"picker.js"
|
||||
"database.js*",
|
||||
"index.js*",
|
||||
"picker.js*"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production rollup -c",
|
||||
|
@ -70,6 +70,7 @@
|
|||
"indexedDB",
|
||||
"IDBKeyRange",
|
||||
"matchMedia",
|
||||
"performance",
|
||||
"requestAnimationFrame",
|
||||
"requestIdleCallback"
|
||||
]
|
||||
|
|
|
@ -18,6 +18,8 @@ const baseConfig = {
|
|||
cjs(),
|
||||
json(),
|
||||
replace({
|
||||
'process.env.NODE_ENV': dev ? '"development"' : '"production"',
|
||||
'process.env.PERF': !!process.env.PERF,
|
||||
'process.env.VERSIONS_AND_TEST_EMOJI': JSON.stringify(versionsAndTestEmoji)
|
||||
}),
|
||||
replace({
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
isEmpty, hasData, loadData, getEmojiByGroup,
|
||||
getEmojiBySearchPrefix, getEmojiByShortcode, getEmojiByUnicode
|
||||
} from './idbInterface'
|
||||
import { log } from '../shared/log'
|
||||
|
||||
export default class Database {
|
||||
constructor ({ dataSource = DEFAULT_DATA_SOURCE, locale = DEFAULT_LOCALE } = {}) {
|
||||
|
@ -37,7 +38,7 @@ export default class Database {
|
|||
const eTag = headResponse.headers.get('etag')
|
||||
warnETag(eTag)
|
||||
if (eTag && await hasData(this._db, url, eTag)) {
|
||||
console.log('Database already populated')
|
||||
log('Database already populated')
|
||||
return // fast init, data is already loaded
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ export default class Database {
|
|||
eTag = await jsonChecksum(emojiBaseData)
|
||||
}
|
||||
if (!empty && await hasData(this._db, url, eTag)) {
|
||||
console.log('Database already populated')
|
||||
log('Database already populated')
|
||||
return // data already loaded
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
STORE_META
|
||||
} from './constants'
|
||||
import { transformEmojiBaseData } from './transformEmojiBaseData'
|
||||
import { mark, stop } from '../shared/marks'
|
||||
|
||||
export async function isEmpty (db) {
|
||||
return !(await get(db, STORE_META, KEY_URL))
|
||||
|
@ -17,59 +18,64 @@ export async function hasData (db, url, eTag) {
|
|||
}
|
||||
|
||||
export async function loadData (db, emojiBaseData, url, eTag) {
|
||||
const transformedData = transformEmojiBaseData(emojiBaseData)
|
||||
const [oldETag, oldUrl] = await get(db, STORE_META, [KEY_ETAG, KEY_URL])
|
||||
if (oldETag === eTag && oldUrl === url) {
|
||||
return
|
||||
}
|
||||
await dbPromise(db, [STORE_EMOJI, STORE_META], MODE_READWRITE, ([emojiStore, metaStore]) => {
|
||||
let oldETag
|
||||
let oldUrl
|
||||
let oldKeys
|
||||
let todo = 0
|
||||
|
||||
function checkFetched () {
|
||||
if (++todo === 3) {
|
||||
onFetched()
|
||||
}
|
||||
mark('loadData')
|
||||
try {
|
||||
const transformedData = transformEmojiBaseData(emojiBaseData)
|
||||
const [oldETag, oldUrl] = await get(db, STORE_META, [KEY_ETAG, KEY_URL])
|
||||
if (oldETag === eTag && oldUrl === url) {
|
||||
return
|
||||
}
|
||||
await dbPromise(db, [STORE_EMOJI, STORE_META], MODE_READWRITE, ([emojiStore, metaStore]) => {
|
||||
let oldETag
|
||||
let oldUrl
|
||||
let oldKeys
|
||||
let todo = 0
|
||||
|
||||
function onFetched () {
|
||||
if (oldETag === eTag && oldUrl === url) {
|
||||
// check again within the transaction to guard against concurrency, e.g. multiple browser tabs
|
||||
return
|
||||
}
|
||||
if (oldKeys.length) {
|
||||
for (const key of oldKeys) {
|
||||
emojiStore.delete(key)
|
||||
function checkFetched () {
|
||||
if (++todo === 3) {
|
||||
onFetched()
|
||||
}
|
||||
}
|
||||
insertData()
|
||||
}
|
||||
|
||||
function insertData () {
|
||||
for (const data of transformedData) {
|
||||
emojiStore.put(data)
|
||||
function onFetched () {
|
||||
if (oldETag === eTag && oldUrl === url) {
|
||||
// check again within the transaction to guard against concurrency, e.g. multiple browser tabs
|
||||
return
|
||||
}
|
||||
if (oldKeys.length) {
|
||||
for (const key of oldKeys) {
|
||||
emojiStore.delete(key)
|
||||
}
|
||||
}
|
||||
insertData()
|
||||
}
|
||||
metaStore.put(eTag, KEY_ETAG)
|
||||
metaStore.put(url, KEY_URL)
|
||||
}
|
||||
|
||||
metaStore.get(KEY_ETAG).onsuccess = e => {
|
||||
oldETag = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
function insertData () {
|
||||
for (const data of transformedData) {
|
||||
emojiStore.put(data)
|
||||
}
|
||||
metaStore.put(eTag, KEY_ETAG)
|
||||
metaStore.put(url, KEY_URL)
|
||||
}
|
||||
|
||||
metaStore.get(KEY_URL).onsuccess = e => {
|
||||
oldUrl = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
metaStore.get(KEY_ETAG).onsuccess = e => {
|
||||
oldETag = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
|
||||
emojiStore.getAllKeys().onsuccess = e => {
|
||||
oldKeys = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
})
|
||||
metaStore.get(KEY_URL).onsuccess = e => {
|
||||
oldUrl = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
|
||||
emojiStore.getAllKeys().onsuccess = e => {
|
||||
oldKeys = e.target.result
|
||||
checkFetched()
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
stop('loadData')
|
||||
}
|
||||
}
|
||||
|
||||
export async function getEmojiByGroup (db, group) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { MIN_SEARCH_TEXT_LENGTH } from '../shared/constants'
|
||||
import { mark, stop } from '../shared/marks'
|
||||
|
||||
function extractTokens (annotation) {
|
||||
return annotation
|
||||
|
@ -11,7 +12,8 @@ function extractTokens (annotation) {
|
|||
}
|
||||
|
||||
export function transformEmojiBaseData (emojiBaseData) {
|
||||
return emojiBaseData.map(({ annotation, emoticon, group, order, shortcodes, tags, emoji, version }) => {
|
||||
mark('transformEmojiBaseData')
|
||||
const res = emojiBaseData.map(({ annotation, emoticon, group, order, shortcodes, tags, emoji, version }) => {
|
||||
const tokens = [...new Set(
|
||||
[
|
||||
...shortcodes.map(extractTokens).flat(),
|
||||
|
@ -38,4 +40,6 @@ export function transformEmojiBaseData (emojiBaseData) {
|
|||
}
|
||||
return res
|
||||
})
|
||||
stop('transformEmojiBaseData')
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import { calculateTextWidth } from '../../utils/calculateTextWidth'
|
|||
import { hasZwj } from '../../utils/hasZwj'
|
||||
import { thunk } from '../../utils/thunk'
|
||||
import { emojiSupportLevel, supportedZwjEmojis } from '../../utils/emojiSupport'
|
||||
import { log } from '../../../shared/log'
|
||||
import { mark, stop } from '../../../shared/marks'
|
||||
|
||||
let database
|
||||
let currentEmojis = []
|
||||
|
@ -59,6 +61,7 @@ $: {
|
|||
}
|
||||
|
||||
function checkZwjSupport (zwjEmojisToCheck) {
|
||||
mark('checkZwjSupport')
|
||||
const rootNode = rootElement.getRootNode()
|
||||
for (const emoji of zwjEmojisToCheck) {
|
||||
const domNode = rootNode.getElementById(`emoji-${emoji.unicode}`)
|
||||
|
@ -68,9 +71,10 @@ function checkZwjSupport (zwjEmojisToCheck) {
|
|||
const supported = emojiWidth.toFixed(1) === baselineEmojiWidth.toFixed(1)
|
||||
supportedZwjEmojis.set(emoji.unicode, supported)
|
||||
if (!supported) {
|
||||
console.log('Filtered unsupported emoji', emoji.unicode)
|
||||
log('Filtered unsupported emoji', emoji.unicode)
|
||||
}
|
||||
}
|
||||
stop('checkZwjSupport')
|
||||
// force update
|
||||
currentEmojis = currentEmojis // eslint-disable-line no-self-assign
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// get the width of the text inside of a DOM node, via https://stackoverflow.com/a/59525891/680742
|
||||
let range
|
||||
export function calculateTextWidth (node) {
|
||||
range = range || document.createRange()
|
||||
const range = document.createRange()
|
||||
range.selectNode(node.firstChild)
|
||||
return range.getBoundingClientRect().width
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// rather than check every emoji ever, which would be expensive, just check some representatives from the
|
||||
// different emoji releases to determine what the font supports
|
||||
import isEmoji from 'if-emoji'
|
||||
import { mark, stop } from '../../shared/marks'
|
||||
|
||||
const versionsAndTestEmoji = process.env.VERSIONS_AND_TEST_EMOJI
|
||||
|
||||
export function determineEmojiSupportLevel () {
|
||||
mark('determineEmojiSupportLevel')
|
||||
const versionsWithSupports = versionsAndTestEmoji.map(({ version, emoji }) => {
|
||||
const supported = isEmoji(emoji)
|
||||
return {
|
||||
|
@ -12,8 +14,10 @@ export function determineEmojiSupportLevel () {
|
|||
supported
|
||||
}
|
||||
})
|
||||
return versionsWithSupports
|
||||
const res = versionsWithSupports
|
||||
.filter(_ => _.supported)
|
||||
.map(_ => _.version)
|
||||
.sort((a, b) => a < b ? 1 : -1)[0]
|
||||
stop('determineEmojiSupportLevel')
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { determineEmojiSupportLevel } from './determineEmojiSupportLevel'
|
||||
import { log } from '../../shared/log'
|
||||
// Check which emojis we know for sure aren't supported, based on Unicode version level
|
||||
export const emojiSupportLevel = determineEmojiSupportLevel()
|
||||
// determine which emojis containing ZWJ (zero width joiner) characters
|
||||
// are supported (rendered as one glyph) rather than unsupported (rendered as two or more glyphs)
|
||||
export const supportedZwjEmojis = new Map()
|
||||
|
||||
console.log('emoji support level', emojiSupportLevel)
|
||||
log('emoji support level', emojiSupportLevel)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
const rIC = typeof requestIdleCallback === 'function' ? requestIdleCallback : requestAnimationFrame
|
||||
const rIC = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout
|
||||
|
||||
export { rIC as requestIdleCallback }
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
// @rollup/plugin-strip doesn't strip console.logs properly
|
||||
export function log () {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.log(...arguments)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// @rollup/plugin-strip doesn't properly strip performance.mark/measure
|
||||
|
||||
export function mark (str) {
|
||||
if (process.env.NODE_ENV !== 'production' || process.env.PERF) {
|
||||
performance.mark(str)
|
||||
}
|
||||
}
|
||||
|
||||
export function stop (str) {
|
||||
if (process.env.NODE_ENV !== 'production' || process.env.PERF) {
|
||||
performance.measure(str, str)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Ad-hoc test</title>
|
||||
<title>Ad-hoc lite-emoji-picker test</title>
|
||||
<style>
|
||||
.container {
|
||||
height: 300px;
|
||||
|
@ -11,12 +11,12 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ad-hoc test</h1>
|
||||
<h1>Ad-hoc lite-emoji-picker test</h1>
|
||||
<div class="container">
|
||||
<lite-emoji-picker></lite-emoji-picker>
|
||||
</div>
|
||||
<script type="module">
|
||||
import '../index.js'
|
||||
import './index.js'
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue