如何在多个 Webpack 包中共享 jQuery 的同一个实例?
How to share the same instance of jQuery across multiple Webpack packs?
我正在开发一个 Rails 应用程序,从 Sprockets 迁移到 Webpack。我们当前的 JavaScript 依赖于全局分配给 window
的库。为了迁移过来,我想保持全局分配,直到我们在以后解决它。我想在不进行任何 JavaScript 更改的情况下从 Sprockets 切换到 Webpack。
我们有几个 JavaScript 捆绑包,它们已被手动拆分以提高性能:
core.js
,其中包含 jQuery 和其他几个文件。这是一个阻塞包。
vendor.js
,其中包含所有其他库和 jQuery 插件。这是一个延迟捆绑包。
application.js
,其中包含我们的自定义应用程序代码。也是一个延迟包。
所有捆绑包都依赖于 jQuery,application.js
依赖于 vendor.js
。这对 Sprockets 没问题,但对 Webpack 来说是个问题。
如何在 core.js
中保留 jQuery,但在 Webpack 中将其从 vendor.js
和 application.js
中排除? 或另一种提问方式是 How do I share the same instance of jQuery across multiple webpack bundles? 我需要使用相同的实例因为 application.js
依赖 jQuery 在 vendor.js
中定义的插件
我的配置文件包括 expose-loader
和 ProvidePlugin
,但它们在捆绑包本身中包括 jQuery,这不是同一个实例。换句话说,我多次捆绑 jQuery(用 splitChunks()
修复),但我不能保证我使用的是哪个实例,因此不能保证插件可用.
// Webpacker environment.js config
const { environment } = require('@rails/webpacker');
const path = require('path');
const webpack = require('webpack');
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: 'jQuery'
},
{
loader: 'expose-loader',
options: '$'
}
]
});
environment.plugins.append(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
);
module.exports = environment;
不确定这是否可行,但也许您可以尝试:
# vendor.js
import JQuery from 'jquery'
window.$ = window.JQuery = JQuery
// rest of vendor.js code
#application.js
import './vendor.js'
//rest of application.js code
虽然我还没有解决方案,但我发现将 jQuery
设置为外部库似乎会强制使用一个全局实例。
// Webpacker environment.js config
const { environment } = require('@rails/webpacker');
const path = require('path');
const webpack = require('webpack');
environment.config.set('externals', {
$: 'jquery',
jquery: 'jQuery'
});
module.exports = environment;
我已经能够通过使用我的 Sprockets core.js
包和 Webpack 来测试这一点。一切都按预期工作。
我已经发布了一个后续问题来尝试有条件地设置外部组件并为所有内容使用 Webpack:Conditionally set externals for a specific Webpack bundle
我已经成功地 splitChunks
强制 jquery combined 的单个实例与 expose-loader 像你描述的那样配置。
这是我正在使用的 Webpack 配置的关键部分:
environment.splitChunks((config) => {
return Object.assign({}, config, {
optimization: {
splitChunks: {
chunks: 'all',
name: true,
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/,
priority: -10,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
})
})
这里的关键是了解 Webpack splitChunks 取代了手动代码拆分的需要。换句话说,无需显式创建 core.js
和 vendor.js
包;将所有导入合并为 application.js
依赖关系树的一部分。 让 Webpack 为您进行代码拆分。
另一个需要注意的是,Webpacker 的 splitChunks
实现意味着在视图中放置一个 javascript_packs_with_chunks_tag
,这样共享的“运行时”块将确保模块,如 jQuery , 不重复。
在我之前使用 Sprockets 的项目中,我曾经像您一样手动拆分我的包。当我不得不自己迁移到 Webpack 时,我花了一段时间才适应这种新方法。我做了一个关于它的演讲,这将使我在这里的回答更加清晰:https://youtu.be/fKOq5_2qj54?t=185
在我的案例中唯一有效的两个选项是:
1) 像这样将 jquery 添加到外部:
module.exports = {
...
externals: {
'jquery': 'jQuery'
},
};
将一个脚本标签放在一个文件中,你可以在任何地方包含它(在我的例子中是 base.html.twig,其他一切都从这个扩展)。
<script src="/path/to/jquery/jquery-2.2.3.min.js"></script>
2) 使用 ProvidePlugin + runtimeChunk: single:
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
"window.jQuery": 'jquery',
"window.$": 'jquery',
})
],
optimization: {
runtimeChunk: 'single',
}
}
runtimeChunk single 将生成一个新文件,您必须将其包含在随处包含的页面中(基本上,无论您有入口点,都包含此运行时块!)
我正在开发一个 Rails 应用程序,从 Sprockets 迁移到 Webpack。我们当前的 JavaScript 依赖于全局分配给 window
的库。为了迁移过来,我想保持全局分配,直到我们在以后解决它。我想在不进行任何 JavaScript 更改的情况下从 Sprockets 切换到 Webpack。
我们有几个 JavaScript 捆绑包,它们已被手动拆分以提高性能:
core.js
,其中包含 jQuery 和其他几个文件。这是一个阻塞包。vendor.js
,其中包含所有其他库和 jQuery 插件。这是一个延迟捆绑包。application.js
,其中包含我们的自定义应用程序代码。也是一个延迟包。
所有捆绑包都依赖于 jQuery,application.js
依赖于 vendor.js
。这对 Sprockets 没问题,但对 Webpack 来说是个问题。
如何在 core.js
中保留 jQuery,但在 Webpack 中将其从 vendor.js
和 application.js
中排除? 或另一种提问方式是 How do I share the same instance of jQuery across multiple webpack bundles? 我需要使用相同的实例因为 application.js
依赖 jQuery 在 vendor.js
我的配置文件包括 expose-loader
和 ProvidePlugin
,但它们在捆绑包本身中包括 jQuery,这不是同一个实例。换句话说,我多次捆绑 jQuery(用 splitChunks()
修复),但我不能保证我使用的是哪个实例,因此不能保证插件可用.
// Webpacker environment.js config
const { environment } = require('@rails/webpacker');
const path = require('path');
const webpack = require('webpack');
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
options: 'jQuery'
},
{
loader: 'expose-loader',
options: '$'
}
]
});
environment.plugins.append(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
);
module.exports = environment;
不确定这是否可行,但也许您可以尝试:
# vendor.js
import JQuery from 'jquery'
window.$ = window.JQuery = JQuery
// rest of vendor.js code
#application.js
import './vendor.js'
//rest of application.js code
虽然我还没有解决方案,但我发现将 jQuery
设置为外部库似乎会强制使用一个全局实例。
// Webpacker environment.js config
const { environment } = require('@rails/webpacker');
const path = require('path');
const webpack = require('webpack');
environment.config.set('externals', {
$: 'jquery',
jquery: 'jQuery'
});
module.exports = environment;
我已经能够通过使用我的 Sprockets core.js
包和 Webpack 来测试这一点。一切都按预期工作。
我已经发布了一个后续问题来尝试有条件地设置外部组件并为所有内容使用 Webpack:Conditionally set externals for a specific Webpack bundle
我已经成功地 splitChunks
强制 jquery combined 的单个实例与 expose-loader 像你描述的那样配置。
这是我正在使用的 Webpack 配置的关键部分:
environment.splitChunks((config) => {
return Object.assign({}, config, {
optimization: {
splitChunks: {
chunks: 'all',
name: true,
cacheGroups: {
vendors: {
test: /[\/]node_modules[\/]/,
priority: -10,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
})
})
这里的关键是了解 Webpack splitChunks 取代了手动代码拆分的需要。换句话说,无需显式创建 core.js
和 vendor.js
包;将所有导入合并为 application.js
依赖关系树的一部分。 让 Webpack 为您进行代码拆分。
另一个需要注意的是,Webpacker 的 splitChunks
实现意味着在视图中放置一个 javascript_packs_with_chunks_tag
,这样共享的“运行时”块将确保模块,如 jQuery , 不重复。
在我之前使用 Sprockets 的项目中,我曾经像您一样手动拆分我的包。当我不得不自己迁移到 Webpack 时,我花了一段时间才适应这种新方法。我做了一个关于它的演讲,这将使我在这里的回答更加清晰:https://youtu.be/fKOq5_2qj54?t=185
在我的案例中唯一有效的两个选项是:
1) 像这样将 jquery 添加到外部:
module.exports = {
...
externals: {
'jquery': 'jQuery'
},
};
将一个脚本标签放在一个文件中,你可以在任何地方包含它(在我的例子中是 base.html.twig,其他一切都从这个扩展)。
<script src="/path/to/jquery/jquery-2.2.3.min.js"></script>
2) 使用 ProvidePlugin + runtimeChunk: single:
module.exports = {
...
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
"window.jQuery": 'jquery',
"window.$": 'jquery',
})
],
optimization: {
runtimeChunk: 'single',
}
}
runtimeChunk single 将生成一个新文件,您必须将其包含在随处包含的页面中(基本上,无论您有入口点,都包含此运行时块!)