发布到npm的webpack打包模块引入报错:TypeError: <myModule> is not a function
首先可以明确:这个问题的核心是webpack的打包配置问题,和babel-loader的关系不大,也不是你源码里函数声明/使用的问题——毕竟直接用src源码能正常工作,说明你的代码本身是没问题的。
为什么指向src能正常用?
你源码里的导出方式(不管是ES模块的export/export default,还是CommonJS的module.exports)是符合标准模块规范的,其他应用引入时能直接识别对应的导出内容。
打包后报错的原因
webpack默认会把你的代码包裹在一个独立的闭包环境里,如果没有正确配置output选项中的模块导出规则,打包后的文件会把你的函数包装在一个复杂的对象结构里,而不是直接暴露成可调用的函数。比如:
- 如果你原本是导出单个函数,打包后可能变成了
{ default: 你的函数 }或者其他嵌套结构,这时候用import { myFunc }去引入自然拿不到正确的函数,就会报“不是函数”的错误。
具体解决步骤
调整webpack的output配置
打开你的模块项目的webpack.config.js,确保output里配置了正确的导出格式,推荐用umd格式来兼容多种模块规范(CommonJS、AMD、浏览器全局变量):const path = require('path'); module.exports = { // ...其他配置 output: { filename: 'index.js', path: path.resolve(__dirname, 'dist'), library: 'myModule', // 可选,全局变量模式下的模块名称 libraryTarget: 'umd', // 关键:支持多种模块导入方式 libraryExport: 'default', // 如果你的源码是用export default导出的函数,需要加这个;如果是命名导出,可改为对应的函数名或者去掉 globalObject: 'this', // 避免浏览器和Node环境下的全局对象冲突 } };确认源码的导出方式
- 如果是命名导出(比如
export const myFunc = () => {}):可以去掉libraryExport,或者把它设为myFunc;其他应用引入时用import { myFunc } from '你的模块名'。 - 如果是默认导出(比如
export default myFunc):必须加上libraryExport: 'default',其他应用可以用import myFunc from '你的模块名'或者import { default as myFunc } from '你的模块名'。
- 如果是命名导出(比如
验证打包后的模块结构
打包后可以在本地快速测试:新建一个js文件,用Node引入打包后的文件,打印看看导出内容的结构:const moduleContent = require('./dist/index.js'); console.log(moduleContent);如果打印出来是
{ default: [Function: myFunc] },说明你需要调整libraryExport或者修改引入方式;如果直接打印出函数,说明配置正确了。
关于babel-loader的说明
babel-loader主要负责转译ES6+语法到低版本兼容的代码,除非你特意配置了改变模块导出的插件(比如@babel/plugin-transform-modules-umd),否则它不会影响模块的导出结构,所以这个问题基本和它无关。
内容的提问来源于stack exchange,提问作者pop42

