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

如何在Next.js 13中实现类似Webpack的externals功能?

在Next.js 13中实现Webpack externals加载外部脚本(ymaps3)的等效方案

Webpack中的实现示例

在Webpack中,可通过配置externals将外部组件(如第三方模块)加载到应用并直接导入。以下是加载无React包装的外部脚本ymaps3的示例配置:

// Generated using webpack-cli https://github.com/webpack/webpack-cli
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const isProduction = process.env.NODE_ENV == "production";

const config = {
  entry: "./src/index.ts",
  output: {
    path: path.resolve(__dirname, "dist")
  },
  devServer: {
    host: "localhost"
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "index.html"
    })
  ],
  externalsType: "script",
  externals: {
    // ymaps3: ["https://api-maps.yandex.ru/3.0/?apikey=4a75efd1-e36a-4f02-8957-954d09371435&lang=ru-RU", "ymaps3"],
    ymaps3: [
      `promise new Promise((resolve) => {
        const script = document.createElement('script');
        script.src = "https://api-maps.yandex.ru/3.0/?apikey=4a75efd1-e36a-4f02-8957-954d09371435&lang=ru-RU";
        script.async = true;
        script.onload = () => {
          ymaps3.ready.then(() => resolve(ymaps3));
          script.remove();
        };
        document.body.appendChild(script);
      })`
    ]
  },
  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/i,
        loader: "ts-loader",
        exclude: ["/node_modules/"]
      }
    ]
  },
  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", "..."]
  }
};

module.exports = () => {
  if (isProduction) {
    config.mode = "production";
  } else {
    config.mode = "development";
  }
  return config;
};

Next.js 13中的实现方案

Next.js 13通过next.config.js配置Webpack参数,以此实现和上述Webpack配置相同的效果,让你可以像导入模块一样使用ymaps3。

1. 配置next.config.js

在项目根目录创建或修改next.config.js,添加Webpack externals配置:

/** @type {import('next').NextConfig} */
const nextConfig = {
  webpack: (config) => {
    // 设置外部资源类型为脚本
    config.externalsType = 'script';
    config.externals = {
      ymaps3: [
        `promise new Promise((resolve) => {
          const script = document.createElement('script');
          script.src = "https://api-maps.yandex.ru/3.0/?apikey=4a75efd1-e36a-4f02-8957-954d09371435&lang=ru-RU";
          script.async = true;
          script.onload = () => {
            ymaps3.ready.then(() => resolve(ymaps3));
            script.remove();
          };
          document.body.appendChild(script);
        })`
      ]
    };
    return config;
  },
};

module.exports = nextConfig;

2. 添加类型声明(TypeScript项目)

为避免TypeScript类型报错,在项目根目录或src目录下创建ymaps3.d.ts文件:

declare module 'ymaps3' {
  export const ready: Promise<void>;
  export const reactify: {
    bindTo(react: typeof import('react'), reactDom: typeof import('react-dom')): {
      module(ymaps: any): {
        YMap: React.ComponentType<any>;
        // 根据需要补充更多组件类型
      };
    };
  };
  // 可参考Yandex Maps官方文档补充完整类型定义
}

3. 组件中使用ymaps3

如果使用App Router,需要在组件顶部添加'use client'指令(客户端组件);Pages Router则无需此步骤。示例代码如下:

'use client';

import * as ymaps3 from 'ymaps3';
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom/client';

function Map() {
  const [loaded, setLoaded] = useState(true);

  useEffect(() => {
    // 等待ymaps3初始化完成
    ymaps3.ready.then(() => setLoaded(false));
  }, []);

  if (loaded) {
    return <div>加载中...</div>;
  }

  // 绑定React和ReactDOM,创建React化的地图组件
  const reactify = ymaps3.reactify.bindTo(React, ReactDOM);
  const { YMap } = reactify.module(ymaps3);

  return <YMap />;
}

export default function App() {
  return (
    <div>
      <button>按钮</button>
      <Map />
    </div>
  );
}

注意事项

  • 替换代码中的apikey为你自己的Yandex Maps API密钥。
  • 若使用Pages Router,将组件放在pages目录下即可,无需'use client'。
  • 类型声明可根据官方文档补充更详细的内容,提升开发体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:23:19