前言
本文介绍了一个使用Google Closure Compiler库实现JavaScript代码格式化的工具类。主要内容包括:1) 添加Maven依赖配置;2) 提供完整的JSFormatterUtil工具类,包含代码格式化和移除模块标识功能;3) 给出测试示例,展示如何获取网络JS文件并进行格式化处理。该工具能自动将压缩的JS代码转换为标准格式,支持错误检测和异常处理,格式化失败时返回原代码。文中还提示了常见问题,如自动引入错误包的问题解决方法,并对比了格式化前后的代码效果差异。
一、添加依赖
此依赖用作格式化代码使用,也有一些其他功能,暂不清楚,可以自行探索!!!
XML
<dependency>
<groupId>com.google.javascript</groupId>
<artifactId>closure-compiler</artifactId>
<version>v20240317</version>
</dependency>
二、格式化工具类
注:1. 格式化前会进行内容校验,若文件内容格式错误,会将原代码返回
- 一定要看引入的包是否正确,若复制代码时不复制import包,Compiler类会自动给你引入java.lang下面的,此时代码报错(我自己踩坑了,一直自动引入java底下的,巨恶心)
java
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.*;
import com.google.javascript.jscomp.jarjar.com.google.common.collect.ImmutableMap;
import java.util.List;
/**
* @program:
* @create: 2025-10-31 16:18
*/
public class JSFormatterUtil {
private static final String MODULE_TAG = "'use strict';";
/**
* 格式化 JavaScript 代码字符串
* 注:1. 若校验格式有问题会返回原代码
* 2. 格式化后会自动添加模块标识,不想要可以手动处理掉
*
* @param jsCode 压缩的 JavaScript 代码
* @return 格式化后的 JavaScript 代码
*/
public static String format(String jsCode) {
if (jsCode == null || jsCode.trim().isEmpty()) {
return jsCode;
}
try {
// 创建编译器实例
Compiler compiler = new Compiler();
// 创建编译器选项
CompilerOptions options = new CompilerOptions();
// 设置格式化选项 - 美化输出
options.setPrettyPrint(true);
options.setPrintInputDelimiter(false);
// 设置不进行代码优化,只格式化(仅处理空白字符)
CompilationLevel.WHITESPACE_ONLY.setOptionsForCompilationLevel(options);
// 获取所有诊断组(高版本兼容方式)
ImmutableMap<String, DiagnosticGroup> registeredGroups = DiagnosticGroups.getRegisteredGroups();
registeredGroups.forEach((k, v) -> options.setWarningLevel(v, CheckLevel.OFF));
// 不输出警告信息
// options.setWarningLevel(DiagnosticGroups.ALL, CheckLevel.OFF);
// 创建源代码输入
SourceFile input = SourceFile.fromCode("input.js", jsCode);
// 使用默认的外部依赖(标准 JavaScript API)
List<SourceFile> externs = CommandLineRunner.getBuiltinExterns(CompilerOptions.Environment.BROWSER);
// 编译(实际只做格式化,不优化)
Result result = compiler.compile(
externs, // externs - 外部依赖
List.of(input), // inputs - 输入文件
options // options - 编译选项
);
// 检查编译是否成功
if (!result.success) {
// 如果编译失败,返回原代码
return jsCode;
}
// 获取格式化后的代码
String formatted = compiler.toSource();
// 如果格式化失败,返回原代码
if (formatted == null || formatted.trim().isEmpty()) {
return jsCode;
}
return formatted.trim();
} catch (Exception e) {
// 如果出错,返回原代码
System.err.println("格式化出错: " + e.getMessage());
e.printStackTrace();
return jsCode;
}
}
/**
* 将格式化时自动添加的模块标识去除
*
* @param formatContent 格式化好的文件内容
* @return 去除模板标识的文件内容
*/
public static String removeModuleTag(String formatContent) {
// 将模块标识去除
String moduleTag = JSFormatterUtil.MODULE_TAG;
if (formatContent.startsWith(moduleTag)) {
int index = formatContent.indexOf(moduleTag);
return formatContent.substring(index + moduleTag.length()).trim();
} else {
return formatContent;
}
}
}
三、测试
此链接可以测试使用,从百度上拿的
java
https://pss.bdstatic.com/r/www/cache/static/protocol/https/jquery/jquery-1.10.2.min_65682a2.js
java
@ApiOperation("测试")
@GetMapping("/test")
public void test(String jsUrl, HttpServletResponse response) {
// 通过jsUrl发送请求获取文件内容,若您的文件是本地文件可以直接读取本地文件,拿到内容就行
String content = restTemplate.get(jsUrl);
// 将文件内容传入工具类,进行格式化
// 格式化后会自动添加一个模块标识,可以根据自己需要是否进行保留
String formatContent = JSFormatterUtil.format(content);
// 将模块标识去除
String finalContent = JSFormatterUtil.removeModuleTag(formatContent);
// 此时文件内容就处理好了,后面可以根据自己需要进行处理
{// 将文件保存到本地
String filePath = "C:\\Users\\marun\\Desktop\\临时文件\\格式化后的JS文件" + System.currentTimeMillis() + ".js";
try (FileWriter writer = new FileWriter(filePath, true)) {
writer.write(finalContent);
System.out.println("内容已成功追加到文件。");
} catch (IOException e) {
System.err.println("写入文件时出错: " + e.getMessage());
}
}
{// 以文件形式返回
byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
// 1. 设置响应头
response.setContentType("application/javascript; charset=UTF-8");
// 强制浏览器下载:attachment,不强制浏览器下载:inline
response.setHeader("Content-Disposition", "attachment; filename=\"p_im-index.js\"");
response.setContentLength(bytes.length);
// 2. 写入响应流
try (OutputStream os = response.getOutputStream()) {
os.write(bytes);
os.flush();
} catch (Exception e) {
throw new IYuanMessageException("文件写入失败");
}
}
}
四、格式化前后示例
1. 格式化前:放到idea上面就是一行数据

2. 格式化后:格式清晰
