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

SvelteKit带iframe的JS在线编辑器脚本执行问题咨询

HTML/CSS/JS在线编辑器自定义脚本无法执行问题的解决

问题背景

开发支持用户编写自定义脚本的HTML/CSS/JS在线编辑器时,在iframe中通过writeln写入<script>标签先是报错,修改后无报错但脚本完全不执行,怀疑是SvelteKit安全配置限制了脚本运行。

当前使用的SvelteKit代码:

<script lang="ts">
    import { onMount } from "svelte";
    import { testjson } from "$src/stores/store1";

    onMount(async () => {
        const getEl = id => document.getElementById(id)

        const iFrame = getEl('iFrame').contentWindow.document
        const htmlTextArea = getEl('htmlTextarea')
        const cssTextArea = getEl('cssTextarea')
        const jsTextArea = getEl('jsTextarea')

        document.body.onkeyup = function() {
            iFrame.open()
            iFrame.writeln(
                htmlTextArea.value +
                '<style>' +
                cssTextArea.value +
                '</style>' 
                +
                '<script>' +
                jsTextArea.value +
                '</script>'
            )
            iFrame.close()
        }
    })
</script>

对应HTML结构:

<body>
    <div class="container">
        <h3>HTML/CSS/JS Playground</h3>
        <div class="row">
            <div class="col-12">
                <ul id="myTab" class="nav nav-tabs">
                    <li class="active"><a href="#html" data-toggle="tab"> HTML</a></li>
                    <li><a href="#css" data-toggle="tab">CSS</a></li>
                    <li><a href="#js" data-toggle="tab">JS</a></li>
                </ul>
                <div id="myTabContent" class="tab-content">
                    <div class="tab-pane fade in active" id="html">
                        <p>
                            <textarea style="float:left" id="htmlTextarea"></textarea>
                        </p>
                    </div>
                    <div class="tab-pane fade" id="css">
                        <p>
                            <textarea style="float:left" id="cssTextarea"></textarea>
                        </p>
                    </div>
                    <div class="tab-pane fade" id="js">
                        <p>
                            <textarea style="float:left" id="jsTextarea"></textarea>
                        </p>
                    </div>
                </div>
            </div>
            <div class="col-12">
                <div>
                    <iframe id="iFrame"></iframe>
                </div>
            </div>
        </div>
    </div>
</body>

解决步骤

1. 修复iframe脚本注入写法

直接用writeln写入<script>标签可能触发浏览器解析截断(比如</script>被提前识别为闭合标签),改用创建脚本元素的方式注入:

document.body.onkeyup = function() {
    const iframeWin = getEl('iFrame').contentWindow;
    const iframeDoc = iframeWin.document;
    
    // 清空并写入HTML和CSS
    iframeDoc.open();
    iframeDoc.write(`${htmlTextArea.value}<style>${cssTextArea.value}</style>`);
    iframeDoc.close();

    // 单独创建脚本元素注入JS代码
    const scriptEl = iframeDoc.createElement('script');
    scriptEl.textContent = jsTextArea.value;
    iframeDoc.body.appendChild(scriptEl);
}

2. 调整SvelteKit的CSP安全策略

SvelteKit默认的内容安全策略(CSP)会限制内联脚本执行,需要修改配置允许用户自定义脚本:

方法一:通过布局文件设置CSP头

在src/routes/+layout.server.ts中添加CSP配置:

export function handle({ event, resolve }) {
    return resolve(event, {
        headers: {
            'Content-Security-Policy': `
                default-src 'self';
                frame-src 'self' data:;
                script-src 'self' 'unsafe-inline' 'unsafe-eval';
                style-src 'self' 'unsafe-inline';
            `.replace(/\n/g, '')
        }
    });
}

方法二:修改svelte.config.js配置

如果使用Node.js等适配器,可直接在配置文件中设置CSP:

import adapter from '@sveltejs/adapter-node';

/** @type {import('@sveltejs/kit').Config} */
const config = {
    kit: {
        adapter: adapter(),
        csp: {
            mode: 'auto',
            directives: {
                'default-src': ['self'],
                'frame-src': ['self', 'data:'],
                'script-src': ['self', 'unsafe-inline', 'unsafe-eval'],
                'style-src': ['self', 'unsafe-inline']
            }
        }
    }
};

export default config;

3. 检查iframe沙箱属性

如果iframe设置了sandbox属性,必须包含allow-scripts值才能允许脚本执行:

<iframe id="iFrame" sandbox="allow-scripts allow-same-origin"></iframe>

注:allow-same-origin用于让iframe访问同域资源,可根据需求选择是否添加。

验证方式

在JS文本框输入测试代码(如document.body.style.background='red'或console.log('测试脚本执行')),触发keyup事件后查看iframe效果,同时检查浏览器控制台是否有报错。


内容的提问来源于stack exchange,提问作者Bitdom8

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:35:16