NextJS中SCORM课程无法与scorm-again JS通信的排查求助
我在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

