Chrome Devtools覆盖范围:如何保存或捕获代码使用的代码?

时间:2017-07-14 15:37:27

标签: google-chrome-devtools

Coverage工具擅长查找已使用和未使用的代码。但是,似乎没有一种方法可以只保存或导出使用过的代码。即使隐藏未使用的代码也会有所帮助。

我试图减少应用程序中的Bootstrap CSS数量;该文件超过7000行。获取所用代码的唯一方法是仔细滚动文件,查找绿色部分,然后将该代码复制到新文件。这是耗时且不可靠的。

有不同的方式吗? Chrome 60似乎没有添加此功能。

10 个答案:

答案 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)

  1. 首先,您需要下载并安装“ Google Chrome开发者版”。
  2. 在Google chrome开发器上,转到“检查元素”>“源”> Ctrl + shift + p
  3. 输入“ coverage”并选择“开始检测覆盖并重新加载页面”
  4. 然后使用“导出”图标 enter image description here 这会给你一个json文件。

您还可以访问:Chrome DevTools: Export your raw Code Coverage Data

答案 3 :(得分:3)

Chrome Canary 73可以做到。您将需要Windows或Mac OS。记录和清除按钮旁边有一个导出功能(向下箭头图标)。您将获得一个json文件,然后可以使用该文件以编程方式删除未使用的行。

答案 4 :(得分:2)

我喜欢这个简单的解决方案。它可与 Chrome 中的 Coverage 工具配合使用,无需进一步安装。您可以简单地使用 Coverage 工具允许您导出的 json 文件:

https://nachovz.github.io/devtools-coverage-css-generator/

答案 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来做到这一点:

  1. 在新文件夹中,使用npm安装puppeteer(这将包括Headless Chrome):

npm i puppeteer --save

  1. 将以下内容放入名为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');
    }
  });
}
})();
  1. 使用node csscoverage.js
  2. 运行它

这会将您正在使用的所有CSS输出到它们出现的单独文件中(阻止您像其他答案一样将外部库合并到您自己的代码中。)

答案 7 :(得分:0)

基于Atoms的更实用的版本。

改进后无需任何文件即可工作。

PHP沙箱http://sandbox.onlinephpfunctions.com/

JSON格式器将转换为1行https://www.freeformatter.com/json-formatter.html#ad-output

将其统一https://unminify.com/

$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) {

所以用这个技术有点问题