我创建了一个小型 JS 模块,打算将其制作为 npm 包,但目前仅在 GitHub 上。该模块是用 ES6 和 SCSS 编写的,因此依赖于 webpack 和 babel 进行转译。
为了测试它,我创建了一个具有类似设置的单独项目(webpack 和 babel)。在 npm 安装我的模块后,当尝试将其导入我的 index.js 时,我在 Chrome 开发人员工具中收到以下错误:(x 是我的模块名称)
index.js:11 Uncaught TypeError: x__WEBPACK_IMPORTED_MODULE_1___default.a is not a constructor
at eval (index.js:11)
at Object../src/index.js (main.js:368)
at __webpack_require__ (main.js:20)
at eval (webpack:///multi_(:8081/webpack)-dev-server/client?:2:18)
at Object.0 (main.js:390)
at __webpack_require__ (main.js:20)
at main.js:69
at main.js:72
我查阅了无数的答案,尝试了无数的解决方案,但都无济于事。我的模块设置如下。
.babelrc
{
"presets": [
["env", {
"targets": {
"browsers": ["ie >= 11"]
}
}]
],
"plugins": [
"transform-es2015-modules-commonjs",
"transform-class-properties"
]
}
webpack.common.js
const path = require('path')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const cleanWebpackPlugin = require('clean-webpack-plugin')
const baseSCSS = new ExtractTextPlugin('main/_base.css')
const themeSCSS = new ExtractTextPlugin('main/_theme.css')
module.exports = {
entry: {
example: [
path.join(__dirname, 'src', 'example', 'index.js')
],
main: [
'idempotent-babel-polyfill',
path.join(__dirname, 'src', 'index.js')
]
},
output: {
path: path.join(__dirname, 'dist'),
filename: path.join('[name]', 'index.js')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
}
)
},
{
test: /\_base-scss$/,
use: baseSCSS.extract(
{
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
}
)
},
{
test: /\_theme-scss$/,
use: themeSCSS.extract(
{
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
}
)
}
]
},
plugins: [
new cleanWebpackPlugin('dist', {}),
new ExtractTextPlugin({ filename: path.join('example', 'style.css') }),
baseSCSS,
themeSCSS,
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: path.join(__dirname, 'src', 'example', 'index.html'),
filename: path.join('example', 'index.html')
})
]
}
webpack.prod.js
const merge = require('webpack-merge')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const webpack = require('webpack')
const common = require('./webpack.common.js')
module.exports = merge(common, {
plugins: [
new UglifyJSPlugin({
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
],
mode: 'production'
})
package.json
{
"name": "my-module-name",
"version": "1.0.0-beta.1",
"description": "",
"main": "dist/main/index.js",
"scripts": {
"start": "webpack-dev-server --config webpack.dev.js",
"server": "node src/server",
"format": "prettier-standard 'src/**/*.js'",
"lint": "eslint src",
"build": "webpack --config webpack.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Liran",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-eslint": "^8.2.3",
"babel-loader": "^7.1.4",
"babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"babel-preset-env": "^1.7.0",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-webpack-plugin": "^3.2.0",
"idempotent-babel-polyfill": "^0.1.1",
"node-sass": "^4.9.0",
"prettier-standard": "^8.0.1",
"sass-loader": "^7.0.1",
"style-loader": "^0.21.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.6.0",
"webpack-cli": "^2.0.15",
"webpack-dev-middleware": "^3.1.3",
"webpack-dev-server": "^3.1.3",
"webpack-merge": "^4.1.2"
}
}
任何帮助/指示将不胜感激。如果您需要更多信息,请告诉我。
如果您不是库作者并且在使用另一个库时遇到问题,您可能会看到如下错误:
TypeError: [LIBRARY_NAME]__WEBPACK_IMPORTED_MODULE_3__ is not a constructor
如果是这种情况,您可能在代码中错误地导入了库(这可能是默认导出的问题)。仔细检查库文档的使用情况。
可能就像更改此一样简单:
import Foo from 'some-library/Foo';
对此:
import { Foo } from 'some-library';
libraryTarget and library
属性。通过这样做,webpack 知道您想要创建哪种格式的模块,即:commonjs (module.exports
) 或 es (export
)。
我会做类似的事情:
...
output: {
path: path.join(__dirname, 'dist'),
filename: path.join('[name]', 'index.js'),
library: "my-library",
libraryTarget: "umd" // exposes and know when to use module.exports or exports.
},
...
除了设置
libraryTarget
之外,可能还需要将 JavaScript 文件中的 export
移至默认值。
function MyClassName() {
...
}
export default MyClassName;
然后在 webpack 配置中库类型
umd
...
(请注意,我使用了较新的
library.type
而不是较旧的 libraryTarget
(请参阅 https://webpack.js.org/configuration/output/#outputlibrarytarget)。
const path = require('path');
module.exports = {
mode: "production",
entry: '../wherever/MyClassName.js',
output: {
library: {
name: "MyClassName",
type: "umd", // see https://webpack.js.org/configuration/output/#outputlibrarytype
export: "default", // see https://github.com/webpack/webpack/issues/8480
},
filename: 'MyClassName.min.js',
path: path.resolve(__dirname, '../wherever/target/')
},
optimization: {
minimize: true
}
};
export default
使该类在 JavaScript 中可用,就像直接嵌入文件一样,即
<script type="text/javascript" src="MyClassName.min.js"></script>
<script type="text/javascript">
<!--
var myInstance = new MyClassName();
// -->
</script>
免责声明:尽管原来的问题已经存在三年了,但我还是添加了这个答案。在遇到“不是构造函数”问题后,我花了几个小时才找到
default
解决方案。那是第二次,我搜索并找到了它:D
如果有东西正在使用 wepack 5 + babel 7
"webpack": "5.73.0",
"@babel/core": "7.4.4",
"@babel/preset-env": "7.4.4",
"babel-loader": "8.0.5",
AND想使用class代替function,这对我有用:
class Person {
constructor(fname, lname, age, address) {
this.fname = fname;
this.lname = lname;
this.age = age;
this.address = address;
}
get fullname() {
return this.fname +"-"+this.lname;
}
}
export default Person;
就我而言 .babelrc 不是必需的
参见。 David Calhoun 的回答,如果您使用第三方库遇到此问题,您可能会尝试将 CommonJS 模块 作为 ECMAScript 模块 导入。解决方法似乎是使用
require
而不是 import
,例如,而不是
import { Foo } from 'bar'
你需要写
const Foo = require('bar')
(可能有更优雅的方法来处理这个问题,但这对我有用。)
对我来说,这是缓存问题。刚刚清除cookies,缓存数据并关闭,重新打开浏览器。成功了。
就我而言,错误是在 React 中尝试调用 JS 的内置
Error
构造函数时引起的,或者换句话说,基本上是在调用 throw new Error("something")
时引起的。
检查我的代码时,我意识到我的项目中有一个名为
Error
的组件,它被导入到同一个文件中。该组件与 JS 内置 Error
构造函数之间的名称冲突导致了问题中提到的错误。
确保通过索引文件正确导入。
对我来说,这个错误是通过索引文件导入引起的。我有多个目录,其中的
index.ts
文件导出了目录内的所有文件。这些索引文件由主 index.ts
文件累积/重新导出,因此所有内容都可以通过它导入。
src/
├── index.ts
├── module1/
│ ├── index.ts
│ ├── file1.ts
│ └── file2.ts
└── module2/
├── index.ts
├── file3.ts
└── file4.ts
在
file4.ts
我有这样的导入:
import { file1Class, file2Class, file3Class } from "src";
我必须将其分成两个单独的导入:
import { file1Class, file2Class } from "src/module1";
import { file3Class } from "src/module2";