JSFiddle - React, Tailwind, and code Playground

HTML

<script type="x-shader/x-vertex" id="vertexShader">

			attribute vec3 center;
			varying vec3 vCenter;

			void main() {

				vCenter = center;

				gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

			}

</script>

<script type="x-shader/x-fragment" id="fragmentShader">

			uniform float widthFactor;

			varying vec3 vCenter;

			float edgeFactorTri() {

				vec3 d = fwidth( vCenter.xyz );

				vec3 a3 = smoothstep( vec3( 0.0 ), d * widthFactor, vCenter.xyz );

				return min( min( a3.x, a3.y ), a3.z );

			}

			void main() {

				if ( edgeFactorTri() > 0.99 ) discard;

				gl_FragColor = gl_FrontFacing ? vec4( 0.9, 0.9, 1.0, 1.0 ) : vec4( 0.4, 0.4, 0.5, 1.0 );

			}

</script>

CSS

body {
	  margin: 0;
}

JavaScript

import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.126.1/build/three.module.js';

let renderer, scene, camera, mesh1, mesh2;

init();

function init() {

	renderer = new THREE.WebGLRenderer( { antialias: true } );
	renderer.setPixelRatio( window.devicePixelRatio );
	renderer.setSize( window.innerWidth, window.innerHeight );
	document.body.appendChild( renderer.domElement );

	scene = new THREE.Scene();

	camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 500 );
	camera.position.z = 150;

	new THREE.BufferGeometryLoader().load( 'https://threejs.org/examples/models/json/WaltHeadLo_buffergeometry.json', function ( geometry ) {

		// on the left

		const material1 = new THREE.MeshBasicMaterial( {

			color: 0xe0e0ff,
			wireframe: true

		} );

		mesh1 = new THREE.Mesh( geometry, material1 );
		mesh1.position.set( - 40, 0, 0 );

		scene.add( mesh1 );

		// on the right

		const uniforms = { 'widthFactor': { value: 1 } };

		const material2 = new THREE.ShaderMaterial( {

			uniforms: uniforms,
			vertexShader: document.getElementById( 'vertexShader' ).textContent,
			fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
			side: THREE.DoubleSide

		} );

		geometry.deleteAttribute( 'normal' );
		geometry.deleteAttribute( 'uv' );

		setupAttributes( geometry );

		mesh2 = new THREE.Mesh( geometry, material2 );
		mesh2.position.set( 40, 0, 0 );

		scene.add( mesh2 );

		//

		animate();

	} );

	window.addEventListener( 'resize', onWindowResize );

}

function setupAttributes( geometry ) {

	const vectors = [
		new THREE.Vector3( 1, 0, 0 ),
		new THREE.Vector3( 0, 1, 0 ),
		new THREE.Vector3( 0, 0, 1 )
	];

	const position = geometry.attributes.position;
	const centers = new Float32Array( position.count * 3 );

	for ( let i = 0, l = position.count; i < l; i ++ ) {

		vectors[ i % 3 ].toArray( centers, i * 3 );

	}

	geometry.setAttribute( 'center', new THREE.BufferAttribute( centers, 3 ) );

}

function...