dxf-viewer: rendering large CAD drawings in the browser with WebGL
DXF 2D viewer written in JavaScript
At a glance
- What is it?
- dxf-viewer is a JavaScript component that renders DXF drawings through three.js, built to handle huge real world files, with geometry batching and instanced rendering to keep the draw call count down, worker offload for parsing, lazy font loading and layer awareness. Its readme is unusually frank about the long list of DXF features it does not yet support.
- Who is it for?
- Adopt dxf-viewer if you need to display DXF drawings in a browser and your files are large enough that a naive renderer would stutter, since the batching and instancing work targets exactly that. Do not adopt it if your drawings rely on line patterns, variable line widths, paper space layouts or non-UTF-8 encodings, because each of those is on the not-yet-implemented list.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the component is, and who it is for
The package provides a DXF 2D viewer component written in JavaScript, and it renders drawings using WebGL through the three.js library.
The important word in that description is huge. The readme says the component was carefully crafted with performance in mind, intended for drawing huge real-world files without performance problems. That is the entire design brief, and it explains the technical choices in a way the feature list alone does not.
Real-world CAD files are a specific kind of unpleasant. A single drawing can contain hundreds of thousands of entities, and the naive way to render it, one mesh and one draw call per entity, produces a scene that a GPU cannot handle. A viewer aimed at that regime has to attack the draw call count, and that is what the batching and instancing work is for.
There is also a browser-first framing. If you just need to view your DXF, the readme points at a hosted example page, and the usage example source and a deployed demo are both linked. The demo is the point of a library like this, because the question a buyer has is not how the API looks but what the rendering actually looks like on a real drawing.
It installs from npm with a single command:
npm install dxf-viewerThe licence is MPL-2.0, the author is Artyom Lebedev, and the recent releases are v1.0.50 from 2026-10-17, v1.0.49 from 2026-09-20 and v1.0.48 from 2026-06-08, with the last push on 2026-10-17.
One detail in the readme is worth noting for anyone filing a bug. There is a release preview deployment running the current development code, ahead of the latest npm release, and the readme recommends opening it before reporting a rendering problem, since the fix may already be in there. It is unreleased work by definition, so expect the occasional rough edge, and no npm version corresponds to it, while the revision it was built from is shown in its toolbar, which you should quote in a report.
How it keeps the draw call count down
Two features carry the performance claim, and both are about how much work the GPU is asked to do.
Geometry batching means a minimal number of rendering batches is created during file processing, thus minimizing the total required number of draw calls. The batching happens at preparation time, when the file is turned into renderable geometry, and the grouping decision is made there rather than at draw time. That matters because the grouping is only possible while you still know which entities share a style, and once you are drawing you do not.
Instanced rendering covers features which are rendered multiple times with different transforms, with DXF block instances given as the example. Rather than emitting one copy of a bolt or a symbol for every place it appears, instanced rendering draws the whole set with a single draw call. A drawing with a thousand instances of the same detail becomes one call instead of a thousand, which is the difference between a smooth pan and a slideshow on a large file.
Then there is the point about the pipeline shape. File fetching, parsing and preparation for rendering is separated in such a way that it can be easily off-loaded to a web worker using the provided helpers, so the most heavy-weight processing part does not affect UI responsiveness, and the example demonstrates the technique.
That separation is a design decision with a lasting effect. A viewer that parses on the main thread will stutter on any file big enough to be interesting, and no amount of batching will fix it, because the stall happens before a single triangle is drawn. Moving the parse to a worker is what makes the rest of the optimisation visible to the user.
Layers are also taken into account when creating rendering batches, so they can be easily hidden and shown, which means toggling a layer does not require rebuilding the scene.
Text, fonts and the glyph fallback problem
Text is where DXF viewers usually fall short, and the readme describes the approach and its limits.
Multiple fonts are supported and a list of fonts can be specified for text rendering, with raw TTF files supported directly. The loading strategy is lazy. Once a character is encountered whose glyph is not yet available through the already loaded fonts, the next font is fetched and checked for the necessary glyph.
That is a sensible design for a CAD viewer, because a drawing can reference several fonts and a realistic one may not reference a font that is available on the viewing machine. Fetching fonts lazily and checking them in order means the common case, where the first font covers most of the text, does not pay for the others.
But the text styling story stops there, and the readme is explicit about it. Text rendering currently uses just the specified fonts in the specified order, DXF style and font attributes are ignored, and text glyphs are always rendered infilled. In other words, if a drawing draws a title in a specific colour or weight defined by its style, that is not honoured.
MTEXT, the richer text entity, is partially supported with a similar caveat. Advanced formatting support for MTEXT is listed as incomplete, with fonts and text height not handled. Stacked text is rendered, but the height codes around it are not, so its size is the AutoCAD default rather than the one the drawing asks for. Colour is honoured per paragraph rather than per span, which means a run of coloured words inside a paragraph loses the individual colours.
The paragraph properties are worse. MTEXT paragraph properties other than alignment are incomplete. Alignment, the q argument of a \p code, is honoured wherever it appears in the argument list, but the indents, the line spacing and the tab stops are parsed over and ignored. The readme gives the consequence precisely: a tabulator advances to the next default stop, at a multiple of four times the character height, rather than to a stop the paragraph names.
The dependency list explains the mechanism. opentype.js is there for the font parsing and the glyph handling, and three.js at 0.186.0 is the renderer, with earcut for polygon triangulation, loglevel for the logging and @types/three for the types.
The list of what does not work yet
The incomplete features section is the most useful part of the readme for an adopter, and it is long and specific.
The readme says there are still many incomplete features, that the author will try to implement some when there is time, and that the most significant reason for missing implementation is the lack of corresponding sample files. That last point is worth sitting with, because it means the gaps are not oversights in a design but places where nobody had a file to test against.
The largest single gap is stream parsing for the input file. The readme explains that the project relies mostly on the dxf-parser package, which is not a stream parser and therefore buffers the whole file before parsing, and that this prevents supporting big DXF files above a gigabyte because of the string size limit in the JavaScript engine, while also making unnecessary memory waste for the buffer.
Line work is the other large cluster. Line patterns are not implemented at all, with all lines rendered in continuous style for now, and the readme describes the intended approach, a one dimensional texture generated at the preparation stage, texture coordinates that account for the pattern continuity flag in the DXF vertex attributes, and a dedicated shader. Line patterns with shapes, such as with circles, are also missing. Wide lines are all rendered as thin lines because physical width is not implemented, and variable width lines with a start and end width specified are missing too. Smoothed polylines, where curve fit or spline fit vertices would be added, are not done.
Hatching is partial, with outer hatching style, solid and gradient infill, MPolygon support, double lines and boundaries defined by external entities all missing. Block instancing in a grid ignores the grid attributes.
Dimension rendering is limited in ways that matter for a drawing. The dimension-specific features and styles are incomplete, including text positioning tuning and limits and tolerances, and the dimension types other than linear ones are not handled. Of the arrowhead blocks a dimension style may name, only ticks, oblique strokes and none are drawn, and any other one falls back to the default closed filled arrow, because the named block is not instantiated. Leaders are listed as missing entirely.
Finally there are the format level gaps. Non-UTF-8 file encoding is not supported and such files are displayed incorrectly, with the $DWGCODEPAGE parameter ignored, and MIF encoded characters are decoded except for the Johab code page, which the browser cannot decode. Full OCS support is absent, meaning arbitrary extrusion directions and elevations, with the exception of a block reference with a tilted extrusion direction whose block contains geometry outside of its XY plane. Paper space, layouts and viewports are not supported at all, and the last line is many less commonly used DXF features.
Working with the DXF standard, and the test tooling
The readme has a section on the DXF standard itself, and it is a short lesson in why a viewer like this takes a long time to be complete.
The DXF format is poorly documented by Autodesk. The official documentation primarily covers high-level generic concepts, while many critical low-level details are omitted. The readme's hypothesis is that Autodesk internally relies on its proprietary DWG format implementation, on which DXF is largely based, so the libredwg project can serve as a useful reference in some cases. As a result, determining correct rendering behavior, especially in edge cases, can be challenging.
That is the structural reason for the incomplete features list. This is not a spec-driven implementation where a feature list exists and can be checked off. The authority on what a DXF file should look like when rendered is the behaviour of other applications, and the readme names the sources the author relies on. The Autodesk online viewer is the primary reference, although it occasionally fails to open certain DXF files. The Ezdxf project is acknowledged for its documentation of DXF rendering behaviour, and user reports describing how various CAD applications handle rendering in practice are cited as another source.
The test tooling in the repository is built around that problem. The scripts in the package manifest show a test suite run with the Node test runner over the test directory, a smoke test, a documentation check, a type check, an SVG rendering script with a raised memory limit, and a query tool that runs through uv, plus an index tool that runs a Python script directly.
The Python side is for the tests, not for the package, and the pyproject says so in a comment. The test fixtures are generated by a script, and ezdxf and fonttools are pinned to exact versions, with the reason given: the fixtures are committed and CI checks that regenerating them changes nothing, so a different version of either would fail that check rather than quietly produce different files.
The API documentation is generated too, from the source comments with jsdoc, so it follows the code rather than drifting from it.
Editorial conclusion
Adopt dxf-viewer if you need to display DXF drawings in a browser and your files are large enough that a naive renderer would stutter, since the batching and instancing work targets exactly that. Do not adopt it if your drawings rely on line patterns, variable line widths, paper space layouts or non-UTF-8 encodings, because each of those is on the not-yet-implemented list. Before you commit, open the release preview build with one of your own files, since the readme notes the fix for a rendering problem may already be in the unreleased code, and check the file size against the gigabyte limit the streaming parser gap imposes.
Frequently asked questions
What is dxf-viewer?
It is a DXF 2D viewer component written in JavaScript that renders drawings using WebGL through the three.js library. It was built with performance in mind, intended for drawing huge real-world files without performance problems, and it is published on npm as dxf-viewer under the MPL-2.0 licence.
How does dxf-viewer handle large drawings?
Through geometry batching, which creates a minimal number of rendering batches and so minimizes the total number of draw calls, instanced rendering, which draws features repeated with different transforms such as DXF block instances in a single draw call, and a pipeline where fetching, parsing and preparation are separated so the heavy part can be off-loaded to a web worker and does not affect UI responsiveness.
Which DXF features does dxf-viewer not support yet?
The list includes line patterns, wide and variable width lines, smoothed polylines, several hatching features, block instancing in a grid, most dimension-specific features and all dimension types other than linear, leaders, non-UTF-8 file encodings, full OCS support, and paper space, layouts and viewports. The most significant missing item is stream parsing, which prevents supporting files above a gigabyte.
How does dxf-viewer handle fonts and text?
A list of fonts can be specified and raw TTF files are supported, with fonts lazy-loaded so that a character whose glyph is missing from the already loaded fonts causes the next font to be fetched and checked. DXF style and font attributes are ignored, glyphs are always rendered infilled, and MTEXT height codes and paragraph properties other than alignment are parsed but not applied.
How is dxf-viewer tested and how is its API documented?
The test suite runs with the Node test runner, alongside a smoke test, a documentation check, a type check and a memory-heavy SVG rendering script. The test fixtures are generated with a Python tool that depends on pinned ezdxf and fonttools versions, and the API documentation is generated from the source comments with jsdoc so it follows the code.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/vagran-dxf-viewer)Was this useful?