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

Safari中CSSStyleSheet非法构造函数错误及Webpack适配方案咨询

问题

我正在使用NodeJS开发一款JS应用,通过Webpack构建,核心用Web Components实现。组件代码示例如下:

import style from "./inboxScreen.css" assert { type: "css" };

export class InboxScreen extends HTMLElement {
  constructor() {
    super();

    this.attachShadow({ mode: "open" })

    this.shadowRoot.adoptedStyleSheets.push(style);

    this.shadowRoot.innerHTML = `
    `;
  }
}

customElements.define("inbox-screen", InboxScreen);

应用在Chrome、Firefox和Edge中运行正常,但在Safari里抛出TypeError: Illegal constructor错误,报错的压缩后代码行指向:

r.push([e.id, ":host {
  width: 100%;

  font-size: 14px;
  color: grey;
}

.pending {
  color: orange;
}

.total {
  color: green;
}

.normal-state {
  display: none;
}

.normal-state.active {
  display: block;
}

.retrieval-state {
  display: none;
}

.retrieval-state.active {
  display: block;
  animation: flash 2s infinite alternate;
}

@keyframes flash {
  0% {
    color: grey;
  }
  50% {
    color: white;
  }
  100% {
    color: grey;
  }
}

.polling-state {
  display: none;
}

.polling-state.active {
  display: flex;
}
", ""]);
var o = new CSSStyleSheet;
o.replaceSync(r.toString()); // illegal constructor

当前Webpack配置规则:

rules: [
  {
    assert: { type: "css" },
    loader: "css-loader",
    options: {
      exportType: "css-style-sheet",
    },
  },
],

已知Safari不支持assert { type: "css" }语法,请问能否通过调整Webpack配置解决该问题?

解决方案

可以通过调整Webpack配置解决,核心思路是避开Safari不支持的assert { type: "css" }语法,同时保留adoptedStyleSheets的使用,具体调整如下:

  • 移除import语句中的assert断言
    把组件里的import style from "./inboxScreen.css" assert { type: "css" };改成普通的CSS导入:

    import style from "./inboxScreen.css";
    
  • 修改Webpack的css-loader配置
    去掉assert规则,同时保留exportType: "css-style-sheet",让css-loader直接导出CSSStyleSheet实例,无需依赖原生的assert语法:

    rules: [
      {
        test: /\.css$/i,
        loader: "css-loader",
        options: {
          exportType: "css-style-sheet",
        },
      },
    ],
    
  • 兼容Safari的CSSStyleSheet构造
    如果调整后仍有new CSSStyleSheet的兼容性问题,可以添加一个简单的兼容逻辑(直接写在组件或入口文件中):

    if (!window.CSSStyleSheet || typeof CSSStyleSheet !== 'function') {
      window.CSSStyleSheet = class CSSStyleSheet {
        constructor() {
          this.adoptedStyleSheet = document.createElement('style');
          document.head.appendChild(this.adoptedStyleSheet);
          this.cssRules = this.adoptedStyleSheet.sheet.cssRules;
        }
        replaceSync(cssText) {
          this.adoptedStyleSheet.textContent = cssText;
        }
      };
    }
    

这样调整后,Webpack会通过css-loader直接处理CSS并生成兼容的CSSStyleSheet实例,无需依赖Safari不支持的assert语法,同时保持Web Components的样式隔离逻辑不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:23:15