将我的头发拉出来寻找一个简单解决方案,通过NPM,跨多个Browserify或Webpack捆绑包共享代码。思考,是否存在文件" bridge"?
这样的事情这不是因为编译时间(我知道watchify),而是希望将我所有供应商特定的库提取到vendor.js
,以便保留我的app.js
文件大小下来并且不会使用大量源映射崩溃浏览器。另外,如果需要查看已编译的js,我发现它更清晰。所以:
// vendor.js
require('react');
require('lodash');
require('other-npm-module');
require('another-npm-module');
非常重要的是,代码可以从NPM加载而不是Bower,或保存到某些供应商的代码中。目录,以便通过相对路径导入并通过垫片识别。除了我的实际应用程序源之外,我想通过NPM保留每个库引用。
在app.js
中,我保留了所有源代码,并通过externals
数组,从编译中排除了上面列出的供应商库:
// app.js
var React = require('react');
var _ = require('lodash');
var Component = React.createClass()
// ...
然后在index.html
中,我需要两个文件
// index.html
<script src='vendor.js'></script>
<script src='app.js'></script>
使用Browserify或Webpack,我如何才能使app.js
能够&#34;看到&#34;进入那些通过npm加载的模块?我知道创建一个包含外部的包,然后通过别名引用直接文件(例如,node_modules
),但我希望找到一个更自动且更少的解决方案&#34; Require.js&#34;喜欢。
基本上,我想知道是否可以桥接这两个,以便app.js
可以查看vendor.js
内部以解决依赖关系。这似乎是一个简单,直接的操作,但我似乎无法在这个广泛的网络上找到答案。
谢谢!
答案 0 :(得分:26)
列出所有供应商文件/模块并使用CommonChunkPlugin确实是推荐的方式。这变得非常乏味,而且容易出错。
考虑这些NPM模块:fastclick
和mprogress
。由于他们没有采用CommonJS模块格式,您需要提供webpack,如下所示:
require('imports?define=>false!fastclick')(document.body);
require('mprogress/mprogress.min.css');
var Mprogress = require('mprogress/mprogress.min.js'),
现在假设您的供应商块中需要fastclick
和mprogress
,您可能会尝试这样做:
module.exports = {
entry: {
app: "./app.js",
vendor: ["fastclick", "mprogress", ...]
唉,它不起作用。您需要匹配require()
:的来电
module.exports = {
entry: {
app: "./app.js",
vendor: [
"imports?define=>false!fastclick",
"mprogress/mprogress.min.css",
"mprogress/mprogress.min.js",
...]
即使有一些resolve.alias
诡计,它也会变老。这是我的解决方法。 CommonChunkPlugin允许您指定一个回调,无论您是否希望模块包含在供应商块中,该回调都将返回。如果您自己的源代码位于特定的src
目录中,其余的位于node_modules
目录中,则只需根据其路径拒绝这些模块:
var node_modules_dir = path.join(__dirname, 'node_modules'),
app_dir = path.join(__dirname, 'src');
module.exports = {
entry: {
app: "./app.js",
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(
/* chunkName= */"vendor",
/* filename= */"vendor.bundle.js"
function (module, count) {
return module.resource && module.resource.indexOf(app_dir) === -1;
}
)
]
};
其中module.resource
是正在考虑的模块的路径。您也可以执行相反的操作,如果模块位于node_modules_dir
内,则仅包含该模块,即:
return module.resource && module.resource.indexOf(node_modules_dir) === 0;
但在我的情况下,我宁愿说:&#34; 将不在源代码树中的所有内容放入供应商块中&#34;。
希望有所帮助。
答案 1 :(得分:11)
使用webpack,您可以使用多个入口点和CommonChunkPlugin。
取自webpack docs:
要将您的应用分成两个文件,例如app.js
和vendor.js
,您可以要求vendor.js
中的供应商文件。然后将此名称传递给CommonChunkPlugin,如下所示。
module.exports = {
entry: {
app: "./app.js",
vendor: ["jquery", "underscore", ...],
},
output: {
filename: "bundle.js"
},
plugins: [
new webpack.optimize.CommonsChunkPlugin(
/* chunkName= */"vendor",
/* filename= */"vendor.bundle.js"
)
]
};
这将从app chunk中删除供应商块中的所有模块。 bundle.js
现在只包含您的应用代码,而不包含任何依赖项。这些都在vendor.bundle.js
。
在您的HTML页面中vendor.bundle.js
之前加载bundle.js
。
<script src="vendor.bundle.js"></script>
<script src="bundle.js"></script>
答案 2 :(得分:0)
// vendor anything coming from node_modules
minChunks: module => /node_modules/.test(module.resource)
来源:https://github.com/webpack/webpack/issues/2372#issuecomment-213149173