Coverage工具擅长查找已使用和未使用的代码。但是,似乎没有一种方法可以只保存或导出使用过的代码。即使隐藏未使用的代码也会有所帮助。
我试图减少应用程序中的Bootstrap CSS数量;该文件超过7000行。获取所用代码的唯一方法是仔细滚动文件,查找绿色部分,然后将该代码复制到新文件。这是耗时且不可靠的。
有不同的方式吗? Chrome 60似乎没有添加此功能。
答案 0 :(得分:12)
你可以用木偶戏
来做到这一点(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage()
//Start sending raw DevTools Protocol commands are sent using `client.send()`
//First off enable the necessary "Domains" for the DevTools commands we care about
const client = await page.target().createCDPSession()
await client.send('Page.enable')
await client.send('DOM.enable')
await client.send('CSS.enable')
const inlineStylesheetIndex = new Set();
client.on('CSS.styleSheetAdded', stylesheet => {
const { header } = stylesheet
if (header.isInline || header.sourceURL === '' || header.sourceURL.startsWith('blob:')) {
inlineStylesheetIndex.add(header.styleSheetId);
}
});
//Start tracking CSS coverage
await client.send('CSS.startRuleUsageTracking')
await page.goto(`http://localhost`)
// const content = await page.content();
// console.log(content);
const rules = await client.send('CSS.takeCoverageDelta')
const usedRules = rules.coverage.filter(rule => {
return rule.used
})
const slices = [];
for (const usedRule of usedRules) {
// console.log(usedRule.styleSheetId)
if (inlineStylesheetIndex.has(usedRule.styleSheetId)) {
continue;
}
const stylesheet = await client.send('CSS.getStyleSheetText', {
styleSheetId: usedRule.styleSheetId
});
slices.push(stylesheet.text.slice(usedRule.startOffset, usedRule.endOffset));
}
console.log(slices.join(''));
await page.close();
await browser.close();
})();
答案 1 :(得分:7)
我与拥有此功能的工程师交谈过。从Chrome 64开始,仍无法导出覆盖率分析的结果。
明星issue #717195,以帮助团队确定此功能请求的优先顺序。
答案 2 :(得分:4)
答案 3 :(得分:3)
Chrome Canary 73可以做到。您将需要Windows或Mac OS。记录和清除按钮旁边有一个导出功能(向下箭头图标)。您将获得一个json文件,然后可以使用该文件以编程方式删除未使用的行。
答案 4 :(得分:2)
我喜欢这个简单的解决方案。它可与 Chrome 中的 Coverage 工具配合使用,无需进一步安装。您可以简单地使用 Coverage 工具允许您导出的 json 文件:
答案 5 :(得分:1)
我下载了最新版本的canary,并且存在导出按钮。
然后,我使用此PHP脚本来解析返回的json
文件。 (数组中的键“ 6”是要解析的资源)。希望对您有所帮助!
$a = json_decode(file_get_contents('coverage3.json'));
$sText = $a[6]->text;
$sOut = "";
foreach ($a[6]->ranges as $iPos => $oR) {
$sOut .= substr($sText, $oR->start, ($oR->end-$oR->start))." \n";
}
echo '<style rel="stylesheet" type="text/css">' . $sOut . '</style>';
答案 6 :(得分:1)
您可以使用Headless Chrome和puppeteer来做到这一点:
npm i puppeteer --save
csscoverage.js
的文件中,并将localhost更改为指向您的网站。:
const puppeteer = require('puppeteer');
const util = require('util');
const fs = require("fs");
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.coverage.startCSSCoverage();
await page.goto('https://localhost'); // Change this
const css_coverage = await page.coverage.stopCSSCoverage();
console.log(util.inspect(css_coverage, { showHidden: false, depth: null }));
await browser.close();
let final_css_bytes = '';
let total_bytes = 0;
let used_bytes = 0;
for (const entry of css_coverage) {
final_css_bytes = "";
total_bytes += entry.text.length;
for (const range of entry.ranges) {
used_bytes += range.end - range.start - 1;
final_css_bytes += entry.text.slice(range.start, range.end) + '\n';
}
filename = entry.url.split('/').pop();
fs.writeFile('./'+filename, final_css_bytes, error => {
if (error) {
console.log('Error creating file:', error);
} else {
console.log('File saved');
}
});
}
})();
node csscoverage.js
这会将您正在使用的所有CSS输出到它们出现的单独文件中(阻止您像其他答案一样将外部库合并到您自己的代码中。)
答案 7 :(得分:0)
基于Atoms的更实用的版本。
改进后无需任何文件即可工作。
PHP沙箱http://sandbox.onlinephpfunctions.com/
JSON格式器将转换为1行https://www.freeformatter.com/json-formatter.html#ad-output
$jsont = <<<'EOD'
{ "url":"test"}
EOD;
$a = json_decode($jsont);
$sText = $a->text;
$sOut = "";
foreach ($a->ranges as $iPos => $oR) {
$sOut .= substr($sText, $oR->start, ($oR->end-$oR->start))." \n";
}
echo '<style rel="stylesheet" type="text/css">' . $sOut . '</style>';
答案 8 :(得分:0)
这是一个基于Christopher Schiefer的版本,可以保留媒体查询:
$jsont = <<<'EOD'
{ "url":"test"}
EOD;
$a = json_decode($jsont);
$sText = $a->text;
preg_match_all('(@media(?>[^{]|(?0))*?{)', $sText, $mediaStartsTmp, PREG_OFFSET_CAPTURE);
preg_match_all("/\}(\s|\\n|\\t)*\}/", $sText, $mediaEndsTmp, PREG_OFFSET_CAPTURE);
$mediaStarts = empty($mediaStartsTmp) ? array() : $mediaStartsTmp[0];
$mediaEnds = empty($mediaEndsTmp) ? array() : $mediaEndsTmp[0];
$sOut = "";
$needMediaClose = false;
foreach ($a->ranges as $iPos => $oR) {
if ($needMediaClose) { //you are in a media query
//add closing bracket if you were in a media query and are past it
if ($oR->start > $mediaEnds[0][1]) {
$sOut .= "}\n";
array_splice($mediaEnds, 0, 1);
$needMediaClose = false;
}
}
if (!$needMediaClose) {
//remove any skipped media queries
while (!empty($mediaEnds) && $oR->start > $mediaEnds[0][1]) {
array_splice($mediaStarts, 0, 1);
array_splice($mediaEnds, 0, 1);
}
}
if (!empty($mediaStarts) && $oR->start > $mediaStarts[0][1]) {
$sOut .= "\n" . $mediaStarts[0][0] . "\n";
array_splice($mediaStarts, 0, 1);
$needMediaClose = true;
}
$sOut .= mb_substr($sText, $oR->start, ($oR->end-$oR->start))." \n";
}
if ($needMediaClose) { $sOut .= '}'; }
echo '<style rel="stylesheet" type="text/css">' . $sOut . '</style>';
答案 9 :(得分:0)
这是我提取代码的python代码:
import json
code_coverage_filename = 'Coverage-20210613T173016.json'
specific_file_url = 'https://localhost:3000/b.css'
with open(code_coverage_filename) as f:
data = json.load(f)
for entry in data:
pass # print entry['url']
if entry['url'] == specific_file_url:
text = ""
for range in entry['ranges']:
range_start = range['start']
range_end = range['end']
text += entry['text'][int(range_start):int(range_end)]+"\n"
print text
但是,有一个问题。 Chrome 调试器不会标记此类行
@media (min-width: 768px) {
所以用这个技术有点问题