Webpack (in prod) bundles give error: TypeError: (0 , tm.useEffect) is not a function...why?
Webpack (in prod) bundles give error: TypeError: (0 , tm.useEffect) is not a function...why?
我的 React 应用程序使用 Webpack + Babel。当我在开发中编译时,一切都运行良好。
当我为生产打包(“npm 运行 build”)并在 prod 中上传打包时,控制台中出现错误:
为什么?我发现了一个类似的问题,但没有找到答案:
这是我的 webpack.prod.js
配置:
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ProvidePlugin, web } = require("webpack");
const cleanPlugin = require("clean-webpack-plugin");
module.exports = {
mode: "production",
devtool: "source-map",
entry: ["regenerator-runtime/runtime.js", "./src/index.js"],
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js",
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
exclude: /[\/]node_modules[\/]/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg$/,
use: {
loader: "svg-url-loader",
},
},
],
},
resolve: {
alias: { react: path.resolve("./node_modules/react") },
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
title: "Production",
}),
//no need to import react in every module
new ProvidePlugin({
React: "react",
}),
//erase "dist" bundle before every "npm run build"
new cleanPlugin.CleanWebpackPlugin(),
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
Package.json:
{
"name": "timerfrontend",
"version": "1.0.0",
"main": "index.js",
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --config webpack.config.js",
"create": "webpack -w",
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.16.5",
"@babel/preset-env": "^7.16.5",
"@babel/preset-react": "^7.16.5",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.3.1",
"html-webpack-plugin": "^5.3.1",
"style-loader": "^3.3.1",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.1"
},
"dependencies": {
"@apollo/client": "^3.5.6",
"@apollo/link-context": "^2.0.0-beta.3",
"@apollo/react-hooks": "^4.0.0",
"@auth0/auth0-react": "^1.8.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link-http": "^1.5.17",
"bootstrap": "^5.0.1",
"clean-webpack-plugin": "^4.0.0",
"dayjs": "^1.10.5",
"npm-force-resolutions": "^0.0.10",
"prop-types": "^15.8.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.1",
"regenerator-runtime": "^0.13.9",
"svg-url-loader": "^7.1.1",
"terser-webpack-plugin": "^5.3.0",
"webpack-merge": "^5.8.0"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"description": "",
"resolutions": {
"react": "17.0.2",
"graphql": "16.1.0"
}
}
控制台错误指向该索引bundle.js:2 代码:
错误是指我项目中的这个反应组件:
import React, { useEffect } from "react";
import { useMutation } from "@apollo/client";
import { NEW_SESSION, newSessionVariables } from "../../graphql/newSession.js";
import { GET_TOTAL_SESSIONS_TODAY } from "../../graphql/getSessions";
import dayjs from "dayjs";
const sessionCreateDate = dayjs().format("M-D-YYYY");
const TimerAtZero = ({ timerState, toggle, user = { name: "" } }) => {
const [createSession, { data, loading, error }] = useMutation(NEW_SESSION, {
refetchQueries: [
{ query: GET_TOTAL_SESSIONS_TODAY, variables: { sessionCreateDate, userName: user.name } },
],
});
const { endSession } = toggle;
React.useEffect(() => {
if (timerState.seconds === 0 && timerState.minutes === 0) {
endSession();
createSession(newSessionVariables(user.name, timerState));
}
}, [timerState.seconds, timerState.minutes]);
if (loading) return <div>Submitting...</div>;
if (error) return <div>{error.message}</div>;
return null;
};
export default TimerAtZero;
将别名指向节点模块是错误的。只需删除您的 resolve
条目,一切都会 运行 正常。
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ProvidePlugin, web } = require("webpack");
const cleanPlugin = require("clean-webpack-plugin");
module.exports = {
mode: "production",
devtool: "source-map",
entry: ["regenerator-runtime/runtime.js", "./src/index.js"],
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js",
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
exclude: /[\/]node_modules[\/]/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg$/,
use: {
loader: "svg-url-loader",
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
title: "Production",
}),
new ProvidePlugin({
React: "react",
}),
new cleanPlugin.CleanWebpackPlugin(),
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
如果仍然崩溃,请删除 ProvidePlugin
并在受影响的文件中手动导入 React。
首先,不要使用缩小版本来查找错误,它通常以一种没有意义的奇怪方式显示问题。在 webpack 中使用 optimization.minimize = false
可以帮助解决这个问题。
使用webpack时需要注意的一些情况ProvidePlugin
.
您用于 linting、类型检查、分析器等的工具也应该配置为检测全局导入,这在其他配置文件中需要更多的工作和维护。
例如 eslint
你可以这样做:
{
"globals": {
"ReactDOM": true
}
}
如果有一天你选择改变你的捆绑器,那么如果另一个捆绑器不支持像 ProvidePlugin
.
这样的东西,你将很难过
而且新开发人员如果不知道 ProvidePlugin
,一开始可能会感到困惑。但是每个人都知道 import
!
考虑到这些问题,最终取决于您和您的项目是否值得使用ProvidePlugin
。
如果您使用 ProvidePlugin
只是因为每次都输入 import react 很困难,那么您需要在编辑器中使用代码片段。例如,在 VSCode 中有一个 plugin 有这种片段。或者,您可以根据需要创建自己的代码段。
我的 React 应用程序使用 Webpack + Babel。当我在开发中编译时,一切都运行良好。
当我为生产打包(“npm 运行 build”)并在 prod 中上传打包时,控制台中出现错误:
为什么?我发现了一个类似的问题,但没有找到答案:
这是我的 webpack.prod.js
配置:
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ProvidePlugin, web } = require("webpack");
const cleanPlugin = require("clean-webpack-plugin");
module.exports = {
mode: "production",
devtool: "source-map",
entry: ["regenerator-runtime/runtime.js", "./src/index.js"],
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js",
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
exclude: /[\/]node_modules[\/]/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg$/,
use: {
loader: "svg-url-loader",
},
},
],
},
resolve: {
alias: { react: path.resolve("./node_modules/react") },
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
title: "Production",
}),
//no need to import react in every module
new ProvidePlugin({
React: "react",
}),
//erase "dist" bundle before every "npm run build"
new cleanPlugin.CleanWebpackPlugin(),
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
Package.json:
{
"name": "timerfrontend",
"version": "1.0.0",
"main": "index.js",
"babel": {
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack serve --config webpack.config.js",
"create": "webpack -w",
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.16.5",
"@babel/preset-env": "^7.16.5",
"@babel/preset-react": "^7.16.5",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.3.1",
"html-webpack-plugin": "^5.3.1",
"style-loader": "^3.3.1",
"webpack": "^5.65.0",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.7.1"
},
"dependencies": {
"@apollo/client": "^3.5.6",
"@apollo/link-context": "^2.0.0-beta.3",
"@apollo/react-hooks": "^4.0.0",
"@auth0/auth0-react": "^1.8.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link-http": "^1.5.17",
"bootstrap": "^5.0.1",
"clean-webpack-plugin": "^4.0.0",
"dayjs": "^1.10.5",
"npm-force-resolutions": "^0.0.10",
"prop-types": "^15.8.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^6.2.1",
"regenerator-runtime": "^0.13.9",
"svg-url-loader": "^7.1.1",
"terser-webpack-plugin": "^5.3.0",
"webpack-merge": "^5.8.0"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"description": "",
"resolutions": {
"react": "17.0.2",
"graphql": "16.1.0"
}
}
控制台错误指向该索引bundle.js:2 代码:
错误是指我项目中的这个反应组件:
import React, { useEffect } from "react";
import { useMutation } from "@apollo/client";
import { NEW_SESSION, newSessionVariables } from "../../graphql/newSession.js";
import { GET_TOTAL_SESSIONS_TODAY } from "../../graphql/getSessions";
import dayjs from "dayjs";
const sessionCreateDate = dayjs().format("M-D-YYYY");
const TimerAtZero = ({ timerState, toggle, user = { name: "" } }) => {
const [createSession, { data, loading, error }] = useMutation(NEW_SESSION, {
refetchQueries: [
{ query: GET_TOTAL_SESSIONS_TODAY, variables: { sessionCreateDate, userName: user.name } },
],
});
const { endSession } = toggle;
React.useEffect(() => {
if (timerState.seconds === 0 && timerState.minutes === 0) {
endSession();
createSession(newSessionVariables(user.name, timerState));
}
}, [timerState.seconds, timerState.minutes]);
if (loading) return <div>Submitting...</div>;
if (error) return <div>{error.message}</div>;
return null;
};
export default TimerAtZero;
将别名指向节点模块是错误的。只需删除您的 resolve
条目,一切都会 运行 正常。
const TerserPlugin = require("terser-webpack-plugin");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { ProvidePlugin, web } = require("webpack");
const cleanPlugin = require("clean-webpack-plugin");
module.exports = {
mode: "production",
devtool: "source-map",
entry: ["regenerator-runtime/runtime.js", "./src/index.js"],
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js",
},
module: {
rules: [
{
test: /\.(jsx|js)$/,
exclude: /[\/]node_modules[\/]/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.svg$/,
use: {
loader: "svg-url-loader",
},
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "src/index.html",
title: "Production",
}),
new ProvidePlugin({
React: "react",
}),
new cleanPlugin.CleanWebpackPlugin(),
],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
如果仍然崩溃,请删除 ProvidePlugin
并在受影响的文件中手动导入 React。
首先,不要使用缩小版本来查找错误,它通常以一种没有意义的奇怪方式显示问题。在 webpack 中使用 optimization.minimize = false
可以帮助解决这个问题。
使用webpack时需要注意的一些情况ProvidePlugin
.
您用于 linting、类型检查、分析器等的工具也应该配置为检测全局导入,这在其他配置文件中需要更多的工作和维护。
例如 eslint
你可以这样做:
{
"globals": {
"ReactDOM": true
}
}
如果有一天你选择改变你的捆绑器,那么如果另一个捆绑器不支持像 ProvidePlugin
.
而且新开发人员如果不知道 ProvidePlugin
,一开始可能会感到困惑。但是每个人都知道 import
!
考虑到这些问题,最终取决于您和您的项目是否值得使用ProvidePlugin
。
如果您使用 ProvidePlugin
只是因为每次都输入 import react 很困难,那么您需要在编辑器中使用代码片段。例如,在 VSCode 中有一个 plugin 有这种片段。或者,您可以根据需要创建自己的代码段。