Webpack Dev Server运行完成后自动删除Bundle文件问题求助
问题:React库中webpack-dev-server热更新时Bundle文件被删除
我正尝试在React库中使用启用热更新(HMR)的webpack-dev-server,核心目标是实现模块热替换。但每次serve运行完成后,Bundle文件似乎都会被删除。
命令行输出
$ clear && npx webpack serve --mode=development <i> [webpack-dev-server] Project is running at: "/tmp/webpack-dev-server.sock" <i> [webpack-dev-server] Content not from webpack is served from '/usr/local/src/foo/View/public' directory asset bundle_ff16b3001589ab53ae37.js 6.39 MiB [emitted] [immutable] (name: main) orphan modules 1010 KiB [orphan] 233 modules runtime modules 28.5 KiB 14 modules cacheable modules 5.65 MiB modules by path ./node_modules/ 5.26 MiB 219 modules modules by path ./src/ 394 KiB modules by path ./src/components/ 389 KiB 90 modules modules by path ./src/lib/ 2.42 KiB modules by path ./src/lib/util/*.ts 778 bytes 2 modules + 2 modules modules by path ./src/*.js 2.72 KiB ./src/export.js 1.06 KiB [built] [code generated] ./src/constants.js 808 bytes [built] [code generated] ./src/helpers.js 899 bytes [built] [code generated] external "React" 42 bytes [built] [code generated] external "ReactDOM" 42 bytes [built] [code generated] webpack 5.90.3 compiled successfully in 8966 ms ... $ ll public total 0
webpack.config.js
const webpack = require('webpack'); const path = require('path'); const fs = require('fs'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const TerserPlugin = require('terser-webpack-plugin'); /** * Path resolver - automatically resolve alias from @folder into ./src/folder * @type {string} */ const srcDir = path.resolve(__dirname, 'src'); const aliases = fs.readdirSync(srcDir) .filter((item) => fs.statSync(path.join(srcDir, item)).isDirectory()) .reduce((acc, item) => { acc[`@${item}`] = path.join(srcDir, item); return acc; }, {}); let config = { entry: path.join(__dirname, 'src/export.js'), watchOptions: { aggregateTimeout: 200, poll: 1000, }, module: { rules: [ { test: [/\.js$/, /\.jsx$/], exclude: [/node_modules/], loader: 'babel-loader' }, { test: [/\.tsx?$/, /\.ts?$/], exclude: [/node_modules/], use: 'ts-loader' }, { test: /\.css$/, exclude: [/node_modules/], loader: 'css-loader' }, { test: /\.scss$/, exclude: [/node_modules/], use: ['style-loader', 'css-loader', 'sass-loader'] }, { test: /\.(png|jpe?g|gif)$/i, exclude: [/node_modules/], type: 'asset/resource' }, { test: /\.svg$/, type: 'asset', use: ['@svgr/webpack'], }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/inline', loader: 'url-loader', } ] }, plugins: [ new webpack.LoaderOptionsPlugin({ options: { globalObject: '(typeof self !== \'undefined\' ? self : this)' } }), new webpack.ProvidePlugin({ process: 'process/browser', }), ], resolve: { fallback: { 'process/browser': require.resolve('process/browser'), }, alias: { ...aliases, '@scss': path.resolve(__dirname, 'src/static/scss'), }, extensions: ['', '.js', '.jsx', '.ts', '.tsx'] }, output: { path: path.join(__dirname, '/public'), library: { name: 'foo', type: 'umd' }, filename: 'bundle_[contenthash].js', clean: true }, externals: { 'react': 'React', 'react-dom': 'ReactDOM' }, }; module.exports = (env, argv) => { if (argv.mode === 'production') { config.optimization = { ...config.optimization, minimizer: [new TerserPlugin({ extractComments: false, })], minimize: true, plugins: [ ...config.plugins, new CleanWebpackPlugin() ] }; } else { config = { ...config, // development by default mode: 'development', devServer: { hot: true, ipc: true, watchFiles: ['./src/**/**'], }, }; } return config; };
解决方案
核心原因
- webpack-dev-server内存存储机制:开发模式下,webpack-dev-server默认将编译后的bundle文件存在内存中,不会写入
public目录,所以磁盘上看不到文件是正常的,服务仍能访问内存中的资源。 - output.clean的全局生效:你在全局output配置中设置了
clean: true,该选项会在编译前清空public目录。即使dev-server不写磁盘,这个清理动作依然会执行,导致目录最终为空。
具体修复步骤
1. 仅在生产模式启用目录清理
把output.clean移到生产模式分支,避免开发阶段清空目录:
// 全局config的output中移除clean: true output: { path: path.join(__dirname, '/public'), library: { name: 'foo', type: 'umd' }, filename: 'bundle_[contenthash].js' // 删除 clean: true }, // 在production分支中添加clean配置 if (argv.mode === 'production') { config.output = { ...config.output, clean: true }; // 其余生产模式配置保持不变 }
2. (可选)让dev-server写入磁盘
如果需要在开发阶段查看磁盘上的bundle文件,可在devServer配置中添加writeToDisk: true:
devServer: { hot: true, ipc: true, watchFiles: ['./src/**/**'], writeToDisk: true // 添加该行 },
注意:开启后会略微降低编译速度,因为需要额外执行磁盘写入操作。
3. 完善React HMR配置(确保热更新生效)
当前仅开启了hot: true,React模块热替换需要额外配置:
- 安装依赖:
npm install -D react-refresh @pmmmwh/react-refresh-webpack-plugin
- 修改webpack配置:
// 顶部引入插件 const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); // 在development分支中更新配置 else { config = { ...config, mode: 'development', devServer: { hot: true, ipc: true, watchFiles: ['./src/**/**'], }, plugins: [ ...config.plugins, new ReactRefreshWebpackPlugin() // 添加热更新插件 ], module: { ...config.module, rules: config.module.rules.map(rule => { // 给babel-loader添加react-refresh预设 if (rule.loader === 'babel-loader') { return { ...rule, options: { presets: ['@babel/preset-react'], plugins: ['react-refresh/babel'] } }; } return rule; }) } }; }
同时确保你的babel配置文件(.babelrc或babel.config.js)包含@babel/preset-react预设。
内容的提问来源于stack exchange,提问作者fiskolin
相关产品推荐
相关产品推荐

