将 svg-url-loader 与 Create React App 结合使用
Using svg-url-loader with Create React App
我正在使用 Create React App,我想将我的 SVG 内嵌作为数据 URI。
我知道 CRA 允许我将 SVG 作为组件导入和渲染,la:
import { ReactComponent as Logo } from './logo.svg';
// <Logo />
而且我知道我可以获得 SVG 的 URL:
import Logo from './logo.svg';
// <img src={Logo} />
但我想做的是将 SVG 的内容嵌入为数据 URI,如:
<img src="data:image/svg+xml;utf8,<svg>...</svg>">
我知道svg-url-loader can do this. So I set it up (using Rescripts,因为CRA限制修改Webpack配置):
function addSvgLoader(config) {
config.module.rules.push({
test: /\.svg/,
use: {
loader: "svg-url-loader",
options: {
limit: 15000,
},
},
});
return config;
}
module.exports = [addSvgLoader];
有了这个,理论上,我应该能够使用上面的第二个示例,而不是获取指纹 URL,而是获取内联数据 URI。然而,指纹 URL 仍然被渲染,SVG 文件的内容现在看起来像这样:
module.exports = "data:image/svg+xml,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 24V0h24v24H0zM ... [truncated] ... 03h-.52l-.23.02z'/%3E%3C/svg%3E"
我怀疑这是CRA的加载器之间的冲突svg-url-loader
,但我一直没能找到解决办法。如果有 svg-url-loader
的替代方案,我也会考虑。
Webpack 规则在使用 import
语法时使用 test
glob 作为规则来处理包含文件。由于规则不必相互排斥,多个规则可以轻松处理相同的 test
标准。
在您的示例中,听起来像是预先存在的 svgs CRA 规则 和 您的 svg-url-loader
规则正在处理导入的 SVG;顺序由您的 Webpack 配置在运行时分配的方式决定。
试试这样的东西:
- 在文件名中使用可识别的名字创建 SVG 的变体(例如
my-image.data-uri.svg
)
配置 svg-url-loader
插件以激活 *.data-uri.svg
glob 模式
{
test: /\.data-uri.svg/,
use: {
loader: 'svg-url-loader',
options: {
encoding: 'base64'
},
},
},
这里的文件名真的很像 intent
并且规则将在构建时通过自定义插件路由这些案例。
备注
如果在现代 CRA 之外尝试这样做,旧的静态编译策略建议在 require 语句中指定导入意图:
require('svg-url-loader?encoding=base64!./file.svg');
这通常已被删除,以支持静态映射,因此需要使用 glob 测试来激活您的特殊插件案例。
这确实是 CRA 的 svg 加载程序与您尝试使用的加载程序之间的冲突。但是,webpack规则可以有一个oneOf
section, which will apply only the first matching rule - and CRA's svg rule is in it(我的版本是3.4.1
)。
此外,规则的顺序很重要,您的规则应该在 CRA 定义的规则之前。
考虑到这两点,我像这样修改了 webpack 配置:
let oneOfRule = config.module.rules.find((r) => r.oneOf);
oneOfRule.oneOf.splice(0, 0, {
test: /\.svg$/,
use: ['svg-url-loader'],
});
我用 svg-sprite-loader 而不是 svg-url-loader 测试了这个,但一般原理保持不变,它应该可以工作。
我正在使用 Create React App,我想将我的 SVG 内嵌作为数据 URI。
我知道 CRA 允许我将 SVG 作为组件导入和渲染,la:
import { ReactComponent as Logo } from './logo.svg';
// <Logo />
而且我知道我可以获得 SVG 的 URL:
import Logo from './logo.svg';
// <img src={Logo} />
但我想做的是将 SVG 的内容嵌入为数据 URI,如:
<img src="data:image/svg+xml;utf8,<svg>...</svg>">
我知道svg-url-loader can do this. So I set it up (using Rescripts,因为CRA限制修改Webpack配置):
function addSvgLoader(config) {
config.module.rules.push({
test: /\.svg/,
use: {
loader: "svg-url-loader",
options: {
limit: 15000,
},
},
});
return config;
}
module.exports = [addSvgLoader];
有了这个,理论上,我应该能够使用上面的第二个示例,而不是获取指纹 URL,而是获取内联数据 URI。然而,指纹 URL 仍然被渲染,SVG 文件的内容现在看起来像这样:
module.exports = "data:image/svg+xml,%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 24V0h24v24H0zM ... [truncated] ... 03h-.52l-.23.02z'/%3E%3C/svg%3E"
我怀疑这是CRA的加载器之间的冲突svg-url-loader
,但我一直没能找到解决办法。如果有 svg-url-loader
的替代方案,我也会考虑。
Webpack 规则在使用 import
语法时使用 test
glob 作为规则来处理包含文件。由于规则不必相互排斥,多个规则可以轻松处理相同的 test
标准。
在您的示例中,听起来像是预先存在的 svgs CRA 规则 和 您的 svg-url-loader
规则正在处理导入的 SVG;顺序由您的 Webpack 配置在运行时分配的方式决定。
试试这样的东西:
- 在文件名中使用可识别的名字创建 SVG 的变体(例如
my-image.data-uri.svg
) 配置
svg-url-loader
插件以激活*.data-uri.svg
glob 模式{ test: /\.data-uri.svg/, use: { loader: 'svg-url-loader', options: { encoding: 'base64' }, }, },
这里的文件名真的很像 intent
并且规则将在构建时通过自定义插件路由这些案例。
备注
如果在现代 CRA 之外尝试这样做,旧的静态编译策略建议在 require 语句中指定导入意图:
require('svg-url-loader?encoding=base64!./file.svg');
这通常已被删除,以支持静态映射,因此需要使用 glob 测试来激活您的特殊插件案例。
这确实是 CRA 的 svg 加载程序与您尝试使用的加载程序之间的冲突。但是,webpack规则可以有一个oneOf
section, which will apply only the first matching rule - and CRA's svg rule is in it(我的版本是3.4.1
)。
此外,规则的顺序很重要,您的规则应该在 CRA 定义的规则之前。
考虑到这两点,我像这样修改了 webpack 配置:
let oneOfRule = config.module.rules.find((r) => r.oneOf);
oneOfRule.oneOf.splice(0, 0, {
test: /\.svg$/,
use: ['svg-url-loader'],
});
我用 svg-sprite-loader 而不是 svg-url-loader 测试了这个,但一般原理保持不变,它应该可以工作。