UNPKG

@alithanar/react-automation-profiler

Version:

Automated React profiling and data visualization using React's Profiler API, Puppeteer, and D3.

188 lines (187 loc) 8.09 kB
Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const d3 = (0, tslib_1.__importStar)(require("d3")); const charts_util_1 = require("./charts.util"); const { INTERACTIONS, RECT, TOTAL } = charts_util_1.MouseEventSelectors; const { ACTUAL_DURATION, BASE_DURATION, NUMBER_OF_INTERACTIONS, TOTAL_AUTOMATION_TIME_ELAPSED, } = charts_util_1.ParagraphMap; (async function () { const height = 500; let width = 1000; let bodyWidth = 0; const margin = { bottom: 20, left: 40, right: 10, top: 10, }; const allJsonValues = []; const carouselIds = []; const interactions = []; const itemIdLengths = []; d3.select('html').on('mousemove', (e) => (0, charts_util_1.updateTooltipPosition)(e)); const jsonFiles = document.querySelectorAll('.json'); const jsonMap = new Map(); jsonFiles.forEach((file) => { const contents = JSON.parse(file.innerHTML); const id = file.id; interactions.push(contents.numberOfInteractions); contents.logs = contents.logs.map((item, index) => { item[ACTUAL_DURATION] = item.actualDuration; item[BASE_DURATION] = item.baseDuration; item.Render = `${index + 1}: ${item.id}`; allJsonValues.push(item[ACTUAL_DURATION], item[BASE_DURATION]); itemIdLengths.push(item.id.length); delete item.actualDuration; delete item.baseDuration; delete item.id; delete item.interactions; delete item.phase; return item; }); jsonMap.set(id, [...contents.logs]); }); const longestId = Math.max(...itemIdLengths); const tallestRect = Math.max(...allJsonValues); const scaleMax = Math.round((tallestRect + tallestRect * 0.05) * 10) / 10; for (const [key, value] of jsonMap.entries()) { const [singularId, multipleId] = key.split('-'); const carouselId = singularId === 'average' ? multipleId : singularId; carouselIds.push(carouselId); let carouselEl = document.getElementById(carouselId); if (!carouselEl) { carouselEl = (0, charts_util_1.createCarousel)(carouselId); const h2El = document.createElement('h2'); let innerText = carouselId.replace(/([^A-Z])([A-Z])/g, '$1 $2'); innerText = innerText[0].toUpperCase() + innerText.substring(1); h2El.innerText = innerText; carouselEl.appendChild(h2El); document.body.appendChild(carouselEl); } const svgEl = (0, charts_util_1.createSVG)(key); carouselEl.appendChild(svgEl); const data = Object.assign(value, { columns: ['Render', BASE_DURATION, ACTUAL_DURATION], }); const totalTimeElapsed = data[data.length - 1].commitTime - data[0].startTime; const potentialWidth = ~~(data.length / 10) * 875 + Math.abs(longestId - 5) * 175 - 1000; width = potentialWidth > 1000 ? potentialWidth : 1000; const potentialBodyWidth = width + 600; if (bodyWidth < potentialBodyWidth) bodyWidth = potentialBodyWidth; svgEl.setAttribute('width', `${width}`); const [groupKey, ...keys] = data.columns; const color = d3.scaleOrdinal().range(['#5A78E6', '#56A6FC', '#52C9F2']); const legend = (svg) => { const g = svg .attr('transform', `translate(${width},0)`) .attr('text-anchor', 'end') .attr('font-family', 'sans-serif') .attr('font-size', 10) .selectAll('g') .data(color.domain().slice().reverse()) .join('g') .attr('transform', (d, i) => `translate(0,${i * 20})`); g.append('rect') .attr('x', -19) .attr('width', 19) .attr('height', 19) .attr('fill', color); g.append('text') .attr('x', -24) .attr('y', 9.5) .attr('dy', '0.35em') .text((d) => d); }; const xAxis = (g) => g .attr('transform', `translate(0,${height - margin.bottom})`) .call(d3.axisBottom(x0).tickSizeOuter(0)) .call((g) => g.select('.domain').remove()); const yAxis = (g) => g .attr('transform', `translate(${margin.left},0)`) .call(d3.axisLeft(y).ticks(null, 's')) .call((g) => g.select('.domain').remove()) .call((g) => g .select('.tick:last-of-type text') .clone() .attr('x', 3) .attr('text-anchor', 'start') .attr('font-weight', 'bold') .text('Milliseconds')); const x0 = d3 .scaleBand() .domain(data.map((d) => d['Render'])) .rangeRound([margin.left, width - margin.right]) .paddingInner(0.1); const x1 = d3 .scaleBand() .domain(keys) .rangeRound([0, x0.bandwidth()]) .padding(0.05); const y = d3 .scaleLinear() .domain([0, scaleMax]) .nice() .rangeRound([height - margin.bottom, margin.top]); const chart = () => { const svg = d3.select(`#chart-${key}`); svg .append('g') .selectAll('g') .data(data) .join('g') .attr('transform', (d) => `translate(${x0(d[groupKey])},0)`) .selectAll('rect') .data((d) => keys.map((key) => ({ key, value: d[key] }))) .join('rect') .attr('x', (d) => x1(d.key)) .attr('y', (d) => y(d.value)) .attr('width', x1.bandwidth()) .attr('height', (d) => y(0) - y(d.value)) .attr('fill', (d) => color(d.key)); svg.append('g').call(xAxis); svg.append('g').call(yAxis); svg.append('g').call(legend); svg .append('text') .attr('transform', `translate(45,${height - margin.bottom + 35})`) .attr('text-align', 'start') .attr('font-size', '11') .attr('font-weight', 'bold') .text('Renders'); svg .append('text') .attr('transform', `translate(${width - 12},${height - margin.bottom + 35})`) .attr('text-anchor', 'end') .attr('font-size', '11') .attr('font-weight', 'bold') .attr('class', 'total') .text(`${TOTAL_AUTOMATION_TIME_ELAPSED}: ${totalTimeElapsed} ms`); svg .append('text') .attr('transform', `translate(${width - 12},${height - margin.bottom + 55})`) .attr('text-anchor', 'end') .attr('font-size', '11') .attr('font-weight', 'bold') .attr('class', 'interactions') .text(`${NUMBER_OF_INTERACTIONS}: ${interactions.shift()}`); svg .select('.total') .on('mouseover', () => (0, charts_util_1.handleMouseOver)(TOTAL)) .on('mouseout', () => (0, charts_util_1.handleMouseOut)()); svg .select('.interactions') .on('mouseover', () => (0, charts_util_1.handleMouseOver)(INTERACTIONS)) .on('mouseout', () => (0, charts_util_1.handleMouseOut)()); svg .selectAll('rect') .on('mouseover', (e) => (0, charts_util_1.handleMouseOver)(RECT, e)) .on('mouseout', (e) => (0, charts_util_1.handleMouseOut)(e)); return svg.node(); }; chart(); } (0, charts_util_1.initCarouselState)(carouselIds); (0, charts_util_1.addExportListener)(); if (bodyWidth) document.body.style.width = `${bodyWidth}px`; })();