使用Webpack编译React应用时出现模块解析失败问题求助
Webpack编译TypeScript React应用时的ModuleNotFoundError问题
我用Webpack编译TypeScript构建React应用,执行npm run server时触发ModuleNotFoundError,无法解析loginfile.js、logoutfile.js等文件。试过在HTML里用../loginfile.js、./loginfile.js、loginfile.ts等多种引入路径,都没用。
为排查问题,我在src/test目录下新建了test.ts和test.html,test.html中引入test.js的代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=Edge" /> <script type="text/javascript" defer src="test.js"></script> </head> <body> </body> </html>
同样报错:
ModuleNotFoundError: Module not found: Error: Can't resolve './test.js' in '/Users/*****/****/summarizr2/summarizr/src/test'
按预期编译后的test.js应该在dist目录中可找到。以下是我的webpack配置、项目结构信息:
webpack.config.js配置
module.exports = async (env, options) => { const dev = options.mode === "development"; const config = { devtool: "source-map", entry: { polyfill: ["core-js/stable", "regenerator-runtime/runtime"], vendor: ["react", "react-dom", "core-js", "@fluentui/react"], taskpane: ["react-hot-loader/patch", "./src/taskpane/index.tsx", "./src/taskpane/taskpane.html"], commands: "./src/commands/commands.ts", loginfile: "./src/login/loginfile.ts", logoutfile: "./src/logout/logoutfile.ts", }, output: { clean: true, }, resolve: { extensions: [".ts", ".tsx", ".html", ".js"], }, module: { rules: [ { test: /\.css$/i, include: path.resolve(__dirname, 'src'), use: ['style-loader', 'css-loader', 'postcss-loader'], }, { test: /\.ts$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { presets: ["@babel/preset-typescript"], }, }, }, { test: /\.tsx?$/, exclude: /node_modules/, use: ["react-hot-loader/webpack", "ts-loader"], }, { test: /\.html$/, exclude: /node_modules/, use: "html-loader", }, { test: /\.(png|jpg|jpeg|gif|ico)$/, type: "asset/resource", generator: { filename: "assets/[name][ext][query]", }, }, ], }, plugins: [ new DotenvWebpackPlugin({ path: `.env.${options.mode}` }), new CopyWebpackPlugin({ patterns: [ { from: "assets/*", to: "assets/[name][ext][query]", }, { from: "manifest*.json", to: "[name]" + "[ext]", transform(content) { if (dev) { return content; } else { return content.toString().replace(new RegExp(urlDev, "g"), urlProd); } }, }, ], }), new HtmlWebpackPlugin({ filename: "taskpane.html", template: "./src/taskpane/taskpane.html", chunks: ["taskpane", "vendor", "polyfills"], }), new HtmlWebpackPlugin({ filename: "loginfile.html", template: "./src/login/loginfile.html", chunks: ["loginfile"], }), new HtmlWebpackPlugin({ filename: "logoutfile.html", template: "./src/logout/logoutfile.html", chunks: ["logoutfile"], }), new HtmlWebpackPlugin({ filename: "endlogout.html", template: "./src/taskpane/endlogout.html", chunks: ["login", "vendor", "polyfills"], }), new HtmlWebpackPlugin({ filename: "commands.html", template: "./src/commands/commands.html", chunks: ["commands"], }), new webpack.ProvidePlugin({ Promise: ["es6-promise", "Promise"], }), ], devServer: { hot: true, headers: { "Access-Control-Allow-Origin": "*", }, server: { type: "https", options: env.WEBPACK_BUILD || options.https !== undefined ? options.https : await getHttpsOptions(), }, port: process.env.npm_package_config_dev_server_port || 3000, }, }; return config; };
项目结构
├ src │ ├ commands │ │ ├ commands.html │ │ ├ commands.ts │ ├ constants │ │ ├ authentication.ts │ ├ login │ │ ├ loginfile.html │ │ ├ loginfile.ts │ ├ logout │ │ ├ logoutfile.html │ │ ├ logoutfile.ts │ ├ services │ │ ├ commands │ │ ├ common │ ├ taskpane │ │ ├ components │ │ ├ endlogout.html │ │ ├ index.css │ │ ├ index.tsx │ │ ├ login.html │ │ ├ logoutcomplete │ │ ├ taskpane.html │ │ ├ urls.ts ├ tailwind.config.js ├ tsconfig.json └ webpack.config.js
问题原因及解决方法
1. 手动引入JS与Webpack构建逻辑冲突
你在HTML模板中用<script>手动引入JS文件的方式,和Webpack的运行逻辑完全矛盾:
- 开发模式下,Webpack Dev Server是内存编译,不会把文件输出到磁盘的dist目录,你手动引用的路径根本找不到实际文件;
- 即使是生产模式,Webpack编译后的chunk文件名可能带有hash(若配置了),手动写的固定文件名也会失效;
test.ts没有加入Webpack的entry配置,Webpack根本不会去编译它,自然不存在对应的test.js。
2. 利用HtmlWebpackPlugin自动注入Chunk
你已经在使用HtmlWebpackPlugin,完全不需要手动写<script>标签,插件会自动把对应chunk注入到HTML中:
- 对于
test.html,需要在webpack配置中新增entry和对应的插件实例:
// 在entry中添加 test: "./src/test/test.ts", // 在plugins数组中添加 new HtmlWebpackPlugin({ filename: "test.html", template: "./src/test/test.html", chunks: ["test"], }),
然后删除test.html中手动写的<script src="test.js"></script>。
- 对于已有的
loginfile.html、logoutfile.html,检查模板中是否存在手动引入loginfile.js/logoutfile.js的<script>标签,必须删除——因为你已经通过chunks: ["loginfile"]配置让插件自动注入了,手动引入会导致Webpack解析不存在的路径。
3. 其他需要修正的配置点
- 完善
output配置:明确指定输出路径和文件名,避免路径歧义:
output: { clean: true, filename: "[name].js", path: path.resolve(__dirname, "dist"), },
- 修正
endlogout.html的插件配置:chunks: ["login", ...]中的login不存在于entry中,应该改为loginfile; - 确保
resolve.extensions中.ts在.js前面,让Webpack优先解析TypeScript文件。
内容的提问来源于stack exchange,提问作者infodev
相关产品推荐
相关产品推荐

