Comments (26)
Hi everyone! I've run into a similar issue, however I didn't want to webpack my entire backend so I came up with a kinda hacky solution.
I was already using ignore-styles as I import relevant stylesheets into my react components, so in order to generate the correct server side markup I just needed to add the following to my bootstrapping file:
const path = require('path');
const crypto = require('crypto');
require('ignore-styles').default(['.scss', '.css', '.svg'], (module, filename) => {
const base = path.basename(filename);
if (base.indexOf('.svg') > 0) {
module.exports = '#' + crypto.createHash('md5').update(filename).digest("hex");
}
});
Note this works with the following webpack config:
{
...
module: {
loaders: [
{
test: /\.svg$/,
loader: 'svg-sprite?' + JSON.stringify({
name: '[pathhash]',
prefixize: true
})
}
]
},
...
}
I hope this helps somebody! 😃
from svg-sprite-loader.
Shouldn't something like SSR live in the default sprite impl? The very least it should do on a node environment it just return the symbol id (without using document
) instead of failing.
from svg-sprite-loader.
I believe for SSR, we need a node require hook that will generate the correct ID for a given path, then it should all work fine since the sprite will be loaded client-side.
I would give it a go, but I'm first trying to get a sprite generated at all.
from svg-sprite-loader.
Thing is I'm using a server side rendered Application, which is why this loader is failing when going through the app initialization. In the meantime, I managed to make it work by only requiring the plugin if typeof window !== 'undefined'
, it's a temporal fix, but works, so will be looking forward to the alpha version next week :)
Thanks for taking the time to look out my problem here 👍
from svg-sprite-loader.
@oliverox you can implement your own sprite behaviour via spriteModule
option. Something like this:
webpack.config.js
...
module: {
loaders: [
{
test: /\.svg/,
// define path to custom sprite module
loader: 'svg-sprite?spriteModule=' + path.resolve(__dirname, 'server-side-rendering-sprite-module.js')
}
]
}
server-side-rendering-sprite-module.js
// simple sprite implementation which renders into string
function Sprite() {
this.symbols = [];
}
Sprite.prototype.add = function(image) {
this.symbols.push(image);
};
Sprite.styles = ['position:absolute', 'width:0', 'height:0', 'visibility:hidden'];
Sprite.prototype.render = function() {
return [
'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="'+ Sprite.styles.join(';') +'">',
'<defs>',
this.symbols.join(''),
'</defs>',
'</svg>'
].join('');
};
module.exports = new Sprite();
my-app.js
require('./image.svg');
var sprite = require('./server-side-rendering-sprite-module');
var renderedSprite = sprite.render();
console.log(renderedSprite);
from svg-sprite-loader.
@oliverox does it helped?
from svg-sprite-loader.
@kisenka Thanks for the help in the right direction. I have not had enough time to implement it yet as I've been moving over the new year. Will try it soon. Thanks again.
from svg-sprite-loader.
@kisenka I stumbled upon same problem. Could you please elaborate on process of implementing the server-sider rendering module for React app?
My node app generates sprite and inlines it into html (this works well):
app.use((req, res, next) => {
const html = renderToString(
<Root />
);
let renderedSprite = Root.sprite;
res.send(template({ html, env, renderedSprite }));
});
and my components looks like this
import svg_aws from './img/aws.svg';
class Icon extends React.Component {
render() {
let { glyph } = this.props;
return (
<svg
className="icon"
width="81px"
height="81px"
dangerouslySetInnerHTML={{__html: '<use xlink:href="' + glyph + '"></use>'}}
/>
)
}
}
<Icon glyph={svg_react} />
The problem is that when webpack compiles it (with target: node
) the svg_aws
is undefined
. So to my understanding the problem boils down to getting the sprite xlink:href
at compile time. Any thoughts on this?
from svg-sprite-loader.
Well.. i came up with crappy solution actually:
const sprite = require('../../utils/svg-server-rendering.js');
...
let ids = sprite.symbols.map(i => {
return i.match(/id="(.*?)"/g)
});
let arr = ids.map(j => j[0].replace('id=', '#').replace(/\"/g, ""))
arr.map(el => <Icon glyph={el} />)
Pretty sure that it is not only ugly, but also wrong somewhere 😐
UPD:
aaaand it does not work on webpack dev server
from svg-sprite-loader.
import svg_aws from './img/aws.svg';
<Icon glyph={svg_react} />
svg_aws
svg_react
Maybe wrong var reference?
from svg-sprite-loader.
No, i map all of them and they all undefined
when render on server. Also initial version based on docs worked perfectly on development server (without SSR).
from svg-sprite-loader.
@olegakbarov sorry, I am vacation till 21 March so I can't help you now
from svg-sprite-loader.
No problem, i'll write up if got some results on this.
from svg-sprite-loader.
Also struggling with server-side rendering. Initially, the error I got was a type error because React is undefined. Found out that it seems it's the babel-loader
trying to do its job (there is no webpack when running with node -r babel-register
). I then tried to just get the correct id generated by node, assuming the sprite would already be setup thanks to the webpack build, but I don't get any svg file in my build output anyway and I'm now very confused.
from svg-sprite-loader.
Sorry for delay. I am working on it
from svg-sprite-loader.
@kisenka do you still intend to work on this?
from svg-sprite-loader.
I've created the testcase https://github.com/kisenka/svg-sprite-loader-ssr-testcase for server-side rendering.
- Fork it.
- npm install
- npm run sprite-test
You will see that output from sprite loader which contains the whole sprite.
You can add your testcases in you forks and tell me.
from svg-sprite-loader.
@danilobuerger you're right. Sprite loader firstly created for in browser usage, so it works with browser environment out of the box. I think it will be good if sprite loader will use environment specific sprite implementation which depends on target
webpack config option. Thoughts?
from svg-sprite-loader.
Hmm, so what we need to consider is client-only and server+client (render server side, pick up on client side) and server-only setups. Probably need to also consider outputing to a svg file (see #23).
Overall it might make more sense splitting this up in multiple loaders. One that returns symbol ids (or external ref + symbol ids) and builds the svg map. Another loader to include that svg map either as file or load it in dom or output it in some other way.
client-only
If inline, return symbol id on require. Include svg map in dom, updateable (?).
If file, return external ref + symbol id on require. Chunk svg map, maybe extractable with extract-text-webpack-plugin
.
server-only
If inline, return symbol id on require. Output svg map so it can be rendered.
If file, return external ref + symbol id on require. Chunk svg map, maybe extractable with extract-text-webpack-plugin
.
client+server
If inline, return symbol id on require. Output svg map so it can be rendered. Client should not include svg map in dom as its already present. Maybe it can updated it instead like react-helmet
does for example.
If file, return external ref + symbol id on require. Chunk svg map, maybe extractable with extract-text-webpack-plugin
. Client should not include svg map in dom.
from svg-sprite-loader.
Just as a heads-up, for my project, I switched to making a webpack bundle for the server as well (as per this article: http://jlongster.com/Backend-Apps-with-Webpack--Part-I) to avoid needing duplicate logic for every loader that node should know about.
from svg-sprite-loader.
I can confirm that the approach provided by @kisenka in #19 (comment) works for me.
I had to make the webpack config for the ?spriteModule=server-side-rendering-sprite-module
conditional on the prerender build, and then in my app I just needed to import the server-side-rendering-sprite-module module and put the result of sprite.render()
in the outgoing HTML.
However, I think that the approach outlined in #45 will be more efficient and easier to set up.
from svg-sprite-loader.
Confirming @hyatt03's solution works well! Thanks for sharing.
from svg-sprite-loader.
Hello!!
Are there any updates on this? (as I see this to be a feature for 2.0).
Also, could you, given you have the chance, point me in the right direction to use with React? Though I did check the example, I can't really see how to implement it with React.
Thanks in advance!
from svg-sprite-loader.
@lrojas94 work in progress, I planning to release alpha version on the next week.
Also, could you, given you have the chance, point me in the right direction to use with React?
Do you have concrete question about loader with React?
from svg-sprite-loader.
@oliverox
@olegakbarov
@qur2
@danilobuerger
@hyatt03
@wmertens
@elado
@lrojas94
Hey guys [email protected] with server side rendering is on the way, please read about it here #91 and take part in discussion/voting. Thanks!
from svg-sprite-loader.
Check 2.0.1 release
from svg-sprite-loader.
Related Issues (20)
- Webpack 5 cache=filesystem HOT 2
- Performance consumption HOT 1
- del
- NPM recommending svg-sprite-loader 2.0.3 as a vulnerability fix?
- Exception emitted for every svg
- How can I add new attributes to the parent SVG?
- Is there a way to set role, focusable and other attributes to root svg sprite tag without extracting?
- Regular Expression Denial of Service in postcss (6.0.11) HOT 2
- Unable to modify spriteFilename if loader rule has resourceQuery while using SpriteLoaderPlugin HOT 1
- SvgSpriteLoader is trying to guess you are using webpack 4 or 5 HOT 1
- Node16 npm audit moderate HOT 1
- SVG created is blank HOT 1
- The plugin doesn-t see rules if config in oneOf HOT 2
- Abnormal width and height
- Dependency on loader-utils 1.1.0 is security concern, CRITICAL vulnerabilities
- Module Warning (from ./node_modules/svg-sprite-loader/lib/loader.js): svg-sprite-loader exception. Some loaders will be applied after svg-sprite-loader in extract mode
- sprite.svg load every time when change showing icon HOT 1
- svg-sprite-loader not working well with encore webpack
- Webpack deprecation warning
- Esbuild alternative HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from svg-sprite-loader.