无法从 webpack 资产库模块解析 css url

Can't resolve css url from webpack asset librarymodule

我能够输出一个资产库和许多其他库,这些库作为远程联合模块和深度导入库工作,以防我没有连接到远程或者我没有在消费者端使用 webpack。

现在的问题是我的所有资产都导出一个模块,该模块要么将原始数据作为 uri,要么将字符串指向正确的资产。例如:bird.svg 输出到 dust 及其哈希加上解析为文件 bird-[hash].svg.

的模块

以上内容在 javascript 中非常棒,但在 css 中就没那么好了。现在我无法重写 url() 以指向正确的远程路径,就像 sg:

//since I don't know when the assets will change names I can't refer to it directly. So I would need to first read the string from the bird.js module. Append the publicPath and then rewrite the url. 
.someClass {
  background-image: url('/assets/bird.js')
} 
//the above won't work for obvious reasons. 

所以,问题是我该如何解决这个问题?或者有没有装载机?我检查了 resolve url 加载程序,但它似乎不是所需要的。

好的,我通过将附加数据作为变量传递给 sass-loader 解决了这个问题。这样我就可以评估文件的实际名称,并将其作为 sass 映射之前并从 sass.

处理它
//I am using glob to return an object with all the assets.
//This can probably be automated better. That would be an easier way.
//But this way works for me in all 3 scenarios, node, browser and federated module.
//Also has caching ootb for the assets.
const assetsPaths = {
  ...glob.sync('../assets/dist/img/**.node.js').reduce(function (obj, el) {
    obj['img/' + path.parse(el).name] = '../../assets/dist/' + require(el).default;
    return obj
  }, {}), ...glob.sync('../assets/dist/fonts/**.node.js').reduce(function (obj, el) {
    obj['fonts/' + path.parse(el).name] = '../../assets/dist/' + require(el).default;
    return obj
  }, {})
};
//...
{
  loader: 'sass-loader',
  options: {
    additionalData: "$assets: '" + assetsMap + "';",
    sourceMap: true,
    sassOptions: {
      outputStyle: "compressed",
    },
  }
},
//...

您还需要禁用url重写

{
  loader: 'css-loader',
  options: {
    url: false,
  }
},

然后您可以在 sass 文件中使用资产地图:

@font-face { 
  font-family: 'Some Font';
  src: local('Some Font');
  src: url("#{map-get($assets, SomeFont)}");
}

您可能需要将您的项目设置排序为单声道存储库,并且您还需要使用两个包构建这些资产库。

一个用于节点,因此您可以在捆绑时使用实际资产的字符串路径 sass/whatever。 另一个用于正常从浏览器加载它。

更新:

我没有做所有这些,而是​​使用从 'webpack-manifest-plugin' 生成的清单来构建要在 sass.

中使用的 $assets 映射
const assetsManifest = JSON.parse(fs.readFileSync('../assets/dist/manifest.json'));

const assetsMapFn = asset => `'${asset[0]}':'${asset[1]}'`;
  const assetsMap = `(
    ${Object.entries(assetsManifest).map(assetsMapFn).join(',')}
  ); `;

如果有人知道更好的方法,请回复或评论。