You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目如何为构建自动注入的Script标签添加defer/async属性

CRA项目为自动注入的Script/Link标签添加defer/async属性配置方案

CRA构建时自动注入静态资源标签的逻辑由内置的html-webpack-plugin实现,不需要手动修改构建产物,根据项目是否eject选择对应配置方式即可:

未Eject项目(推荐,保留官方升级能力)

使用配置覆写工具修改内置webpack配置即可,以兼容性更好的@craco/craco为例:

  • 安装开发依赖
    npm i @craco/craco -D
    
  • 修改package.json中的脚本命令,将原有的react-scripts替换为craco:
    {
      "scripts": {
        "start": "craco start",
        "build": "craco build",
        "test": "craco test"
      }
    }
    
  • 在项目根目录新建craco.config.js,写入配置逻辑:
    module.exports = {
      webpack: {
        configure: (webpackConfig) => {
          // 定位内置的html-webpack-plugin实例
          const htmlPlugin = webpackConfig.plugins.find(
            plugin => plugin.constructor.name === 'HtmlWebpackPlugin'
          )
          if (!htmlPlugin) return webpackConfig
    
          // 全局给所有注入的script标签加defer,需要async就改为'async'
          htmlPlugin.userOptions.scriptLoading = 'defer'
    
          // 细粒度控制标签属性,支持扩展Link标签配置
          htmlPlugin.userOptions.transformTags = (tags) => {
            return tags.map(tag => {
              // 处理Script标签:可按chunk路径、资源类型单独给指定资源加属性
              if (tag.tagName === 'script') {
                // 示例:给异步加载的业务chunk单独加async属性
                // if (tag.attributes.src?.includes('async-chunk')) {
                //   delete tag.attributes.defer
                //   tag.attributes.async = true
                // }
              }
    
              // 扩展处理Link标签:可针对CSS、预加载资源做自定义属性配置
              if (tag.tagName === 'link') {
                // 示例:给非关键CSS做延迟加载
                // if (tag.attributes.rel === 'stylesheet' && !tag.attributes.href.includes('critical')) {
                //   tag.attributes.media = 'print'
                //   tag.attributes.onload = "this.media='all'"
                // }
              }
    
              return tag
            })
          }
    
          return webpackConfig
        }
      }
    }
    

如果习惯用react-app-rewired,配置逻辑完全一致,只需要把上述webpack修改逻辑写到根目录的config-overrides.js中即可。

已Eject项目

Eject后可以直接修改内置webpack配置,打开config/webpack.config.js,搜索HtmlWebpackPlugin找到插件配置块:

  • 全局生效:直接在配置项中添加scriptLoading: 'defer',需要async则传值'async'
  • 细粒度控制:和未Eject场景一致,在插件配置中添加transformTags方法,自定义标签转换逻辑即可
  • 修改完成后保存,重新执行构建命令生效

注意事项

  • 同一个Script标签不要同时添加defer和async属性,两者执行逻辑差异较大:async为资源下载完成后立刻执行,会中断HTML解析;defer为HTML全部解析完成后按脚本引入顺序执行,更适合普通业务JS场景
  • 配置完成后执行npm run build,查看build/index.html产物即可验证标签属性是否注入成功
  • 所有Link标签的自定义属性需求,都可以在transformTags的link判断分支中实现,直接修改tag.attributes对象即可

内容的提问来源于stack exchange,提问作者user11392477

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:27:24