Webpack 和外部库:ProvidePlugin vs entry vs global import?
Posted
技术标签:
【中文标题】Webpack 和外部库:ProvidePlugin vs entry vs global import?【英文标题】:Webpack and External Libs: ProvidePlugin vs entry vs global import? 【发布时间】:2017-02-14 18:00:22 【问题描述】:1。 ProvidePlugin()
看起来是一种常用的方法。有一个关于它的gist,展示了如何将 whatwg-fetch polyfill 包含到 Webpack 构建中。 *** 上的很多答案都使用它here 和here。
new webpack.ProvidePlugin(
'$': 'jquery',
'jQuery': 'jquery',
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
)
????优点
有效。 (如果我遗漏了什么,请更新此列表)????缺点
需要跟踪 Webpack 配置中的全局库。2。 entry: [...]
当我在this gist 中发现这种方法时,我有点惊讶,但它同样有效。
entry: [
'babel-polyfill',
'whatwg-fetch',
'jquery',
'webpack-hot-middleware/client',
path.join(process.cwd(), 'app/app.js')
],
????优点
有效。 我可以完全放弃ProvidePlugin()
。
????缺点
需要跟踪 Webpack 配置中的全局库。3。***import
这个很简单,看这个app.js 例子。该文件是 React 应用程序的入口点。
/**
* app.js
*/
import 'whatwg-fetch';
import 'babel-polyfill';
import 'jquery';
????优点
同样有效。 轻松添加/删除。无需修改 Webpack 配置。????缺点
看起来这种方法不能单独用于 jQuery 插件,例如bootstrap.js.观察:在所有三种方法中,我没有注意到包大小有任何变化。
有没有一种推荐的使用 Webpack(和 React)处理全局库的方法?这些解决方案中的任何一个都会导致服务器端渲染出现问题吗?
谢谢!
【问题讨论】:
如果您有多个入口点,entry
根本不是一个好主意。
【参考方案1】:
我不建议将库公开为全局库,除非您确实需要它,即模块系统的重点是显式声明依赖关系,例如
// app.js
import $ from 'jquery';
$.ajax(...);
如果您在全局上确实需要 jQuery,因为第三方脚本在您的页面上需要它,或者可能用于在控制台中进行调试,那么这里有一些关于您列出的方法的信息:
提供插件
ProvidePlugin 不会在全局上公开 jQuery,并且真正旨在修复错误地依赖全局模块的存在的第三方模块,因此我不建议这样做,例如
// app.js
$.ajax(...);
被有效地转译成:
// app.js
require('jquery').ajax(...);
入口和***导入
这些方法不适用于常规的 UMD 模块,例如 jQuery,因为 jQuery 足够聪明,不会在由 commonjs / amd / es6 感知加载器加载时将自身暴露在全局上。
然而,这两种方法非常适合具有副作用的模块,例如 babel-polyfill
/ whatwg-fetch
,因为它们不会导出任何内容,它们会固有地改变全局环境。
因此,我对 jQuery 的建议是使用 expose-loader
,它旨在全局公开模块导出,例如
// webpack.config.js
module:
loaders: [
test: require.resolve('jquery'),
loader: 'expose-loader?jQuery!expose-loader?$'
]
你仍然需要在你的应用代码中导入它:
// app.js
import $ from 'jquery';
$.ajax(...)
但如果绝对必要,它可以在全局上供页面上的其他脚本访问:
// console
window.$
window.jQuery
注意:从技术上讲,您可以在使用暴露加载器时在入口点中只 import 'jquery'
一次,然后在其他模块中依赖全局。
不过,正如我所说,如果您不需要公开一个模块,即使您当前碰巧在其他所有模块中使用它,也不建议公开它。
【讨论】:
【参考方案2】:如果您在使用ProvidePlugin 时在一页中包含多个包(入口点),只需发现提供的lib 将被覆盖。例如 RoR 和 Webpacker,但我认为这并不重要。
例如,您的布局中有:
javascript_pack_tag 'application',
'metronic'
在配置中你有:
environment.plugins.append('Provide', new webpack.ProvidePlugin(
$: 'jquery',
jQuery: 'jquery',
"window.jQuery": "jquery",
"window.$": "jquery",
_: 'underscore',
Handlebars: 'handlebars'
));
如果在application.js
中你需要库,它会改变 JQuery,你将在metronic.js
和浏览器中失去所有这些突变,即使你使用暴露加载器公开 JQuery。
如果我错了,请纠正我,ProvidePlugin 可能只是在每个入口点导入库。
【讨论】:
以上是关于Webpack 和外部库:ProvidePlugin vs entry vs global import?的主要内容,如果未能解决你的问题,请参考以下文章
使用 React Router 和 Webpack 2 如何仅在某些路由上需要外部库?