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

相关推荐
禅思院1 小时前
AI对话前端从入门到崩溃:一个长对话引发的五层优化战争【引子】
前端·面试·架构
TrisighT2 小时前
Electron 鸿蒙 PC 上点外链唤醒应用,我试了 6 种写法只有 1 种能跑
前端·electron·harmonyos
天才熊猫君3 小时前
配置与数据分离:一种可视化搭建的属性编辑方案
前端·javascript
林希_Rachel_傻希希3 小时前
web性能之相关路径——AI总结
前端·javascript·面试
不好听6133 小时前
从零搭建一个 RAG 语义搜索系统 —— DEMO的初始阶段
javascript·面试·llm
何时梦醒3 小时前
上下文工程(Context Engineering):AI 应用开发的新范式 —— 从理论到实战全解析
javascript
竹林8183 小时前
用 wagmi v2 踩坑两天,我终于搞懂了多链钱包切换在 DeFi 前端中的正确姿势
前端·javascript
用户2136610035723 小时前
Vue项目搜索功能与面包屑导航
前端·javascript
星栈3 小时前
LiveView 的实时通信,爽是爽,但 PubSub 和广播也最容易把自己绕晕
前端·前端框架·elixir
用户2930750976693 小时前
告别关键词匹配,拥抱向量语义 —— RAG 搜索从零到一
前端