我的团队正在切换到 webpack,我遇到了需要帮助的问题。
我不知道为什么,但 webpack 似乎没有公开每个文件外部的依赖关系。不幸的是,这打破了我们用于抽象表渲染逻辑的模式。
foo.renderers.DefaultCellRenderer
class DefaultCellRenderer
renderCell: (data) ->
... render logic goes here ...
foo.renderers.ComplexCellRenderer
class ComplexCellRenderer
renderCell: (data) ->
... render logic goes here ...
foo.mixins.SimpleTableMixin
require foo.mixins.BaseTableMixin
class SimpleTableMixin
constructor: (@data) ->
foo.mixins.BaseTableMixin.apply @
@columns = [
{ label: 'Col 1' }
{ label: 'Col 2' }
]
foo.mixins.ComplexTableMixin
require foo.mixins.BaseTableMixin
require foo.renderers.ComplexCellRenderer
class ComplexTableMixin
constructor: (@data) ->
foo.mixins.BaseTableMixin.apply @
@columns = [
{ label: 'Col 1' }
{ label: 'Col 2', renderer: 'ComplexCellRenderer' }
]
foo.mixins.BaseTableMixin
require foo.renderers.DefaultCellRenderer
class BaseTableMixin
render: (container) =>
# render table header...
# render table body...
for row in @data
for metadata, cellIndex in @columns
name = metadata.renderer or 'DefaultCellRenderer'
target = foo.renderers[name]
container.append target.renderCell row[cellIndex]
这是一个极其简化的示例,但本质上,这种方法允许我们构建非常复杂的表,其行为层可在运行时动态配置。
在实现 webpack 之前,这种方法是有效的,因为“foo.renderers”是全局的,任何需要自定义渲染的类都负责声明该依赖关系,保证其在被基本 .render() 函数调用时存在......
但是,自从迁移到 webpack 后,除非我在基表混合中明确要求,否则这些渲染器不再可用。这打破了这种方法的根本好处,即使我们的表可扩展而无需修改底层逻辑。
此外,我无法直接在列数组中传递渲染器引用,因为应用程序状态需要可序列化为 JSON,以便可以随意脱水/再水化。
考虑到所有这些,谁能告诉我是否有一种方法可以确保这些依赖项在基表混合中可用,而不必在该文件中显式声明它们(从而打破打开/关闭原则) ?
谢谢!
更新 因此,根据下面 dtothefp 的答案,我最终创建了一个包装类,它动态地需要同一目录或子目录中的所有渲染器...所以我只需要需要一个引用而不是单个引用(尽管,它们可以单独需要)同样,以避免循环引用)
/foo/common/renderers/Renderers.coffee
goog.provide 'foo.common.renderers'
context = require.context './', true, /^.+\.js$/
context.keys().forEach (key) ->
renderers = context(key)?.foo?.common?.renderers
_.extend foo.common.renderers, renderers if renderers?
return
最佳答案
尝试使用 expose-loader
https://github.com/webpack-contrib/expose-loader
module: {
rules: [{
test: path.join(yourSrcRoot, 'foo', 'renderers', 'DefaultCellRenderer'),
use: [{
loader: 'expose-loader',
options: 'foo.renderers.DefaultCellRenderer' // not sure if this works???
}]
}]
}
似乎尝试从您之前拥有的任何内容转移到在命名空间上使用全局变量的 Webpack 是一种反模式,但这可能会让您开始。
或者更好的是,为什么不在包的开头引导整个事情呢?
// index.js
const foos = require.context('./foo', true, /(renderers|mixins)\/.+\.js$/);
global.foo = {};
global.foo.mixins = {};
global.foo.renderers = {};
foos.keys().forEach((fp) => {
const [dir] = fp.split('/');
global.foo[dir] = foos(fp);
});
不确定您所说的“这破坏了这种方法的根本好处,即使我们的表可扩展而无需修改底层逻辑”是什么意思。如果您想使用模块加载器但不想导入依赖项,那么您似乎错过了重点。
关于javascript - WebPack:如何访问单独的类/文件中所需的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43666686/