JSFiddle - React, Tailwind, and code Playground

HTML

<script src="http://d3js.org/topojson.v0.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.7.12/xlsx.core.min.js"></script>
<script src="https://cdn.jsdelivr.net/alasql/0.3/alasql.min.js"></script>

CSS

path {
  stroke: white;
  stroke-width: 0.25px;
  fill: grey;
}

JavaScript

var width = 960,
    height = 500;

var projection = d3.geo.mercator()
    .center([0, 5 ])
    .scale(200)
    .rotate([-180,0]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var path = d3.geo.path()
    .projection(projection);

var g = svg.append("g");

// load and display the World
d3.json("https://unpkg.com/[email protected]/world/110m.json", function(error, topology) {

// load and display the cities

    alasql('SELECT * FROM xlsx("https://cdn.rawgit.com/agershun/alasql-org/gh-pages/demo/014map/cities.xlsx",{headers:true})',[], function(data) {
    g.selectAll("text")
       .data(data)
       .enter()
       .append('text')
    .text(function(d){return d.city})
    .attr("x", function(d) {
               return projection([d.lon, d.lat])[0];
       })
    .attr("y", function(d) {
               return projection([d.lon, d.lat])[1];
       })
});


g.selectAll("path")
      .data(topojson.object(topology, topology.objects.countries)
          .geometries)
    .enter()
      .append("path")
      .attr("d", path)
});

// zoom and pan
var zoom = d3.behavior.zoom()
    .on("zoom",function() {
        g.attr("transform","translate("+ 
            d3.event.translate.join(",")+")scale("+d3.event.scale+")");
        g.selectAll("circle")
            .attr("d", path.projection(projection));
        g.selectAll("path")  
            .attr("d", path.projection(projection)); 

  });

svg.call(zoom)