A simple script written in JS, that extracts used parts of JS and CSS code from coverage JSON files.
Those FILES can be download after running some coverage web development tool, available on most of the popular modern browsers as Chrome, Firefox and Edge.
- Node.js to run
extract.js
node extract.js [1*] [2]
-
INPUT FULL PATH + FILE NAME
- Required
- JSON coverage file complete path
-
OUTPUT RELATIVE PATH
- Optional
- Path + name of the folder that will be created from root to write the output files
- Defaults to
output
One of the web development tools available, among most of the popular browsers sets.
You can figure out how to use it on the docs linked below the quotes.
The Coverage tab in Chrome DevTools can help you find unused JavaScript and CSS code. Removing unused code can speed up your page load and save your mobile users cellular data.
Code coverage essentially measures how often certain lines are hit, branches taken or conditions met in a program, given some test that you run on it.
The Coverage tool can help you find unused JavaScript and CSS code. Removing unused code can speed up your page load and save your mobile users cellular data.
The sample folder have a site, inputs and outputs that you can check out.
Consider the sample_onclick_both
in/out as they will give the most reliable result for this example.
Read below important infos about each one:
-
sample.html
- Includes <link href="./sample.css"> and <script src="./sample.js">. - Defines a <style> and a <script> itself.
- <style>
Defines .used, .dynamic and .not-used classes. - .used will always be covered, as it's defined on document build. - .dynamic will be covered by clicking on "Add Dynamic by JS <script> tag". - .not-used will never be covered, as example of unused codes.
- <script>
Defines "load" listener to window and "addDynamic" function. - window.onload will always be covered. - "addDynamic" function will be covered by clicking on "Add Dynamic by JS <script> tag".
-
sample.css
Defines .used-css, .dynamic-css and .not-used-css classes. - .used-css will always be covered, as it's defined on document build of "sample.js". - .dynamic-css will be covered by clicking on "Add Dynamic by JS file". - .not-used-css will never be covered, as example of unused codes.
-
sample.js
Defines "load" listener to window and "addDynamicJS" function. - window.onload will always be covered. - "addDynamicJS" function will be covered by clicking on "Add Dynamic by JS file".
The JSON you will get from coverage if:
-
sample_onload.json
Downloading right after page loads, with no interactions covered and unused + important code missing if extracted.
-
sample_onclick_doc.json
Downloading right after clicking ONLY on "Add Dynamic by JS < script > tag" button, with just one possible interaction covered and unused + important code missing if extracted.
-
sample_onclick_js.json
Downloading right after clicking ONLY on "Add Dynamic by JS file" button, with just one possible interaction covered and unused + important code missing if extracted.
-
sample_onclick_both.json
Downloading right after clicking on both buttons, with all possible interactions covered and just unused code missing if extracted.
The result js, css and mixed files of extraction. Genereted by running:
-
node extract.js ./sample/inputs/sample_onload.json sample/outputs/sample_onload
-
node extract.js ./sample/inputs/sample_onclick_doc.json sample/outputs/sample_onclick_doc
-
node extract.js ./sample/inputs/sample_onclick_js.json sample/outputs/sample_onclick_js
-
node extract.js ./sample/inputs/sample_onclick_both.json sample/outputs/sample_onclick_both
-
Extracting minified JS bundles considering coverage
Unless this is really required and there is no other way, it is better not do it.
There are many bugs that may occur if extracting, deppending on the minifing, mangler and bundler processes used.
The limitations lies mostly on coverage tools (and what they consider a "executed" code) and the own JS grammar.One commom problem you can face, as example, with
prototypes
:// example.js foo.prototype.bar=function(){...}; // can be WRONGLY extracted, causing a syntax error, as foo.prototype.bar=;
This example can happen if
bar
is not called, because coverage will calculate theranges
considering:foo.prototype
as executed code. Therefore including also the=;
bar
actualfunction
definition, as unused code.
- The coverage is
recorded
, so you MUST use/test all features of your page to assure a reliable result; - Still, code can be lost and bugs appear, so if you're planning to refactor anything considering coverage and this extractor, assure to have
backups
and do it on copied code; - Even if your app is a Single Page App, it is better to
run the extractions individually
for each view/page or possible use case. You can analyze and merge more result codes and mitigate risks; - Be sure to know well the architecture of your App/Site, speacially the dependencies that are not covered by this tool (3rd party mainly);
- There's no magic, but helpfull tools;
- Read more about web vitals and get your code even better after cleaning it :)