如何让Google Apps Script Web App的前端JS代码不被控制台查看
如何隐藏Google Apps Script独立Web App中的前端JavaScript代码?
背景
我正在开发一个Google Apps Script独立Web App,配置如下:
- 类型:独立Web App
- 运行身份:我本人
- 访问权限:任何人都可访问
涉及文件:
- Code.gs - 主服务端代码
- Home.html - 主页面
- Content.html - 附加内容片段
- Js.html - 前端JavaScript代码
目前所有功能正常运行,但用户可通过浏览器开发者工具轻松查看HTML输出中的JS代码,对此我感到担忧。
核心问题
有没有办法让用户无法访问前端JavaScript代码?
已尝试的方向与疑问
- 试过用
eval函数但没成功,如果这个方案可行,希望能基于我现有代码给出实现示例; - 考虑过把JS代码分离成库,但担心引入性能问题或不必要的复杂度,毕竟代码只用于当前Web App。
现有功能与代码
主页面(Home)包含Add和Remove按钮:点击Add会添加Content.html的内容,点击Remove会移除该内容,但当前JS代码可在开发者工具中直接查看。
Code.gs
function doGet(e) { Logger.log(Utilities.jsonStringify(e) ); // html head var output = HtmlService.createTemplateFromFile('Home').evaluate(); var output = output.asTemplate(); return output.evaluate() .addMetaTag('viewport', 'width=device-width, initial-scale=1') .setTitle('Home'); } function include(filename) { return HtmlService.createTemplateFromFile(filename).evaluate().getContent(); } function getHtmlOutput(filename) { return HtmlService.createTemplateFromFile(filename).evaluate(); }
Home.html
<!DOCTYPE html> <html> <head> <base target="_top"> <style> div { color: red; } </style> </head> <body> <div id="content-container"> Hello World <button type="button" onclick="add()">Add</button> <button type="button" onclick="remove()">Remove</button> <?!= include('js');?> </div> </body> </html>
Content.html
<div id="content"> This is the content </div>
Js.html
<script> function runGS(functionName,params=[]) { return new Promise((resolve,reject) => { google.script.run .withSuccessHandler(data => { resolve(data) }) .withFailureHandler(error => { reject(error) }) [functionName](...params); }) } async function add() { var content = await runGS("include",["Content"]); var target = document.getElementById("content-container"); target.insertAdjacentHTML("afterend",content); return "done"; } function remove() { var target = document.getElementById("content"); target.remove(); } </script>
解决方案分析与实现
首先明确:所有运行在浏览器端的JavaScript代码本质上无法完全隐藏——浏览器需要解析执行代码,就必须获取到可读取的内容。但可以通过混淆、动态加载或逻辑转移等方式增加查看难度,提升安全性。
1. 基于eval的编码加载实现(适配你的现有代码)
通过服务端对JS代码进行Base64编码,前端获取后解码再用eval执行,开发者工具中只会看到编码后的字符串,而非原始代码。
修改步骤:
Code.gs
新增获取编码后JS的函数,并调整doGet不再直接嵌入JS:
function doGet(e) { Logger.log(Utilities.jsonStringify(e) ); var output = HtmlService.createTemplateFromFile('Home').evaluate(); return output .addMetaTag('viewport', 'width=device-width, initial-scale=1') .setTitle('Home'); } function include(filename) { return HtmlService.createTemplateFromFile(filename).evaluate().getContent(); } function getEncodedJS() { // 获取Js.html内容并移除<script>标签 var jsContent = HtmlService.createTemplateFromFile('Js').evaluate().getContent(); jsContent = jsContent.replace(/<script>|<\/script>/g, ''); // 转Base64编码 return Utilities.base64Encode(jsContent, Utilities.Charset.UTF_8); }
Home.html
移除<?!= include('js');?>,添加动态加载脚本:
<!DOCTYPE html> <html> <head> <base target="_top"> <style> div { color: red; } </style> </head> <body> <div id="content-container"> Hello World <button type="button" onclick="add()">Add</button> <button type="button" onclick="remove()">Remove</button> </div> <script> // 动态获取编码JS并解码执行 google.script.run .withSuccessHandler(encodedJS => { const decodedBlob = Utilities.newBlob(Utilities.base64Decode(encodedJS, Utilities.Charset.UTF_8)); eval(decodedBlob.getDataAsString()); }) .getEncodedJS(); </script> </body> </html>
Js.html
保留原逻辑(可可选压缩代码进一步混淆):
<script> function runGS(functionName,params=[]) { return new Promise((resolve,reject) => { google.script.run .withSuccessHandler(resolve) .withFailureHandler(reject) [functionName](...params); }) } async function add() { const content = await runGS("include",["Content"]); document.getElementById("content-container").insertAdjacentHTML("afterend",content); return "done"; } function remove() { const target = document.getElementById("content"); target?.remove(); } </script>
2. 核心逻辑转移到服务端(更安全的方案)
如果业务逻辑不需要在前端执行,优先将其放到Code.gs中,前端仅负责触发调用。比如数据处理、权限校验等逻辑都可以迁移,前端只保留UI交互代码。
示例(针对非DOM操作逻辑):
// Code.gs新增函数 function processData(input) { // 服务端处理核心逻辑 return input * 2; } // 前端调用 async function handleProcess() { const result = await runGS("processData", [10]); console.log(result); }
3. 关于分离为库的说明
将JS代码做成Google Apps Script库会额外增加复杂度,且库代码依然会被编译后发送到前端,本质上仍可被查看,仅路径不同。若代码量不大,不建议采用此方式。
注意事项
- 混淆/编码仅能增加查看难度,无法阻止有经验的开发者还原代码;
eval可能被浏览器安全策略限制,或被代码检测工具标记为不安全;- 最安全的方式是将核心业务逻辑放在服务端(Code.gs),前端仅负责UI交互。
内容的提问来源于stack exchange,提问作者AAng
相关产品推荐
相关产品推荐

