如何在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
相关产品推荐
相关产品推荐

