跨域脚本报错

886 阅读1分钟

参考

原因

由于项目用域名到 CDN 的脚本资源不同域,造成不同域的脚本报错无法捕获更多详细信息

解决

加载脚本资源的script标签添加上crossOrigin属性

具体不不同项目配置如下:

@vue/cli 脚手架项目

配置vue.config.js

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
  // 入口模块与splitChunks模块
  crossorigin: 'anonymous',
  chainWebpack: (config) => {
    // 异步模块
    config.output.crossOriginLoading('anonymous');
  },
});

webpack 项目

配置webpack.config.js

  • 异步模块
const CorsPlugin = require('@vue/cli-service/lib/webpack/CorsPlugin.js');

module.exports = {
  output: {
    // 异步模块
    crossOriginLoading: 'anonymous',
  },
  plugins: [
    new CorsPlugin({
      publicPath: '项目的publicPath',
      crossorigin: 'anonymous',
      integrity: false,
    }),
  ],
};

使用CorsPlugin注意@vue/cli-service对应的 webpack 的版本

vite项目

  • 异步模块不需要添加vite内置已实现

  • 入口模块vite内置已实现

以上实现的vite打包后代码

const __vitePreload = function preload(baseModule, deps) {
  if (!deps || deps.length === 0) {
    return baseModule();
  }
  return Promise.all(deps.map((dep) => {
    dep = `${base}${dep}`;
    if (dep in seen)
      return;
    seen[dep] = true;
    const isCss = dep.endsWith(".css");
    const cssSelector = isCss ? '[rel="stylesheet"]' : "";
    if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
      return;
    }
    const link = document.createElement("link");
    link.rel = isCss ? "stylesheet" : scriptRel;
    if (!isCss) {
      link.as = "script";
      link.crossOrigin = "";
    }
    link.href = dep;
    document.head.appendChild(link);
    if (isCss) {
      return new Promise((res, rej) => {
        link.addEventListener("load", res);
        link.addEventListener("error", () => rej(new Error(`Unable to preload CSS for ${dep}`)));
      });
    }
  })).then(() => baseModule());
};

__vitePreload 函数的添加crossOrigin的属性

  • manualChunks模块, 需添加自定义vite插件实现
import { Plugin } from 'vite';

export const HtmlEntryCrossOrigin = () => {
  return {
    name: 'vite-html-entry-crossorigin',
    enforce: 'post',
    apply: 'build',
    transformIndexHtml(html) {
      html = html.replace(/link rel="modulepreload"/gi, 'link rel="modulepreload" crossorigin as="script"');
      return html;
    },
  } as Plugin;
};

vite.config.ts

export default defineConfig({
  // 更多代码
  plugins: [
       HtmlEntryCrossOrigin()
    ]
    // 更多代码
});

注意

  • 同时,项目手动createElement形式加载脚本的也需要添加上crossOrigin属性
// 更多逻辑
let script = document.createElement('script');
script.type = 'text/javascript';


// 添加属性
script.setAttribute('crossOrigin', 'anonymous');

// 更多逻辑
  • 项目index.html引用的cdn脚本资源,同样也需要手动添加上crossOrigin属性