使用Rollup打包模块脚本时,如何将外部导入重写为esm.sh的CDN路径
解决方案:用Rollup重写裸模块导入为esm.sh CDN链接
嘿,这个需求完全可以通过Rollup的插件来实现,我给你两个靠谱的方案,都不用依赖importmap:
方案1:用专门的rollup-plugin-esm-sh插件(最简单)
这个插件就是为esm.sh量身打造的,能自动把裸模块导入转换成对应的CDN链接,还能帮你统一管理包版本,配置起来超省心。
- 先安装插件:
npm install rollup-plugin-esm-sh --save-dev
- 在你的
rollup.config.js里配置:
import esmSh from 'rollup-plugin-esm-sh'; export default { input: 'src/main.js', // 替换成你的项目入口文件路径 output: { file: 'dist/bundle.js', format: 'es' // 必须是ES模块格式,才能在<script type="module">里用 }, plugins: [ esmSh({ // 在这里指定你需要的包和对应的版本 versions: { 'react': '19.2.4', 'react-dom': '19.2.4' } }) ] };
打包之后,你源码里的import { createRoot } from 'react-dom/client';就会自动变成import { createRoot } from 'https://esm.sh/react-dom@19.2.4/client';,完美符合你的要求。
方案2:自定义Rollup插件(更灵活)
如果你需要更定制化的逻辑——比如要支持多个CDN源、处理一些特殊的包路径——那自己写个极简的Rollup插件就很合适,利用Rollup的transform钩子就能轻松实现导入语句替换:
直接在rollup.config.js里添加这个自定义插件:
export default { input: 'src/main.js', output: { file: 'dist/bundle.js', format: 'es' }, plugins: [ { name: 'rewrite-imports-to-cdn', // 插件名称,随便起 transform(code) { // 先定义好你要映射的包和版本 const packageVersions = { 'react': '19.2.4', 'react-dom': '19.2.4' // 其他依赖包也可以在这里添加 }; // 用正则匹配所有导入语句,支持带子路径的情况 return code.replace( /import\s+(.*?)\s+from\s+['"]([^'"]+)['"]/g, (match, imports, specifier) => { // 把比如'react-dom/client'拆成包名和子路径两部分 const [packageName, ...subPathParts] = specifier.split('/'); // 如果这个包在我们的配置里,就替换成CDN链接 if (packageVersions[packageName]) { const cdnUrl = `https://esm.sh/${packageName}@${packageVersions[packageName]}${subPathParts.length ? `/${subPathParts.join('/')}` : ''}`; return `import ${imports} from '${cdnUrl}'`; } // 如果是本地模块或者没配置的包,就保持原样 return match; } ); } } ] };
这个插件会扫描所有导入语句,精准替换你配置好的包,同时保留子路径,完全适配你的场景。
几个小提醒
- 一定要确保Rollup的输出格式是
es,不然没法在<script type="module">里正常加载。 - 如果项目里有其他第三方依赖,记得在
packageVersions里添加上对应的包名和版本号,插件才会帮你替换。 - 自定义插件的正则可以根据你的实际代码写法调整,比如如果有
import * as React from 'react'这种写法,当前的正则也能完美匹配。
内容的提问来源于stack exchange,提问作者Thom Smith
相关产品推荐
相关产品推荐

