vue使用externals分离依赖,同时我想使用动态获取最快CDN来加载,要怎么实现呢?

webpack配置:

externals = {
    vue: 'Vue',
    axios: 'axios'
}

正常是在html中使用固定的cdn链接加载:

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.16/vue.min.js"></script>
....

以上是没问题的,但是国内cdn不稳定,我想从多个cdn中使用最快的cdn,于是我写了个函数:

loadFastCdnScripts() {
  // 此处动态判断多个cdn链接速度,选择最快的cdn来并添加到头部,此处代码实现没问题
}

我不知道该把loadFastCdnScripts函数放在哪执行?怎么让Cdn加载完后才加载主程序呢?因为运行总是报Vue is undefined,似乎主程序总是优先于cdn加载

阅读 1.9k
avatarAI BotBETA

为了在 Vue 项目中动态地选择并使用最快的 CDN 来加载外部依赖(如 Vue 和 axios),你需要确保 CDN 脚本在应用程序的其它脚本之前加载,并在它们加载完成后再初始化你的 Vue 应用。这可以通过使用 JavaScript 的事件监听来实现,比如监听 DOMContentLoaded 事件或者监听特定脚本的加载完成。

下面是一个基本的实现思路:

  1. 在 HTML 中不要直接添加 <script> 标签来加载 CDN 资源。
  2. 编写 loadFastCdnScripts 函数,该函数负责动态选择 CDN 并插入 <script> 标签到 <head> 中。
  3. loadFastCdnScripts 函数中为每个 CDN 脚本添加 onload 事件监听器,以确认它们何时加载完成。
  4. 一旦所有必要的 CDN 脚本都加载完成,触发一个自定义事件或者调用一个回调函数来初始化你的 Vue 应用。

以下是一个简化的代码示例,演示了如何实现这个过程:

// 假设这个函数能够返回最快的 CDN URL
function getFastCdnUrl(library) {
  // ... 这里是选择最快 CDN 的逻辑 ...
  return 'https://fast-cdn.example.com/' + library + '.min.js';
}

// 加载 CDN 脚本的函数
function loadCdnScript(url, callback) {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = url;
    script.async = true;
    script.onload = () => {
      resolve();
      if (typeof callback === 'function') {
        callback();
      }
    };
    script.onerror = (error) => {
      reject(error);
    };
    document.head.appendChild(script);
  });
}

// 动态加载 Vue 和 axios 的 CDN 脚本
async function loadFastCdnScripts() {
  const vueUrl = getFastCdnUrl('vue');
  const axiosUrl = getFastCdnUrl('axios');

  // 等待 Vue 和 axios 加载完成
  await Promise.all([
    loadCdnScript(vueUrl),
    loadCdnScript(axiosUrl)
  ]);

  // 所有 CDN 脚本加载完成后,初始化 Vue 应用
  initializeVueApp();
}

// 初始化 Vue 应用的函数
function initializeVueApp() {
  // 在这里初始化你的 Vue 实例
  new Vue({
    // ...
  }).$mount('#app');
}

// 在页面加载完成后加载 CDN 脚本
document.addEventListener('DOMContentLoaded', () => {
  loadFastCdnScripts();
});

请注意,以上代码仅提供了一个基本的框架,你需要根据自己的项目结构和需求来调整。特别是 getFastCdnUrl 函数需要实现具体的 CDN 选择逻辑,比如可以发送预加载请求并测量响应时间等。

确保在调用 initializeVueApp 之前,Vue 和 axios 的 CDN 脚本已经成功加载到页面上。通过这种方式,你就可以动态地选择并使用最快的 CDN 来加载你的依赖,并且保证在它们加载完成后再初始化 Vue 应用。

2 个回答

我感觉等你判断好了,这点时间都说不定随便挑一个cdn都加载完了

为了在使用 Vue 和 axios 等库时动态选择最快的 CDN 并确保这些库在主程序加载前就已经加载完毕,可以遵循以下步骤:
1. 创建动态加载 CDN 的函数
首先,创建一个函数 loadFastCdnScripts,用于动态加载 CDN 脚本并确保在脚本加载完成后才继续加载主程序。

function loadFastCdnScripts(urls, callback) {
    let loaded = false;
    const head = document.getElementsByTagName('head')[0];

    urls.forEach(url => {
        const script = document.createElement('script');
        script.src = url;
        script.onload = () => {
            if (!loaded) {
                loaded = true;
                callback();
            }
        };
        script.onerror = () => {
            console.error(`Failed to load script: ${url}`);
        };
        head.appendChild(script);
    });
}

2. 在主程序加载前调用该函数
在你的 index.html 文件中调用这个函数,并确保在加载主程序前完成 CDN 脚本的加载。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue App</title>
    <script>
        function loadFastCdnScripts(urls, callback) {
            let loaded = false;
            const head = document.getElementsByTagName('head')[0];

            urls.forEach(url => {
                const script = document.createElement('script');
                script.src = url;
                script.onload = () => {
                    if (!loaded) {
                        loaded = true;
                        callback();
                    }
                };
                script.onerror = () => {
                    console.error(`Failed to load script: ${url}`);
                };
                head.appendChild(script);
            });
        }

        const vueCdnUrls = [
            "https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.16/vue.min.js",
            "https://cdn.jsdelivr.net/npm/vue@2.7.16/dist/vue.min.js",
            // Add more URLs as needed
        ];

        const axiosCdnUrls = [
            "https://cdnjs.cloudflare.com/ajax/libs/axios/0.24.0/axios.min.js",
            "https://cdn.jsdelivr.net/npm/axios@0.24.0/dist/axios.min.js",
            // Add more URLs as needed
        ];

        function loadScriptsSequentially(urls, callback) {
            if (urls.length === 0) {
                callback();
                return;
            }

            loadFastCdnScripts(urls[0], () => {
                loadScriptsSequentially(urls.slice(1), callback);
            });
        }

        window.onload = function() {
            loadScriptsSequentially(vueCdnUrls, () => {
                loadScriptsSequentially(axiosCdnUrls, () => {
                    // Now all required scripts are loaded
                    const script = document.createElement('script');
                    script.src = "main.js"; // Your main JavaScript file
                    document.body.appendChild(script);
                });
            });
        };
    </script>
</head>
<body>
    <div id="app"></div>
</body>
</html>

3. Webpack 配置
确保你的 webpack.config.js 中使用了 externals 配置,以避免将 Vue 和 axios 打包到你的主程序中:

module.exports = {
    // other configurations
    externals: {
        vue: 'Vue',
        axios: 'axios'
    }
};

4. 在主程序中使用外部库
确保在你的主程序(main.js 或其他入口文件)中,Vue 和 axios 是作为全局变量使用的,因为它们是通过 CDN 加载的外部库:

// main.js

new Vue({
    el: '#app',
    data: {
        message: 'Hello Vue!'
    }
});

通过以上步骤,你可以确保 Vue 和 axios 通过最快的 CDN 加载,并在加载完成后才开始执行主程序代码。这将避免 Vue is undefined 的错误,并提高加载效率和稳定性。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题