前言最近在公司的一个项目中使用了Webpack5。但是在使用npm包时,出现了Bufferisnotdefined的问题。原因很明显,因为浏览器运行时没有BufferAPI,所以需要为浏览器引入BufferPolyfill。Webpack项目下使用NodeJS包的Webpack5应该很常见。为什么我以前没有遇到过这个问题。因为是Webpack5之前的版本,Webpack会自动为我们引入NodeJSAPIPolyfill。但是在Webpack5之后,官方认为自动引入Polyfill会导致bundlesize过大,而大多数情况下这些自动引入的Polyfill并没有被使用。所以Webpack5需要我们手动引入Polyfill来配置Webpack5安装BufferPolyfill。我们需要先安装一个兼容浏览器环境的Buffer实现。这里使用npm包npminstall-Dbuffer来配置FallbackWebpackresolve.fallback来指定当我们的目标构建环境中不存在相应的包时,将使用fallback的值作为回退。这里使用安装好的buffer包作为fallback{resolve:{fallback:{buffer:require.resolve('buffer/'),},},}这里使用'buffer/',可以明确的告诉NodeJS模块去查询算法,使用buffernpm包而不是NodeJS自带的buffer模块来配置ProvidePluginWebpackProvidePlugin可以注入一个模块或者值作为全局变量。我们可以不用import/require直接使用注入的全局变量{plugins:[newwebpack.ProvidePlugin({Buffer:['buffer','Buffer'],//['packagename','valueinthepackage']})]}上面的配置等同于constBuffer=require('buffer').Buffer;完成配置{resolve:{fallback:{buffer:require.resolve('buffer/'),},},plugins:[newwebpack.ProvidePlugin({Buffer:['buffer','Buffer'],})]}package.jsonbrowserfield经过上面的配置,一般情况下可以解决Bufferisnotdefined的问题。但是我用的公司内的某个npm包报了一个新问题Cannotreadpropertiesofundefined(reading'allocUnsafe'),其他依赖buffer的包都正常。经查,与该包的package.json浏览器字段有关。//package.json{"browser":{"buffer":false}}根据非npm官方规范(https://github.com/defunctzombie/package-browser-field-spec),浏览器可以有三个主要领域替代。npm官方文档中描述的用途,值为string类型,用于指定浏览器环境的包入口“browser”:“./browser/specific/main.js”,而不是指定的文件。左边是你需要替换的模块或文件名,右边是替换项"browser":{"module-a":"./shims/module-a.js","./server/only.js":"./shims/client-only.js"}忽略模块。设置false可以防止模块或文件被打包成packages"browser":{"module-a":false}上面的配置会导致a未定义consta=require('module-a');解决方法也很简单,让包的维护者删除package.json中的browser字段即可。至此所有错误都解决了,可以愉快的使用BufferAPI了。结论Webpack5不再自动为我们引入NodeJSPolyfill。我们可以安装兼容浏览器环境的npm包,然后通过配置resolve.fallback和providePlugin插件手动导入;如果配置完成后,部分包还是有问题,可以尝试查看对应包中的package.json浏览器字段
