React+Webpack+Babel构建中排除Modernizr及增强构建控制求助
React项目中Modernizr的来源、排除方法及构建控制优化
问题描述
我使用React、Webpack与Babel技术栈构建React项目,需要优化构建产物的资源加载逻辑。发现Modernizr被包含在react-dom.production.min.js的代码块中,希望了解:
- Modernizr的引入来源
- 如何排除它
- 如何增强对构建子元素的控制能力
项目依赖
"dependencies": { "react": "^18.2.0", "react-dom": "^18.2.0" }, "devDependencies": { "@babel/preset-react": "^7.18.6", "babel-loader": "^9.1.0", "css-loader": "^6.7.2", "file-loader": "^6.2.0", "html-webpack-plugin": "^5.5.0", "http-server": "^14.1.1", "style-loader": "^3.3.1", "webpack": "^5.75.0", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.11.1" }
Webpack配置
const HtmlPack = require('html-webpack-plugin') const HtmlList = [ "index", "test/secondpage" ] module.exports = { // entry: { main: [ "./src/index.js", ], test: [ "./src/test/secondpage.js", ], }, entry: HtmlList.reduce( (config, page) => { config[page] = `./src/${page}.js`; return config; },{}), output: { path: __dirname+'/public/reactor', filename: '[name].bundle.js', clean: true }, devServer: { static: __dirname+'/src', port: 8080, open: true, hot: true }, optimization: { minimize: false, // minimizer: [new TerserPlugin({ // extractComments: false, // })], removeAvailableModules: true, // 检测并移除已包含的模块 sideEffects: true, // 检测并跳过模块的无副作用子库加载 runtimeChunk: 'single', // 为所有chunk生成单个runtime文件 removeEmptyChunks: true, // 清理空chunk优化文件体积 splitChunks: { chunks: "all" }, }, module: { rules: [ { test: /\.js$/i, exclude: /node_modules/, use: [ 'babel-loader' ] }, { test: /\.css$/i, exclude: /node_modules/, use: [ 'style-loader', 'css-loader' ] } , { test: /\.(jpe?g|png|gif|webp|svg|ico|zip|json)$/i, exclude: /node_modules/, loader: 'file-loader', options: { name: '[path][name].[ext]' } } ] }, plugins : [].concat( HtmlList.map( page => new HtmlPack({ filename: `${page}.html`, })), ) }
更新说明
更新01:误判致歉
经多次测试发现:"runtimeChunk"会引入未请求的Modernizr及其他代码,原因未知
更新02:Modernizr来自react-dom
查看react-dom.production.min.js代码,发现内部包含Modernizr的自定义构建版本:
/** * @license React * react-dom.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /* Modernizr 3.0.0pre (Custom Build) | MIT */ var aa=__webpack_require__(294),ca=__webpack_require__(840);function p(a){for(var b="https://reactjs.org/docs/error-decoder.html?invariant="+a,c=1;c<arguments.length..... etc
Modernizr 3.0.0pre (Custom Build) | MIT —— 这是怎么回事???
解答
1. Modernizr的引入来源
React DOM内部确实内置了自定义构建的Modernizr 3.0.0pre版本,它的作用是做浏览器特性检测——比如检测浏览器是否支持特定DOM API、CSS特性,为React的渲染逻辑提供兼容性判断依据。这部分代码是React DOM官方打包时整合进去的,并非项目依赖或配置主动引入的第三方包。
2. 如何减少Modernizr的影响
由于Modernizr是React DOM源码的组成部分,无法直接通过Webpack配置完全排除,但可以通过以下方式缩小其体积或移除未使用的代码:
- 使用React DOM的ES模块版本:修改入口文件中React DOM的引入方式,使用ES模块版本让Webpack的Tree Shaking功能尽可能移除未被触发的兼容性检测代码:
// 替换原有引入方式 import { createRoot } from 'react-dom/client'; - 开启深度代码压缩:配置TerserPlugin移除未执行的代码分支,需要先安装
terser-webpack-plugin:npm install terser-webpack-plugin --save-dev,再修改Webpack的optimization配置:optimization: { minimize: true, minimizer: [ new require('terser-webpack-plugin')({ terserOptions: { compress: { drop_unused: true, dead_code: true } } }) ] }
3. 增强构建子元素的控制能力
可以通过以下配置优化Webpack的构建控制精度:
- 精细化拆分第三方依赖:调整SplitChunks配置,将React、React DOM单独打包,避免重复加载:
splitChunks: { chunks: 'all', cacheGroups: { reactVendor: { test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, name: 'vendors-react', priority: 10 }, commonChunks: { minChunks: 2, name: 'common', priority: 5 } } } - 扩展模块处理规则:对React相关的
node_modules文件启用Babel转译,提升Tree Shaking效率:module: { rules: [ { test: /\.js$/i, exclude: /node_modules\/(?!(react|react-dom)\/)/, // 不排除React系列包 use: ['babel-loader'] } ] } - 可视化分析构建产物:安装
webpack-bundle-analyzer插件,直观查看产物构成,精准定位冗余代码:const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; plugins: [ // 保留原有插件 new BundleAnalyzerPlugin() ]
内容的提问来源于stack exchange,提问作者gaxah
相关产品推荐
相关产品推荐

