它让我失望,在我的通用JavaScript应用程序中,我通过webpack DLL plugin提取了DLL库,但我必须在默认导出(供浏览器使用)或commonjs
之间进行选择(供我使用)节点)。
在所有数千行供应商代码中,字面上两个出口之间的唯一区别是第一行:
- module.exports =
+ var vendor =
我的快递应用只允许我require
module.exports
变种,因为它需要commonjs
个模块,而我的浏览器不知道该做什么,除非得到var vendor
变种。
我不想99.999999 ...%相同文件的相同副本。
本能地,这感觉很疯狂:我认为两个环境都应该能够使用相同的DLL库,因为它们之间的应用程序代码是相同的。
所以我一直在集思广益,我想出了以下几种可能性:
我找不到中间两点或实现替代方法的实现细节是不成功的。我正在寻找超越“只需要两份副本并继续生活”的答案。如果您知道如何处理中间两点,我很乐意向您提供实施细节。如果你有想法或方法我没有在这里列出,我全都听见了!
答案 0 :(得分:0)
因此,当我发布我的问题时,我发现正确的Google搜索会引导我this solution。我在一小时前从未听说过vm模块,但它似乎提供了我正在寻找的内容。
使用var NAME =
为浏览器构建DLL(这是默认行为)。然后,在服务器上,使用vm.runInNewContext
评估磁盘中的文件,并返回新的上下文,其中的键将与您的DLL中的var
语句匹配。最后,只需将这些键分配给global.NAME
和boom:服务器理解文件。
这是我的代码(当前)的样子:
const vm = require('vm');
const fs = require('fs');
// from a custom webpack plugin I wrote, where keys are the name of the chunk
// and the value is a relative filepath to that chunk
const chunks = require('path/to/my/chunks.json');
if (!chunks.js.serverDLL || !chunks.js.appDLL) {
throw new Error('Chunks could not be loaded!!');
}
const dllContext = ((pathMap, context = {}) => {
Object.keys(pathMap).forEach((key) => {
vm.runInNewContext(fs.readFileSync(pathMap[key]), context, pathMap[key]);
});
return context;
})({ serverDLL: `.${chunks.js.serverDLL}`, appDLL: `.${chunks.js.appDLL}` });
global.serverDLL = dllContext.serverDLL;
global.appDLL = dllContext.appDLL;
上面还有改进的余地,因为我可能会使用HOC函数迭代我的块输入而不是硬编码键。此外,我的publicPath
设置为/
,但传递到我的vm.runInNewContext
的路径需要是相对文件路径。由于我只在生产中进行此操作(不是开发),因此我的构建目录是扁平的(对于这些文件无论如何),因此我预先添加.
,将客户端URL路由转换为适当的相对文件路径。另外,这是我第一次使用vm
,所以我相信有人会指出我可以更好地完成上述工作的方法。 :d
答案 1 :(得分:0)
听起来这个文件开头和结尾的变化可能有效:
// start of file
try {
module.exports;
} catch (err) {
var module = {};
}
var vendor = // ... the duplicated code
// end of file
module.exports = vendor;
我确信nodejs和浏览器一般都可以通过这种方式获取正确的值,但我自己并没有使用带有webpack的DLL库,所以如果不适合这种情况,我会提前道歉。为了以防万一,我以为我会把它扔出去。