Snap.svg
Snap.svg copied to clipboard
Snap.svg on Node.js
Hi! I'm asking because I found no documentation about this topic. Is it possible to use Snap.svg with Node.js? Did someone succeeded making it work server side?
Thanks in advance for your answers
On its own, not without modification. Node.js' require system is modeled after the CommonJS spec and there is issue #447 for it. Support would be awesome.
If you happen to be using webpack, or don't mind utilizing it, it has an imports-loader module that can help shim in CommonJS compatibility for the time being. The approach is detailed in #341.
To be clear webpack obviously is meant for the web but it's output targets are configurable and at the time of this writing contain options for: node-compatible CJS output, node-compatible asynchronous loading via fs/vm node modules, a webkit variant of the node output (for nw.js) and an electron variant of the node output.
I recently posted the answer in SO about running Snap.svg in Node.js with jsdom.
In short:
const jsdom = require('jsdom');
const xmlserializer = require('xmlserializer');
jsdom.env('', ['node_modules/snapsvg/dist/snap.svg.js'], (error, window) => {
if (error) throw error;
const paper = window.Snap(100, 100);
const rect = paper.rect(20, 20, 60, 60);
rect.attr({fill: 'red'});
const svg = xmlserializer.serializeToString(paper.node);
window.close();
console.log(svg);
});
It can be solved with this loader config (seen in #341):
{
test: require.resolve('snapsvg'),
loader: 'imports-loader?this=>window,fix=>module.exports=0'
}
Did anyone manage to have it run well with node.js? Any best practices (or alternatives for *.svg processing in node.js)?
@roadev I arrive here without knowing what "loader" is. Can you give a more fleshed out example of your solution based on #341 that is specific to node?
@sparr See #483. It’s for working with webpack, which is a preferred way of bundling & managing JS for front-end code (it also allows you to use NPM for easy version management).
Here's a way of doing it in typescript without any special bundler, just a refresh of @hakatashi's method. Note I have the "dom" in my "lib" array for the compiler to handle the types/jsdom .d.ts files.
const dom = new jsdom.JSDOM(
'<script src="node_modules/snapsvg/dist/snap.svg.js"/>',
{
runScripts: "dangerously",
resources: "usable"
}
);
const window = dom.window as typeof dom.window & {
Snap: typeof snap;
};
// have to be sure the snap module is loaded before proceeding
await ((async () => {
while (!window.Snap) {
await bluebird.delay(100);
}
})());
const height = 800;
const width = 600;
const surface = window.Snap(height, width);
// start drawing
// surface.circle(150, 150, 100);
const rect = surface.rect(10, 10, 200, 125, 10, 10);
//serialize
xmlserializer.serializeToString(surface.node)
@Sammons that’s awesome. Could you submit a PR that adds that to the README? That seems useful for others.
but jsdom does not have implemented getBBox https://github.com/jsdom/jsdom/issues/918
jsdom is on version 16 now.
anyone have an updated template to get this running with latest version of JSDOM?