You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Google Apps Script Web App的前端JS代码不被控制台查看

如何隐藏Google Apps Script独立Web App中的前端JavaScript代码?

背景

我正在开发一个Google Apps Script独立Web App,配置如下:

  • 类型:独立Web App
  • 运行身份:我本人
  • 访问权限:任何人都可访问
    涉及文件:
  1. Code.gs - 主服务端代码
  2. Home.html - 主页面
  3. Content.html - 附加内容片段
  4. Js.html - 前端JavaScript代码

目前所有功能正常运行,但用户可通过浏览器开发者工具轻松查看HTML输出中的JS代码,对此我感到担忧。

核心问题

有没有办法让用户无法访问前端JavaScript代码?

已尝试的方向与疑问

  1. 试过用eval函数但没成功,如果这个方案可行,希望能基于我现有代码给出实现示例;
  2. 考虑过把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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 12:47:45