JavaScript无阻塞加载的方式

JavaScript无阻塞加载的方式

在 JavaScript 中,无阻塞加载(Non-blocking Loading)是优化网页性能的关键技术,通过避免脚本阻塞页面渲染和其他资源的加载,提升用户体验。以下是实现无阻塞加载的常用方法及示例:

1. 使用 async 属性

  • 作用:异步加载脚本,下载完成后立即执行,不阻塞 HTML 解析。

  • 适用场景:独立脚本,不依赖其他脚本或 DOM。

  • 示例

    html 复制代码
    <script async src="script.js"></script>

2. 使用 defer 属性

  • 作用:异步加载脚本,但延迟到 HTML 解析完成后按顺序执行。

  • 适用场景:需要按顺序执行且依赖 DOM 的脚本。

  • 示例

    html 复制代码
    <script defer src="script1.js"></script>
    <script defer src="script2.js"></script> <!-- script1 先执行 -->

3. 动态脚本加载

通过 JavaScript 动态创建 <script> 标签,实现按需加载。

  • 适用场景:非关键脚本或条件加载。

  • 示例

    javascript 复制代码
    function loadScript(src) {
        const script = document.createElement('script');
        script.src = src;
        document.body.appendChild(script);
    }
    // 在需要时加载
    window.addEventListener('DOMContentLoaded', () => {
        loadScript('script.js');
    });

4. 使用 Promiseasync/await 控制加载顺序

结合动态加载和 Promise,管理脚本依赖关系。

  • 示例

    javascript 复制代码
    function loadScript(src) {
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = src;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    }
    
    async function init() {
        await loadScript('lib.js');
        await loadScript('app.js'); // 确保 lib.js 先加载
    }
    init();

5. 使用 Intersection Observer 延迟加载

在元素进入视口时加载脚本,适用于非首屏资源。

  • 示例

    javascript 复制代码
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                loadScript('lazy-script.js');
                observer.unobserve(entry.target);
            }
        });
    });
    observer.observe(document.querySelector('#lazy-element'));

6. 模块化动态导入(ES6 import()

按需加载 ES6 模块,适用于现代浏览器。

  • 示例

    javascript 复制代码
    button.addEventListener('click', async () => {
        const module = await import('./module.js');
        module.doSomething();
    });

7. 使用 Web Workers 处理计算密集型任务

将耗时任务移至后台线程,避免阻塞主线程。

  • 示例

    javascript 复制代码
    const worker = new Worker('worker.js');
    worker.postMessage({ data: 'start' });
    worker.onmessage = (e) => {
        console.log('Result:', e.data);
    };

8. 资源预加载(preloadprefetch

通过 <link> 标签提示浏览器提前加载资源。

  • preload :高优先级资源,当前页面使用。

    html 复制代码
    <link rel="preload" href="critical.js" as="script">
  • prefetch :低优先级资源,未来页面可能使用。

    html 复制代码
    <link rel="prefetch" href="next-page.js" as="script">

9. 条件加载(根据浏览器特性)

检测浏览器支持后加载特定脚本。

  • 示例

    javascript 复制代码
    if ('IntersectionObserver' in window) {
        loadScript('modern-script.js');
    } else {
        loadScript('fallback-script.js');
    }

10. 服务端异步加载(SSR + Hydration)

结合服务端渲染(SSR)和客户端激活(Hydration),按需加载交互逻辑。

  • 示例 (Next.js 框架):

    javascript 复制代码
    import dynamic from 'next/dynamic';
    const DynamicComponent = dynamic(() => import('../components/HeavyComponent'));

总结

方法 核心原理 适用场景 优点 缺点
async/defer 异步加载脚本 首屏非关键脚本 简单易用 async 不保证执行顺序
动态脚本加载 按需创建<script> 标签 非关键脚本/条件加载 灵活控制加载时机 需手动管理依赖
import() 动态导入 按需加载 ES6 模块 现代浏览器应用 模块化支持 需支持 ES6 模块
Intersection Observer 延迟加载视口外资源 图片、懒加载组件 高性能懒加载 兼容性需处理
Web Workers 后台线程执行任务 计算密集型操作 避免主线程阻塞 无法直接操作 DOM
资源预加载 提前加载关键资源 优化关键路径 减少加载延迟 可能浪费带宽

注意事项

  • 依赖管理 :确保异步脚本的执行顺序(如使用 deferPromise)。
  • 兼容性 :旧版浏览器(如 IE)不支持 async/defer 和 ES6 模块,需降级处理。
  • 性能监控:使用工具(如 Lighthouse)分析加载性能,针对性优化。

通过合理组合这些方法,可显著提升页面加载速度和交互体验。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github

相关推荐
kidding7231 天前
高效备忘清单工具类小程序
前端·计算机网络·微信小程序·小程序
IMPYLH1 天前
HTML 的 <abbr> 元素
前端·算法·html
小鹿软件办公1 天前
倒计时开启:Chromium 宣布几周内将全面切断 MV2 扩展支持
开发语言·javascript·ublock origin
李白的天不白1 天前
Tree-Shaking
前端
Csvn1 天前
TypeScript:你以为安全的 `JSON.parse` 其实是颗雷 — 运行时类型安全实战
前端·javascript
触底反弹1 天前
从 JS 引擎执行原理理解数据类型:栈内存、堆内存与作用域
javascript·数据结构·面试
橘子星1 天前
深入理解线性数据结构:栈、队列与链表
前端·javascript
dadaobusi1 天前
Linux内核完成大量内存/调度/时间子系统初始化的关键阶段
java·linux·前端
用户059540174461 天前
Redis 缓存过期不一致踩坑实录:一个 bug 让我排查了 3 小时,最终用 Pytest 自动化堵上漏洞
前端·css
东风破_1 天前
AJAX 异步请求:从回调地狱到 async/await,到底解决了什么?
前端