自定义React组件库非Node环境script引入报global未定义如何解决
问题解决方法
错误原因
- Webpack配置中
target设置为node:该配置会让Webpack按照Node.js环境的规则编译代码,默认使用Node环境的全局变量global,浏览器环境不存在该变量,因此抛出global is not defined错误 - 使用
nodeExternals外置所有node_modules依赖:编译后的代码不会包含依赖模块,浏览器环境没有内置的模块导入能力,依赖缺失导致代码执行中断,自然无法完成Components对象的挂载 - 手动挂载全局对象的操作冗余:配置UMD规范后Webpack会自动处理全局对象的挂载,不需要手动操作
具体修改方案
1. 调整Webpack配置
修改核心配置项如下:
module.exports = merge(commonConfig , { entry: resolve(__dirname, './', 'index.ts'), mode: 'production', // 替换node为universal,同时适配Node和浏览器环境 target: 'universal', node: { // 兼容global变量,浏览器环境自动映射为window global: true, __dirname: false, __filename: false }, output: { filename: '[name].js', chunkFilename: '[name].js', libraryTarget: 'umd', library: 'Components', // 适配不同环境的全局对象,Node中是global,浏览器中是window globalObject: 'this', umdNamedDefine: true }, optimization: { minimizer: [ new TerserPlugin({ parallel: true, cache: true, }), ], // 浏览器端使用的UMD产物建议关闭代码分割,打出单文件方便引入 splitChunks: false }, // 移除nodeExternals,如果要外置React等公共依赖,可以按如下配置,要求使用方提前引入对应资源 // externals: { // 'react': 'React', // 'react-dom': 'ReactDOM' // }, plugins: [ new CleanWebpackPlugin(), new DtsBundleWebpack({ name: "components", main: resolve(__dirname, './', 'index.d.ts'), out: resolve(__dirname, './', 'dist/main.d.ts'), }) ], });
2. 调整入口文件代码
移除手动挂载window的冗余代码即可:
export { default as Button } from './src/components/Button/Button';
3. 多产物兼容方案(可选)
如果需要同时支持Node/打包工具引入和浏览器script引入,可以配置Webpack多实例编译,分别输出两类产物:
- 给Node/打包工具的CJS/ESM产物:保留
target: 'node'和nodeExternals配置,不需要打包公共依赖,减小产物体积 - 给浏览器的UMD产物:使用上述修改后的配置,要么打包所有依赖,要么外置React等公共依赖
验证方式
编译后在HTML中按如下方式引入即可使用:
<!-- 如果你外置了React,需要先引入对应资源 --> <script src="你的React资源路径"></script> <script src="你的ReactDOM资源路径"></script> <!-- 引入你的组件库 --> <script src="./dist/main.js"></script> <script> // 直接从全局取Components使用 const { Button } = window.Components; </script>
内容的提问来源于stack exchange,提问作者Giedrius
相关产品推荐
相关产品推荐

