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

NextJS中SCORM课程无法与scorm-again JS通信的排查求助

问题:Next.js中SCORM课程iframe无法找到LMS API

我在NextJS页面中使用https://cdn.jsdelivr.net/npm/scorm-again@2.0.0/dist/scorm-again.js,加载CDN后完成初始化,window.API_1484_11已赋值,但iframe中的SCORM课程仍无法找到LMS API,无法获取分数与进度,抛出如下警告:

Warning: Course was unable to find the LMS API for CommitData. Course may have been launched from scormcontent/index.html, or the course package is not within an LMS. Saving of student data will not occur.

index.html:195 Warning: Course was unable to find the LMS API for ConcedeControl. Course may have been launched from scormcontent/index.html, or the course package is not within an LMS. Saving of student data will not occur.
index.html:195 Warning: Course was unable to find the LMS API for CreateResponseIdentifier. Course may have been launched from scormcontent/index.html, or the course package is not within an LMS. Saving of student data will not occur.

我的实现代码如下:

'use client';

import { useEffect, useState, useRef } from "react";
import Script from "next/script"; // For Next.js (remove if using plain React)

declare const Scorm2004API: any;
declare const Scorm12API: any;

const ScormCDN = () => {
  const [scormAPILoaded, setScormAPILoaded] = useState(false);
  const [loadIframe, setLoadIframe] = useState(false);
  const iframeRef = useRef(null);

  // Function to execute when the SCORM library is loaded
  const onLoadScormAgainLibrary = () => {
    setScormAPILoaded(true);
    console.log("✅ SCORM library loaded");
  };

  useEffect(() => {
    if (scormAPILoaded && typeof window !== "undefined") {
      // Initialize SCORM 2004 API and attach it to `window`
      const apiUrl = 'http://localhost:3000/v1';
      const apiVersion: string = '2004';
      const apiSettings = {
        logLevel: 1,
        version: apiVersion,
        lmsCommitUrl: `${apiUrl}/scorm/progress`,
        autocommitSeconds: 5,
        autocommit: false,
        asyncCommit: true,
        xhrWithCredentials: true,
        autoProgress: true,
        xhrHeaders: {
            accept: 'application/json',
        },
        fetchMode: 'cors',
        responseHandler: (response: any) => {
            if (response.status === 404) {
                console.error('Commit failed with 404 error, retrying...');
            } else {
                console.log('responseHandler Response from LMS:', response);
            }
        },
        onload: function (response: any) {
          console.log('onload Response from LMS:', response);
        },
        renderCommonCommitFields: true,
        mastery_override: false
      }

      const userId = '123';
      const userName = 'Binyameen';

      if(apiVersion === '1.2')
      {
        window.API = new Scorm12API(apiSettings);
        console.log("✅ SCORM 1.2 API initialized:", window.API);

        window.API.cmi.core.student_id = userId;
        window.API.cmi.core.student_name = userName;
      }
      else if(apiVersion === '2004')
      {
        window.API_1484_11 = new Scorm2004API(apiSettings);
        console.log("✅ SCORM 2004 API initialized:", window.API_1484_11);
            // Attach event listener before initializing
            window.API_1484_11.on("Initialize", function () {
              console.log("🚀 SCORM session started");

              // Set initial values after initialization
              const success1 = window.API_1484_11.SetValue("cmi.completion_status", "incomplete");
              const success2 = window.API_1484_11.SetValue('cmi.learner_id', userId);
              const success3 = window.API_1484_11.SetValue('cmi.learner_name', userName);

              console.log("Set cmi.completion_status:", success1);
              console.log("Set cmi.learner_id:", success2);
              console.log("Set cmi.learner_name:", success3);
            });

            window.API_1484_11.Initialize();      
      }

      setLoadIframe(true);      
      
    }
  }, [scormAPILoaded]);

  return (
    <div>
      <h2>SCORM 2004 Course (CDN Version)</h2>

      {/* Load SCORM library from CDN */}
      <Script
        src="https://cdn.jsdelivr.net/npm/scorm-again@2.0.0/dist/scorm-again.js"
        onLoad={onLoadScormAgainLibrary}
        strategy="afterInteractive" // Only for Next.js
      />

      {/* Load SCORM content in iframe */}
      {loadIframe && (
        <iframe
          ref={iframeRef}
          src="/SPSG_Hearing_Scorm2004_010324/scormcontent/index.html"
          width="100%"
          height="600px"
          title="SCORM Course"
        ></iframe>
      )}
    </div>
  );
};

export default ScormCDN;

我是SCORM集成新手,已查阅库文档、NPM、GitHub问题及AI工具仍无法解决,请问下一步该如何排查?


排查步骤
  • 检查iframe的跨域限制:SCORM课程的iframe加载本地路径/SPSG_Hearing_Scorm2004_010324/scormcontent/index.html,浏览器同源策略会阻止iframe直接访问父窗口的window.API_1484_11。确认课程文件域名与Next.js应用一致,若不一致需配置CORS或同域部署;本地开发必须用http://localhost:3000这类HTTP协议,禁止用file://协议。

  • 手动注入API到iframe:SCORM课程的FindAPI函数可能无法正常遍历窗口层级,可在iframe加载完成后手动传递API:

    useEffect(() => {
      if (loadIframe && iframeRef.current) {
        const iframeWindow = iframeRef.current.contentWindow;
        if (iframeWindow) {
          iframeWindow.API_1484_11 = window.API_1484_11;
          console.log("🔧 已手动注入SCORM API到iframe");
        }
      }
    }, [loadIframe]);
    
  • 兼容SCORM 1.2的API查找逻辑:部分旧课程仅查找window.API(SCORM 1.2),可同时挂载别名:

    window.API_1484_11 = new Scorm2004API(apiSettings);
    window.API = window.API_1484_11; // 兼容只识别SCORM 1.2 API的课程
    
  • 延迟加载iframe到API初始化完成:确保API完全初始化后再加载iframe,将setLoadIframe(true)移到Initialize回调中:

    window.API_1484_11.on("Initialize", function () {
      console.log("🚀 SCORM session started");
      // ... 设置初始值
      setLoadIframe(true); // 初始化完成后再加载iframe
    });
    window.API_1484_11.Initialize();
    
  • 开启详细日志排查:将apiSettings中的logLevel改为2或3,查看更详细的初始化日志,确认API是否真的就绪,是否有隐藏错误。

  • 脱离Next.js验证基础功能:先搭建纯HTML页面加载SCORM库和iframe,验证集成逻辑是否正常。若纯HTML环境正常,再排查Next.js的Script组件加载策略,比如将strategy改为beforeInteractive或lazyOnload,确保库在页面早期加载完成。


内容的提问来源于stack exchange,提问作者Muhammad Binyameen Malik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 23:18:10