هلالtonight’s moonشمسةthe sixteen-petal rosette — how it is drawn

The observatory

Tonight’s moonهلال

Next new moon
—
Next full moon
—

The first thin crescent — هلال, the hilal — is the moon a day or two out of conjunction, and it is a beginning. The Hijri calendar is lunar: twelve months of twenty-nine or thirty days, a year some eleven days shorter than the solar one, so its months walk backwards through the seasons. A month opens when the new crescent is seen — and the naked-eye hilal is a hard object, thin and low and lost in the dusk it hangs in, which is why what counts as seeing it has been argued over for centuries.

That is one reason the astronomers of the medieval Islamic world measured the moon as closely as they did. Al-Battani, who spent most of his life at Raqqa and died in 929, left the earliest surviving zīj — a book of astronomical tables — in the Ptolemaic tradition, and tables like it could place the crescent before anyone went out to look for it. The disc above is worked the same way: everything on it follows from ψ, the angle between sun and moon, which fixes both the phase and the lit fraction, (1 − cos ψ) ⁄ 2.

The observatory

The sixteen-petal rosetteشمسة

the compass circle · sixteen points

Everything here is stepped off one circle. Sixteen points around it, each joined to the sixth from it; the {16/6} star polygon that follows then supplies its own measurements — the petal valleys at 0.689 R where consecutive chords meet, the ring at 0.390 R where they cross closest to the centre. Nothing is chosen by eye.

Patterns built on that kind of scaffolding are girih, the interlaced strapwork behind much of Islamic geometric ornament; cut from glazed terracotta and set piece by hand-chiselled piece, the same figures become zellij, the mosaic of Morocco and al-Andalus this page is named for. What craftsmen carried between sites was the construction rather than the finished design: the Topkapı Scroll, 114 patterns from the Timurid workshops, is the one pattern-book of its kind to survive. The eight-pointed star this rosette closes on is the khatam — two squares laid across each other, the octagram the Qur’an uses in its margins as the Rub el Hizb.

Ahmed El Gabri

أحمد الجابري

Two-centred drop arch — the Mosque of Ibn Tulun, Cairo, 876–879

Blog

Analyzing & optimizing your webpack bundle

One of the problems I noticed with many developers that when they use a module bundler like Webpack, Browserify, etc… they tend to think that it will automagically handle optimization for them just by enabling & using all the optimization plugins available in the tool.

But that’s not true, while these bundlers plus their plugins & optmization settings can handle nearly 90% of the this issue, you still need to handle the rest yourself or at least measure & check every once in a while what your bundle looks like. So I’ll show you a couple of things you can do with Webpack to optimize your bundle even more.

I’ll cover how to analyze your bundle & remove things you don’t need (you might even not be aware of some stuff, more on that latter)

So let’s start…

Analyzing your Webpack bundle

I have a very simple react app here, you just type in the input field & it will slugify the output of what you typed.

That’s the code for the app, pretty normal stuff nothing fancy here.

App.js
import React, {Component} from 'react'
import {render} from 'react-dom'
import slug from 'slug'

const Input = ({onChange}) => <input type="text" onChange={onChange} />

class App extends Component {
	constructor(props) {
		super(props)

		this.state = {
			text: '',
		}

		this.handleEvent = this.handleEvent.bind(this)
	}

	handleEvent(e) {
		this.setState({text: e.target.value.trim()})
	}

	render() {
		return (
			<div>
				<Input onChange={this.handleEvent} />
				<p>{slug(this.state.text) || 'Start typing...'}</p>
			</div>
		)
	}
}

render(<App />, document.querySelector('#App'))

So, you run it through Webpack & eveything is fine, right? It compiles, works & everyone is happy. But look at this output from Webpack.

The bundle size is 1.84mb! And there is this file called So.js which is 1.91mb alone, and it’s coming from a folder called unicode/category. How can we get more info about this?

You have a couple of options here:

  1. Open node_modules & grep, find or even manually to try & find where is that unicode folder is.
  2. Use Webpack’s powerful CLI flags to get more data & information about your bundle.

I’ll go with the second option, so I’ll add this script to my package.json so I can run the command easily

package.json
{
	"name": "webpack-analyze",
	"version": "1.0.0",
	"description": "",
	"main": "index.js",
	"scripts": {
		"build": "NODE_ENV=production webpack",
		"debug": "npm run build -- --progress --colors --profile --display-modules --display-reasons --display-error-details"
	},
	"license": "MIT",
	"dependencies": {
		"babel-core": "6.22.1",
		"babel-loader": "6.2.10",
		"babel-preset-es2015": "6.22.0",
		"babel-preset-react": "6.22.0",
		"react": "15.4.2",
		"react-dom": "15.4.2",
		"slug": "0.9.1",
		"slugify": "1.1.0",
		"webpack": "2.2.0"
	}
}

Tip: you can reuse npm run scripts in other npm scripts & pass flags to them by adding -- between the command & the flags. Like in the debug script here.

This npm run debug will simply reveal more info about the bundle & modules that will allow us to narrow down what is the problem exactly. I recommend to read more about the Webpack CLI to get an idea on what else you can do. So after running npm run debug you will get something like this (it’s too big to put it all in the post so this is just the part that we are interested in)

So now we know that So.js is related to the slug module, great. So it turns out that the slug module, has a postinstall hook that creates some unicode files to handle different languages & So.js is one of them & it holds mainly Arabic & Tibetan unicode symbols.

Another solution to check your bundle which can actually help you even, is using something like webpack-bundle-analyzer. Because it visualizes the size of your dependency tree using tree maps, it should look like this.

So, the perfect scenario you would use a different module other than slug, but let’s assume that you can replace this right now for whatever reason (time, overhead, etc…) you still don’t want to serve these ~2mb for your users. So how can you do this?

Turns out that solutions was pretty simple, you can use Webpack’s IgnorePlugin to tell Webpack to ignore this file from the bundle.

webapck.config.js
plugins: [
	// ignore the So.js unicode table file (mainly it contains Arabic & tibitan unicode data)
	new webpack.IgnorePlugin(/unicode\/category\/So/, /node_modules/),
]

And here is the output after that change, the bundle is only 150KB now.

Congratulations, you have just removed ~2mb from your bundle 🎉

While following best practices when setting up Webpack can go a long way for optimizing your bundle, you still need to monitor it for any sudden size increase and/or audit it every once in a while to make sure things like this doesn’t happen.

If you want to play with the code it’s on Github

You can share this post or reach me on @ahmedelgabri.