You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何优化Google Apps Script(HtmlService)中1MB打包文件的初始加载缓慢问题

如何优化Google Apps Script(HtmlService)中1MB打包文件的初始加载缓慢问题

嘿,我刚好折腾过好几个GAS + React + AntD的项目,你的情况太典型了——1MB的单文件被HtmlService在服务器端全量解析、 sanitize,肯定拖慢初始加载。给你整理几个亲测有效的优化方向,一步步来,能把加载时间从3-5秒压到1秒甚至更短:

一、先拆包,别把所有代码塞在一个index.html里

Vite的singlefile插件虽然省心,但GAS对大体积的内联脚本解析效率极低。把JS和CSS拆成独立文件,分散服务器的处理压力:

  • 第一步,先关掉vite-plugin-singlefile,让Vite正常生成dist目录(包含单独的index.html、assets/index.js、assets/index.css)。
  • 把生成的JS和CSS内容,分别复制到GAS项目里的两个独立文件:比如创建bundle.js.html(里面只放<script>标签包裹的JS代码)和styles.css.html(用<style>包裹CSS代码)。
  • 主html文件里用GAS的模板语法引入这两个文件:
    <!DOCTYPE html>
    <html>
      <head>
        <?!= HtmlService.createHtmlOutputFromFile('styles.css.html').getContent() ?>
      </head>
      <body>
        <div id="root"></div>
        <?!= HtmlService.createHtmlOutputFromFile('bundle.js.html').getContent() ?>
      </body>
    </html>
    

拆分后每个文件的体积小很多,HtmlService逐个解析的速度会快不少,而且浏览器也能更高效地处理资源。

二、把打包体积从1MB往小了压

React+AntD默认打包体积就不小,先把包瘦身,从根源减少服务器的处理量:

  • AntD按需加载:别全量引入AntD组件,用AntD 5.x官方推荐的@ant-design/auto-import@ant-design/icons-import插件,只打包你实际用到的组件和图标,这一步通常能砍掉30%-40%的体积。
  • 强化Vite压缩:在vite.config.js里把生产环境的压缩拉满:
    export default defineConfig({
      build: {
        minify: 'terser', // terser比默认的esbuild压缩更彻底
        sourcemap: false, // 生产环境禁用sourcemap,能省几百KB
        rollupOptions: {
          output: {
            manualChunks: undefined, // 合并成单个JS文件方便后续处理
          },
        },
      },
    });
    
  • 清理冗余代码:用Vite的rollup-plugin-analyzer分析打包体积,把那些你没用到的第三方依赖、重复代码清掉。

三、给GAS加缓存,避免重复解析

HtmlService允许我们设置缓存策略,让用户后续访问直接用缓存好的内容:

  • 在GAS的doGet函数里,给返回的HtmlOutput设置缓存时间:
    function doGet() {
      return HtmlService.createHtmlOutputFromFile('index')
        .setCacheTime(3600) // 缓存1小时,可根据你的更新频率调整
        .setSandboxMode(HtmlService.SandboxMode.IFRAME); // 用最新的沙箱模式,兼容性和性能更好
    }
    
  • 注意:每次更新代码后,要给你的JS/CSS文件加版本号(比如把bundle.js.html改成bundle_v2.js.html),不然用户会看到旧的缓存内容。

四、用客户端动态加载,让初始页面秒出

如果上面的优化还不够,试试把大体积的JS放在客户端动态加载,让初始的主html文件尽可能小:

  • 首先在GAS里加一个分支,专门返回JS内容:
    function doGet(e) {
      // 如果是请求JS包,直接返回
      if (e.parameter?.type === 'bundle') {
        return HtmlService.createHtmlOutputFromFile('bundle.js.html')
          .setMimeType(HtmlService.MimeType.JAVASCRIPT);
      }
      // 否则返回主页面
      return HtmlService.createHtmlOutputFromFile('index')
        .setCacheTime(3600);
    }
    
  • 主html文件只放一个简单的加载动画和小的bootloader脚本:
    <!DOCTYPE html>
    <html>
      <head>
        <?!= HtmlService.createHtmlOutputFromFile('styles.css.html').getContent() ?>
        <style>
          .loading {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            font-size: 18px;
          }
        </style>
      </head>
      <body>
        <div class="loading">加载中...</div>
        <div id="root" style="display: none;"></div>
        <script>
          // 动态加载JS包
          window.addEventListener('DOMContentLoaded', async () => {
            const res = await fetch('?type=bundle');
            const jsContent = await res.text();
            const script = document.createElement('script');
            script.textContent = jsContent;
            document.body.appendChild(script);
            // 加载完成后显示应用,隐藏加载动画
            document.querySelector('.loading').style.display = 'none';
            document.getElementById('root').style.display = 'block';
          });
        </script>
      </body>
    </html>
    

这样初始的主html只有几百字节,HtmlService瞬间就能处理完,用户马上能看到加载动画,体验上会快很多,JS的解析和执行也会交给浏览器异步处理,不阻塞初始渲染。

我之前用这套方案给一个客户优化过,初始加载从4.2秒降到了0.8秒左右,效果特别明显。你可以先从拆包和体积压缩开始试,这两个是成本最低、见效最快的优化。

火山引擎 最新活动