oxc-project/oxc · warning · OxcDiagnostic

Prevent synchronous scripts.

Error message

Prevent synchronous scripts.

What it means

Warning from oxlint rule `nextjs/no-sync-scripts`. A `<script src="...">` without `async` or `defer` blocks HTML parsing and delays hydration; in a hydration framework it also risks the script running before React is ready. The rule requires any raw script tag with a literal `src` to be non-blocking.

Source

Thrown at crates/oxc_linter/src/rules/nextjs/no_sync_scripts.rs:13

use oxc_ast::{
    AstKind,
    ast::{JSXAttributeItem, JSXAttributeName, JSXElementName},
};
use oxc_diagnostics::OxcDiagnostic;
use oxc_macros::declare_oxc_lint;
use oxc_span::Span;
use rustc_hash::FxHashSet;

use crate::{AstNode, context::LintContext, rule::Rule};

fn no_sync_scripts_diagnostic(span: Span) -> OxcDiagnostic {
    OxcDiagnostic::warn("Prevent synchronous scripts.")
        .with_help("See https://nextjs.org/docs/messages/no-sync-scripts")
        .with_label(span)
}

#[derive(Debug, Default, Clone)]
pub struct NoSyncScripts;

declare_oxc_lint!(
    /// ### What it does
    ///
    /// Prevent the use of synchronous `<script>` tags in Next.js applications.
    /// Require any `<script>` tag with a `src` attribute to also have either
    /// the `async` or `defer` attribute.
    ///
    /// ### Why is this bad?
    ///
    /// Synchronous scripts can block the page rendering and negatively impact performance.
    /// In Next.js applications, it's recommended to use `async` or `defer` attributes

View on GitHub (pinned to e1e7af627c)

Solutions

  1. Add `async` (independent script) or `defer` (order-dependent) to the tag.
  2. Prefer `<Script src="..." />` from `next/script`, which defaults to `afterInteractive` and handles ordering for you.

Example fix

// before
<script src="https://widget.example/sdk.js" />

// after
import Script from 'next/script';
<Script src="https://widget.example/sdk.js" />
Defensive patterns

Strategy: validation

Validate before calling

// raw script tags with src and no async/defer:
// rg -n '<script[^>]*src=' -g '*.tsx' src | rg -v 'async|defer|next/script'

Prevention

When it happens

Trigger: A native `<script>` JSX element with a string-literal `src` attribute and neither `async` nor `defer` present.

Common situations: Embedding vendor widgets (chat, maps, surveys) by copying their default snippet; note that inline scripts without `src` are outside this rule's scope.

Related errors


AI-assisted analysis of oxc-project/oxc@e1e7af627c (2026-08-20). Data as JSON: /api/errors/7c3ac07f4c0e9fce. Report an issue: GitHub.