We are refactoring a legacy web app and as a result are "killing" quite a lot of JavaScript code but we're afraid of deleting what we think is dead code due to not being sure. Is there any tool / technique for positively identifying dead code in JavaScript?
问题:
回答1:
There's grep. Use it to find function calls. Suppose you have a method called dostuff()
. Use grep -r "dostuff()" * --color
on your project's root directory. Unless you find anything other than the definition, you can safely erase it.
ack is also a notable alternative to grep.
回答2:
Without looking for anything too complex:
- JSLint (not really a static analyzer, but if you give it your concatenated development code, you'll see what methods are never called, at least in obvious scoping contexts)
- Google Closure Compiler
- Google Closure Linter
回答3:
If your code uses "eval", it is pretty hard to get a gaurantee that somewhere the code doesn't assemble a string by some obscure means and eval it, calling your dead code. (And really nasty stuff might call eval on a string containing eval...).
You also have to worry about calls from outside your code; many webpages use HTML "on" attributes to invoke JavaScript code.
So what you need to do is to find methods/declarations that appear to be dead, and find and vet all the eval calls, and find and vet all the "on" attributes.
Using test coverage as others have suggested is a way to get an initial list of possibly-dead code. You obviously want to exercise as much of the functionality as you can to eliminated possibly dead candidates, then search for the remaining ones to see if there are calls in your code. Finding evals and on-events is a matter of searching the code for such things.
Grep will likely work, although it might be painful to go through your list of names one by one, type in the right search, guess from its output which ones are not false positives, and go inspect them in an editor one by one.
You might look at our SD Source Code Search Engine (SCSE), which can do language-specific searches for many langauges, including HTML pages of various types and JavaScript. You can easily restrict the SCSE to inspect just the function calls in JavaScript code (e.g, to ignore comments and strings) for the remaining candidattes and/or eval, and inspect just the "on*" attributes in the HTML pages (e.g., to ignore all the other text in the HTML pages). It uses a GUI to accept you search query, show hits, and pull up the source text containing the hit for easy inspection. It will even take you to your editor on a hit, if needed.
For a static analysis solution, you need tools that can parse the code and determine which names refer to which entities; scope matters. Then you need to be able to determine plausiable execution paths through the code, modulo the dynamic object structure and those nasty evals. For this you need a pretty sophisticated engine and likely some engineering unless somebody just happens have this lying around, which I doubt.
Our DMS Software Reengineering Toolkit is just such an engine, and it has a full JavaScript (and HTML) parsers. While we haven't used DMS to this for JavaScript, we have built such a dead code remover for Java using DMS. You feed it the Java code, and it produces a "appears to be dead" list of classes, methods, and fields (including the transitive closure of dead: if class A is dead, and references B, the A's references don't count as real references to B), and a modified version of the code with all the "dead" stuff removed. You decide if you believe the report; if you do, you keep the code. If you don't, you modify the code to make sure that that apparantly dead thing isn't dead, and run it again.
回答4:
WebStorm IDE from JetBrains can highlight deadcode and unused variables in your project.
回答5:
You could use code optimizers as Google Closure Compiler, however it's often used for minimizing code.
function hello(name) {
alert('Hello, ' + name);
}
function test(){
alert('hi');
}
hello('New user');
Will result in
alert("Hello, New user");
For example.
Another thing you could do is to use Chrome's Developer Tools (or Firebug) to see all function calls. Under Profiles you can see which functions are being called over time and which are not.
回答6:
Chrome has come up with new feature which lets developer see the code coverage, ie., which lines of codes were executed.
This certainly is not a one stop solution, but can extend a helping hand to developers to get code insights.
Check this link for details
Rolled as apart of Chrome 59 release
回答7:
If you want to automate this I'd take a look at https://github.com/joelgriffith/navalia, which exposes an automated API to do just that:
const { Chrome } = require('navalia');
const chrome = new Chrome();
chrome.goto('http://joelgriffith.net/', { coverage: true })
.then(() => chrome.coverage('http://joelgriffith.net/main.bundle.js'))
.then((stats) => console.log(stats)) // Prints { total: 45913, unused: 5572,
percentUnused: 0.12135996340905626 }
.then(() => chrome.done());
More here: https://joelgriffith.github.io/navalia/Chrome/coverage/