经纬志
首页 / 实战手册 / 工程化

import 一个 CommonJS 包,构建直接报错

先看结论

引入 proj4 做坐标换算,开发环境正常,构建时提示模块没有默认导出,打包中断。

最后验证 2026-11-03 · 多技术栈 · proj4 2.12 · 更新 2026-10-29 · 引用本文

现象

npm run dev 正常,npm run build 报错:

error during build:
SyntaxError: The requested module '/node_modules/.vite/deps/proj4.js?v=9a1c3f2e'
does not provide an export named 'default'

用 webpack 时是另一条提示,本质相同:

WARNING in ./src/geo/transform.js
"export 'default' (imported as 'proj4') was not found in 'proj4'

原因

proj4 发布的是 UMD 包,主入口 dist/proj4-src.js 通过 module.exports 导出。ESM 与 CJS 的互操作规则由构建工具决定: 浏览器原生 ESM 不会自动为 CJS 模块合成 default, 预构建阶段如果没有正确识别,就会报导出名缺失。

把它当成 ESM 写命名导入(import { transform } from 'proj4')也会失败, CJS 模块的属性不是静态可分析的命名导出。

排查过程

  1. 看包的 package.json,确认 main 与 module 字段。
  2. 在 Node 里试 require('proj4') 与 import('proj4'),对比导出形状。
  3. 看构建日志里是否提到 commonjs 或 optimizeDeps。
node -e "const p = require('proj4'); console.log(typeof p, Object.keys(p).slice(0,5));"
# function [ 'default', 'Proj', 'transform', ... ]

解决方案

显式把 proj4 加入预构建,并在代码里用默认导入。Vite 会在依赖预构建阶段处理 CJS:

// vite.config.js
export default {
  optimizeDeps: {
    include: ['proj4']
  },
  build: {
    commonjsOptions: {
      transformMixedEsModules: true
    }
  }
};
import proj4 from 'proj4';

var wgs84 = '+proj=longlat +datum=WGS84 +no_defs';
var webMercator = '+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +no_defs';

var xy = proj4(wgs84, webMercator, [116.391, 39.907]);
console.log(xy);   // [12956581.2, 4852296.7]

构建工具的互操作仍然不生效时,用命名空间导入再取 default, 这是最兼容的写法:

import * as proj4Module from 'proj4';

var proj4 = proj4Module.default || proj4Module;

var xy = proj4(wgs84, webMercator, [116.391, 39.907]);

换用本身提供 ESM 的替代包也是可行路径,例如 proj4js 的 新版入口,或自己写一层只做 Web Mercator 换算的轻量函数:

function toWebMercator(lng, lat) {
  var R = 6378137;
  var x = R * lng * Math.PI / 180;
  var y = R * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360));
  return [x, y];
}

验证

npm run build 通过,不再提示 does not provide an export named 'default'。 页面中坐标换算结果与在线转换工具一致,误差小于 0.5 米。 打包产物体积没有因为引入整包而显著增加。

先查包格式:package.json 里只有 main、 没有 module 或 exports,基本可以确定是 CJS。 这类包一律用默认导入,不要写命名导入。

引用本文

经纬志(2026)。《import 一个 CommonJS 包,构建直接报错》。https://www.jingweizhi.com/cookbook/esm-cjs-mixed.html(访问日期 2026-11-03)。