In the previous episode I used D3 to make a simple graph, without using any tooling. Let's do a more modern take.
Create a new app
There's a lot of different bundlers, and most of them require some painful configuration.
Let's try parcel
this time, as it promises to just work out of the box.
$ npm init -y
$ npm install d3 parcel
It doesn't quite do what it promises, but it's still a lot less configuration that webpack or rollup.
Parcel configuration for GitHub Pages
The first issue with Parcel is that it outputs everything with absolute path, so your app will only work if you host it on top level of a domain.
Which is not how GitHub Pages are setup, and is overall a terrible default. The default should be relative paths, so it can be served anywhere. To make it work, we need to passs --public-url .
to parcel
.
package.json
We need to change two things. Set source
entry with our entrypoint. And tell Parcel that we want relative URLs, so it works with GitHub Pages.
{
"name": "episode-30",
"version": "1.0.0",
"description": "",
"scripts": {
"parcel:build": "parcel build --public-url ."
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"d3": "^7.4.2",
"parcel": "^2.4.1"
},
"source": "src/index.html"
}
That's almost the end of our Parcel issues.
src/index.html
Here we can reduce two scripts to one. We need to add type="module"
annotation to make it work.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="app.css">
</head>
<body>
<h1>Russian Tank Losses</h1>
<script src="app.js" type="module"></script>
</body>
</html>
src/app.css
Unchanged from previous version.
body {
margin: 0;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
src/app.js
And one more Parcel issue. By default it won't copy static assets like our .csv
files to the build directory. There are many solutions to this - the way we'll be using it, is by importing url:
of the asset we want.
Overall, only three lines changed from previous episode's version.
First we need to import d3 with import * as d3 from "d3"
. We could also just import specific functions like import {csv, scaleLinear, scaleTime, extent, select, axisBottom, axisLeft, line} from d3
, but D3 API really wasn't created for it, and I wouldn't recommend it.
Second we need to inform Parcel that our csv
needs bundling. csvUrl
will become the Parcel-bundled URL, with appropriate hash. This isn't the only way to do assets, but it works well enough.
And then we need to use that csvUrl
with let data = await d3.csv(csvUrl, parseRow)
.
Nothing else needed changing.
import * as d3 from "d3"
import csvUrl from 'url:./russia_losses_equipment.csv'
let parseRow = ({date,tank}) => ({date: new Date(date), tank: +tank})
let main = async () => {
let data = await d3.csv(csvUrl, parseRow)
data.unshift({date: new Date("2022-02-24"), tank: 0})
let xScale = d3.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, 600])
let yScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.tank))
.range([400, 0])
let svg = d3.select("body")
.append("svg")
.attr("width", 800)
.attr("height", 600)
.append("g")
.attr("transform", "translate(100, 100)")
svg.append("g")
.call(d3.axisLeft(yScale))
svg.append("g")
.attr("transform", "translate(0, 400)")
.call(d3.axisBottom(xScale))
svg.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 1.5)
.attr("d", d3.line()
.x(d => xScale(d.date))
.y(d => yScale(d.tank)))
}
main()
Should you use Parcel?
Parcel didn't quite do zero-config bundling, and there are some annoying things, like it's impossible to turn off hashing (--no-content-hash
just replaces content hashes with static hashes), but that's still a big improvement over other JavaScript bundlers.
If you use a framework like Svelte or React, you already have a bundler setup, so you should probably just use that. But if you don't, Parcel might be the best low-config solution right now.
Story so far
I deployed this on GitHub Pages, you can see it here.
Coming next
In the next episode, we'll port this app to Svelte. And after that we'll try to figure out how long until Russia runs out of tanks.
Top comments (0)